diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/CREDITS linux-2.4.27-rc4/CREDITS
--- linux-2.4.26/CREDITS	2004-04-14 13:05:21.000000000 +0000
+++ linux-2.4.27-rc4/CREDITS	2004-07-30 16:29:55.000000000 +0000
@@ -1232,8 +1232,8 @@ P: 1024D/77D4FC9B F5C5 1C20 1DFC DEC3 31
 D: National Language Support
 D: Linux Internationalization Project
 D: German Localization for Linux and GNU software
-S: Helenenstrasse 18
-S: 65183 Wiesbaden
+S: Kriemhildring 12a
+S: 65795 Hattersheim am Main
 S: Germany
 
 N: Christoph Hellwig
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/CodingStyle linux-2.4.27-rc4/Documentation/CodingStyle
--- linux-2.4.26/Documentation/CodingStyle	2001-09-09 23:40:43.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/CodingStyle	2004-07-30 16:27:15.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 reading 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 [cC]onfig.in, 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
-that 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.
 
-		Chapter 5: Commenting
+The goto statement comes in handy when a function exits from multiple
+locations and some common work such as cleanup has to be done.
+
+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 - a infinite number of monkeys typing into GNU emacs would never
-make a good program). 
+typing - an infinite number of monkeys typing into GNU emacs would never
+make a good program).
 
 So, you can either get rid of GNU emacs, or change it to use saner
 values.  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.
@@ -200,19 +270,20 @@ automagically when you edit source files
 But even if you fail in getting emacs to do sane formatting, not
 everything is lost: use "indent".
 
-Now, again, GNU indent has the same brain dead settings that GNU emacs
-has, which is why you need to give it a few command line options. 
+Now, again, GNU indent has the same brain-dead settings that GNU emacs
+has, which is why you need to give it a few command line options.
 However, that's not too bad, because even the makers of GNU indent
 recognize the authority of K&R (the GNU people aren't evil, they are
 just severely misguided in this matter), so you just give indent the
-options "-kr -i8" (stands for "K&R, 8 character indents"). 
+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),
 somewhat different indentation is used.
@@ -235,20 +306,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.
@@ -258,9 +329,99 @@ when there are users of different "class
 the number of subclass users, and decrements the global count just once
 when the subclass count goes to zero.
 
-Examples of this kind of "multi-reference-counting" can be found in
+Examples of this kind of "multi-level-reference-counting" can be found in
 memory management ("struct mm_struct": mm_users and mm_count), and in
 filesystem code ("struct super_block": s_count and s_active).
 
 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 March 2004 by a community effort on LKML.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/Configure.help linux-2.4.27-rc4/Documentation/Configure.help
--- linux-2.4.26/Documentation/Configure.help	2004-04-14 13:05:24.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/Configure.help	2004-07-30 16:31:28.648655536 +0000
@@ -569,6 +569,19 @@ CONFIG_BLK_DEV_UMEM
   The umem driver has been allocated block major number 116.
   See Documentation/devices.txt for recommended device naming.
 
+Promise SATA SX8 support
+CONFIG_BLK_DEV_SX8
+   Saying Y or M here will enable support for the 
+   Promise SATA SX8 controllers.
+
+  If you want to compile this driver as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called sx8.o.
+
+  The sx8 driver has been allocated block major numbers 160, 161.
+  See Documentation/devices.txt for recommended device naming.
+
 Network block device support
 CONFIG_BLK_DEV_NBD
   Saying Y here will allow your computer to be a client for network
@@ -1296,11 +1309,13 @@ CONFIG_PIIX_TUNING
 
   If unsure, say N.
 
-PROMISE PDC20246/PDC20262/PDC20265/PDC20267/PDC20268 support
+Promise PDC202{46|62|65|67} support
 CONFIG_BLK_DEV_PDC202XX_OLD
-  Promise Ultra33 or PDC20246
-  Promise Ultra66 or PDC20262
-  Promise Ultra100 or PDC20265/PDC20267/PDC20268
+  Promise Ultra 33 [PDC20246]
+  Promise Ultra 66 [PDC20262]
+  Promise FastTrak 66 [PDC20263]
+  Promise MB Ultra 100 [PDC20265]
+  Promise Ultra 100 [PDC20267]
 
   This driver adds up to 4 more EIDE devices sharing a single
   interrupt. This add-on card is a bootable PCI UDMA controller. Since
@@ -1309,7 +1324,7 @@ CONFIG_BLK_DEV_PDC202XX_OLD
   not match, the driver attempts to do dynamic tuning of the chipset
   at boot-time for max-speed.  Ultra33 BIOS 1.25 or newer is required
   for more than one card. This card may require that you say Y to
-  "Special UDMA Feature".
+  "Force (U)DMA burst transfers" (old name: "Special UDMA Feature").
 
   If you say Y here, you need to say Y to "Use DMA by default when
   available" as well.
@@ -1319,7 +1334,7 @@ CONFIG_BLK_DEV_PDC202XX_OLD
 
   If unsure, say N.
 
-PROMISE PDC202{68|69|70|71|75|76|77} support
+Promise PDC202{68|69|70|71|75|76|77} support
 CONFIG_BLK_DEV_PDC202XX_NEW
   Promise Ultra 100 TX2 [PDC20268]
   Promise Ultra 133 PTX2 [PDC20269]
@@ -1334,17 +1349,16 @@ CONFIG_BLK_DEV_PDC202XX_NEW
   multiple cards can be installed and there are BIOS ROM problems that
   happen if the BIOS revisions of all installed cards (max of five) do
   not match, the driver attempts to do dynamic tuning of the chipset
-  at boot-time for max speed.  Ultra33 BIOS 1.25 or newer is required
-  for more than one card.
+  at boot-time for max speed.
 
   If you say Y here, you need to say Y to "Use DMA by default when
   available" as well.
 
   If unsure, say N.
 
-Special UDMA Feature
+Force (U)DMA burst transfers
 CONFIG_PDC202XX_BURST
-  This option causes the pdc202xx driver to enable UDMA modes on the
+  This option causes the pdc202xx_old driver to enable UDMA modes on the
   PDC202xx even when the PDC202xx BIOS has not done so.
 
   It was originally designed for the PDC20246/Ultra33, whose BIOS will
@@ -1357,9 +1371,17 @@ CONFIG_PDC202XX_BURST
 
   If unsure, say N.
 
-Special FastTrak Feature
+Ignore BIOS port disabled setting on FastTrak
 CONFIG_PDC202XX_FORCE
-  For FastTrak enable overriding BIOS.
+  Chipsets affected:
+
+  PDC202{46|62|63|65|67}
+  (pdc202xx_old driver)
+
+  PDC202{70|76}
+  (pdc202xx_new driver)
+
+  Say Y unless you want to use Promise proprietary driver.
 
 SiS5513 chipset support
 CONFIG_BLK_DEV_SIS5513
@@ -4286,6 +4308,46 @@ CONFIG_HOTPLUG_PCI_ACPI
   inserted in and removed from the running kernel whenever you want).
   The module will be called acpiphp.o. If you want to compile it
   as a module, say M here and read <file:Documentation/modules.txt>.
+ 
+CONFIG_HOTPLUG_PCI_SHPC
+  Say Y here if you have a motherboard with a SHPC PCI Hotplug
+  controller.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called shpchp.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+  When in doubt, say N.
+
+CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE
+  Say Y here if you want to use the polling mechanism for hot-plug 
+  events for early platform testing.
+
+  When in doubt, say N.
+
+CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
+  Say Y here for AMD SHPC. You have to select this option if you are 
+  using this driver on platform with AMD SHPC.
+
+  When in doubt, say N.
+
+CONFIG_HOTPLUG_PCI_PCIE
+  Say Y here if you have a motherboard that supports PCI Express Native
+  Hotplug
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called pciehp.o. If you want to compile it
+  as a module, say M here and read <file:Documentation/modules.txt>.
+
+  When in doubt, say N.
+
+CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
+  Say Y here if you want to use the polling mechanism for hot-plug 
+  events for early platform testing.
+
+  When in doubt, say N.
 
 MCA support
 CONFIG_MCA
@@ -5543,14 +5605,15 @@ CONFIG_FB_SIS
 SIS 300 series support
 CONFIG_FB_SIS_300
   This enables support for SiS 300 series chipsets (300/305, 540, 630,
-  730).  Documentation available at the maintainer's website at
-   <http://www.winischhofer.net/linuxsisvga.shtml>.
+  630S, 730S). Documentation available at the maintainer's website at
+  <http://www.winischhofer.net/linuxsisvga.shtml>.
 
 SIS 315/330 series support
 CONFIG_FB_SIS_315
-  This enables support for SiS 315/330 series chipsets (315, 550, 650,
-  M650, 651, 661FX, M661FX, 740, 741, 330). Documentation available at
-  the maintainer's site <http://www.winischhofer.net/linuxsisvga.shtml>.
+  This enables support for SiS 315/330 series chipsets (315, 315PRO, 
+  55x, (M)650, 651, (M)661FX, 661MX, 740, (M)741(GX), (M)760, 330).
+  Documentation available at the maintainer's website at
+  <http://www.winischhofer.net/linuxsisvga.shtml>.
 
 IMS Twin Turbo display support
 CONFIG_FB_IMSTT
@@ -6109,8 +6172,7 @@ CONFIG_NET_IPIP
   can be useful if you want to make your (or some other) machine
   appear on a different network than it physically is, or to use
   mobile-IP facilities (allowing laptops to seamlessly move between
-  networks without changing their IP addresses; check out
-  <http://anchor.cs.binghamton.edu/~mobileip/LJ/index.html>).
+  networks without changing their IP addresses).
 
   Saying Y to this option will produce two modules ( = code which can
   be inserted in and removed from the running kernel whenever you
@@ -7521,6 +7583,11 @@ CONFIG_ATM_FORE200E_SBA_FW
   not have to supply an alternative one. They just say Y to "Use
   default SBA-200E firmware", above.
 
+CONFIG_ATM_FORE200E_USE_TASKLET
+  This defers work to be done by the interrupt handler to a
+  tasklet instead of handling everything at interrupt time.  This
+  may improve the responsiveness of the host.
+
 Maximum number of tx retries
 CONFIG_ATM_FORE200E_TX_RETRY
   Specifies the number of times the driver attempts to transmit
@@ -9202,6 +9269,48 @@ CONFIG_SCSI_MEGARAID2
   say M here and read <file:Documentation/modules.txt>.  The module
   will be called megaraid2.o.
 
+CONFIG_SCSI_SATA
+  This driver family supports Serial ATA host controllers
+  and devices.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_SVW
+  This option enables support for Broadcom/Serverworks/Apple K2
+  SATA support.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_PROMISE
+  This option enables support for Promise Serial ATA TX2/TX4.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_SX4
+  This option enables support for Promise Serial ATA SX4.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_SIL
+  This option enables support for Silicon Image Serial ATA.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_SIS
+  This option enables support for SiS Serial ATA 964/180.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_VIA
+  This option enables support for VIA Serial ATA.
+
+  If unsure, say N.
+
+CONFIG_SCSI_SATA_VITESSE
+  This option enables support for Vitesse VSC7174 Serial ATA.
+
+  If unsure, say N.
+
 Intel/ICP (former GDT SCSI Disk Array) RAID Controller support
 CONFIG_SCSI_GDTH
   Formerly called GDT SCSI Disk Array Controller Support.
@@ -12101,6 +12210,20 @@ CONFIG_E1000
   module, say M here and read <file:Documentation/modules.txt> as well
   as <file:Documentation/networking/net-modules.txt>.
 
+CONFIG_E1000_NAPI
+  NAPI is a new driver API designed to reduce CPU and interrupt load
+  when the driver is receiving lots of packets from the card. It is
+  still somewhat experimental and thus not yet enabled by default.
+
+  If your estimated Rx load is 10kpps or more, or if the card will be
+  deployed on potentially unfriendly networks (e.g. in a firewall),
+  then say Y here.
+
+  See <file:Documentation/networking/NAPI_HOWTO.txt> for more
+  information.
+
+  If in doubt, say N.
+
 AMD LANCE and PCnet (AT1500 and NE2100) support
 CONFIG_LANCE
   If you have a network (Ethernet) card of this type, say Y and read
@@ -13407,6 +13530,16 @@ CONFIG_HIPPI
   under Linux, say Y here (you must also remember to enable the driver
   for your HIPPI card below). Most people will say N here.
 
+IBM PowerPC Virtual Ethernet driver support
+CONFIG_IBMVETH
+  This driver supports virtual ethernet adapters on newer IBM iSeries
+  and pSeries systems.
+
+  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 ibmveth.o.
+
 Essential RoadRunner HIPPI PCI adapter support
 CONFIG_ROADRUNNER
   Say Y here if this is your PCI HIPPI network card.
@@ -16093,6 +16226,27 @@ CONFIG_USB_ETH
    Say "y" to link the driver statically, or "m" to build a
    dynamically linked module called "g_ether".
 
+CONFIG_USB_ETH_RNDIS
+  Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+  and Microsoft provides redistributable binary RNDIS drivers for
+  older versions of Windows.
+
+  If you say "y" here, the Ethernet gadget driver will try to provide
+  a second device configuration, supporting RNDIS to talk to such
+  Microsoft USB hosts.
+
+CONFIG_USB_FILE_STORAGE
+  The File-backed Storage Gadget acts as a USB Mass Storage
+  disk drive.  As its storage repository it can use a regular
+  file or a block device (in much the same way as the "loop"
+  device driver), specified as a module parameter.
+
+CONFIG_USB_FILE_STORAGE_TEST
+  Say "y" to generate the larger testing version of the
+  File-backed Storage Gadget, useful for probing the
+  behavior of USB Mass Storage hosts.  Not needed for
+  normal operation.
+
 Always do synchronous disk IO for UBD
 CONFIG_BLK_DEV_UBD_SYNC
   The User-Mode Linux port includes a driver called UBD which will let
@@ -17269,7 +17423,7 @@ CONFIG_AUTOFS4_FS
   automounter (amd), which is a pure user space daemon.
 
   To use the automounter you need the user-space tools from
-  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
+  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/v4/>; you also
   want to answer Y to "NFS file system support", below.
 
   If you want to compile this as a module ( = code which can be
@@ -17427,13 +17581,10 @@ Tracing support (EXPERIMENTAL)
 CONFIG_XFS_TRACE
   Say Y here to get an XFS build with activity tracing enabled.
   Enabling this option will attach historical information to XFS
-  inodes, pagebufs, certain locks, the log, the IO path, and a
+  inodes, buffers, certain locks, the log, the IO path, and a
   few other key areas within XFS.  These traces can be examined
   using a kernel debugger.
 
-  Note that for the pagebuf traces, you will also have to enable
-  the sysctl in /proc/sys/vm/pagebuf/debug for this to work.
-
   Say N unless you are an XFS developer.
 
 Debugging support (EXPERIMENTAL)
@@ -23001,22 +23152,20 @@ CONFIG_BLUEZ
 
   Linux Bluetooth subsystem consist of several layers:
                BlueZ Core (HCI device and connection manager, scheduler)
-               HCI Device drivers (interface to the hardware)
-               L2CAP Module (L2CAP protocol)
-               SCO Module (SCO links)
-               RFCOMM Module (RFCOMM protocol)
-               BNEP Module (BNEP protocol)
-               CMTP Module (CMTP protocol)
+               HCI Device drivers (Interface to the hardware)
+               SCO Module (SCO audio links)
+               L2CAP Module (Logical Link Control and Adaptation Protocol)
+               RFCOMM Module (RFCOMM Protocol)
+               BNEP Module (Bluetooth Network Encapsulation Protocol)
+               CMTP Module (CAPI Message Transport Protocol)
 
-  Say Y here to enable Linux Bluetooth support and to build BlueZ Core
-  layer.
+  Say Y here to compile Bluetooth support into the kernel or say M to
+  compile it as module (bluez.o).
 
   To use Linux Bluetooth subsystem, you will need several user-space
   utilities like hciconfig and hcid.  These utilities and updates to
   Bluetooth kernel modules are provided in the BlueZ package.
-  For more information, see <http://bluez.sourceforge.net/>.
-
-  If you want to compile BlueZ Core as module (bluez.o) say M here.
+  For more information, see <http://www.bluez.org/>.
 
 L2CAP protocol support
 CONFIG_BLUEZ_L2CAP
@@ -23029,7 +23178,7 @@ CONFIG_BLUEZ_L2CAP
 
 SCO links support
 CONFIG_BLUEZ_SCO
-  SCO link provides voice transport over Bluetooth. SCO support is
+  SCO link provides voice transport over Bluetooth.  SCO support is
   required for voice applications like Headset and Audio.
 
   Say Y here to compile SCO support into the kernel or say M to
@@ -23037,7 +23186,7 @@ CONFIG_BLUEZ_SCO
 
 RFCOMM protocol support
 CONFIG_BLUEZ_RFCOMM
-  RFCOMM provides connection oriented stream transport. RFCOMM
+  RFCOMM provides connection oriented stream transport.  RFCOMM
   support is required for Dialup Networking, OBEX and other Bluetooth
   applications.
 
@@ -23051,25 +23200,12 @@ CONFIG_BLUEZ_RFCOMM_TTY
 BNEP protocol support
 CONFIG_BLUEZ_BNEP
   BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
-  emulation layer on top of Bluetooth. BNEP is required for Bluetooth
-  PAN (Personal Area Network).
-
-  To use BNEP, you will need user-space utilities provided in the 
-  BlueZ-PAN package.
-  For more information, see <http://bluez.sourceforge.net>.
+  emulation layer on top of Bluetooth.  BNEP is required for
+  Bluetooth PAN (Personal Area Network).
 
   Say Y here to compile BNEP support into the kernel or say M to
   compile it as module (bnep.o).
 
-CMTP protocol support
-CONFIG_BLUEZ_CMTP
-  CMTP (CAPI Message Transport Protocol) is a transport layer
-  for CAPI messages. CMTP is required for the Bluetooth Common
-  ISDN Access Profile.
-
-  Say Y here to compile CMTP support into the kernel or say M to
-  compile it as module (cmtp.o).
-
 BNEP multicast filter support
 CONFIG_BLUEZ_BNEP_MC_FILTER
   This option enables the multicast filter support for BNEP.
@@ -23078,6 +23214,15 @@ BNEP protocol filter support
 CONFIG_BLUEZ_BNEP_PROTO_FILTER
   This option enables the protocol filter support for BNEP.
 
+CMTP protocol support
+CONFIG_BLUEZ_CMTP
+  CMTP (CAPI Message Transport Protocol) is a transport layer
+  for CAPI messages.  CMTP is required for the Bluetooth Common
+  ISDN Access Profile.
+
+  Say Y here to compile CMTP support into the kernel or say M to
+  compile it as module (cmtp.o).
+
 HCI UART driver
 CONFIG_BLUEZ_HCIUART
   Bluetooth HCI UART driver.
@@ -23167,9 +23312,6 @@ CONFIG_BLUEZ_HCIBT3C
      3Com Bluetooth Card (3CRWB6096)
      HP Bluetooth Card
 
-  The HCI BT3C driver uses external firmware loader program provided in
-  the BlueFW package. For more information, see <http://bluez.sf.net>.
-
   Say Y here to compile support for HCI BT3C devices into the
   kernel or say M to compile it as module (bt3c_cs.o).
 
@@ -28781,12 +28923,24 @@ CONFIG_CRYPTO_CAST6
   The CAST6 encryption algorithm (synonymous with CAST-256) is
   described in RFC2612.
 
+CONFIG_CRYPTO_TEA
+  TEA cipher algorithm.
+
+  Tiny Encryption Algorithm is a simple cipher that uses
+  many rounds for security.  It is very fast and uses
+  little memory.
+
+  Xtendend Tiny Encryption Algorithm is a modifcation to
+  the TEA algorithm to address a potential key weakness
+  in the TEA algorithm.
+
 CONFIG_CRYPTO_ARC4
   ARC4 cipher algorithm.
   
-  This is a stream cipher using keys ranging from 8 bits to 2048
-  bits in length.  ARC4 is commonly used in protocols such as WEP 
-  and SSL.
+  ARC4 is a stream cipher using keys ranging from 8 bits to 2048
+  bits in length.  This algorithm is required for driver-based 
+  WEP, but it should not be for other purposes because of the
+  weakness of the algorithm.
 
 CONFIG_CRYPTO_DEFLATE
   This is the Deflate algorithm (RFC1951), specified for use in
@@ -28794,6 +28948,12 @@ CONFIG_CRYPTO_DEFLATE
 
   You will most probably want this if using IPSec.
 
+CONFIG_CRYPTO_MICHAEL_MIC
+  Michael MIC is used for message integrity protection in TKIP
+  (IEEE 802.11i). This algorithm is required for TKIP, but it
+  should not be used for other purposes because of the weakness
+  of the algorithm.
+
 CONFIG_CRYPTO_TEST
   Quick & dirty crypto test module.
   
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/DocBook/Makefile linux-2.4.27-rc4/Documentation/DocBook/Makefile
--- linux-2.4.26/Documentation/DocBook/Makefile	2002-11-28 23:53:08.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/DocBook/Makefile	2004-07-30 16:28:28.000000000 +0000
@@ -2,7 +2,7 @@ BOOKS	:= wanbook.sgml z8530book.sgml mca
 	   kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
 	   kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
 	   deviceiobook.sgml procfs-guide.sgml tulip-user.sgml \
-	   journal-api.sgml
+	   journal-api.sgml libata.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -79,6 +79,16 @@ mcabook.sgml: mcabook.tmpl $(TOPDIR)/arc
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/arch/i386/kernel/mca.c \
 		<mcabook.tmpl >mcabook.sgml
 
+libata.sgml: libata.tmpl $(TOPDIR)/drivers/scsi/libata-core.c \
+		$(TOPDIR)/drivers/scsi/libata-scsi.c	\
+		$(TOPDIR)/drivers/scsi/sata_sil.c	\
+		$(TOPDIR)/drivers/scsi/sata_via.c
+	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/scsi/libata-core.c \
+		$(TOPDIR)/drivers/scsi/libata-scsi.c	\
+		$(TOPDIR)/drivers/scsi/sata_sil.c	\
+		$(TOPDIR)/drivers/scsi/sata_via.c	\
+		< libata.tmpl > libata.sgml
+
 videobook.sgml: videobook.tmpl $(TOPDIR)/drivers/media/video/videodev.c
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/media/video/videodev.c \
 		<videobook.tmpl >videobook.sgml
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/DocBook/libata.tmpl linux-2.4.27-rc4/Documentation/DocBook/libata.tmpl
--- linux-2.4.26/Documentation/DocBook/libata.tmpl	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/DocBook/libata.tmpl	2004-07-30 16:27:26.000000000 +0000
@@ -0,0 +1,85 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+
+<book id="libataDevGuide">
+ <bookinfo>
+  <title>libATA Developer's Guide</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Jeff</firstname>
+    <surname>Garzik</surname>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2003</year>
+   <holder>Jeff Garzik</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+   The contents of this file are subject to the Open
+   Software License version 1.1 that can be found at
+   <ulink url="http://www.opensource.org/licenses/osl-1.1.txt">http://www.opensource.org/licenses/osl-1.1.txt</ulink> and is included herein
+   by reference.
+   </para>
+
+   <para>
+   Alternatively, the contents of this file may be used under the terms
+   of the GNU General Public License version 2 (the "GPL") as distributed
+   in the kernel source COPYING file, in which case the provisions of
+   the GPL are applicable instead of the above.  If you wish to allow
+   the use of your version of this file only under the terms of the
+   GPL and not to allow others to use your version of this file under
+   the OSL, indicate your decision by deleting the provisions above and
+   replace them with the notice and other provisions required by the GPL.
+   If you do not delete the provisions above, a recipient may use your
+   version of this file under either the OSL or the GPL.
+   </para>
+
+  </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+  <chapter id="libataThanks">
+     <title>Thanks</title>
+  <para>
+  The bulk of the ATA knowledge comes thanks to long conversations with
+  Andre Hedrick (www.linux-ide.org).
+  </para>
+  <para>
+  Thanks to Alan Cox for pointing out similarities 
+  between SATA and SCSI, and in general for motivation to hack on
+  libata.
+  </para>
+  <para>
+  libata's device detection
+  method, ata_pio_devchk, and in general all the early probing was
+  based on extensive study of Hale Landis's probe/reset code in his
+  ATADRVR driver (www.ata-atapi.com).
+  </para>
+  </chapter>
+
+  <chapter id="libataExt">
+     <title>libata Library</title>
+!Edrivers/scsi/libata-core.c
+  </chapter>
+
+  <chapter id="libataInt">
+     <title>libata Core Internals</title>
+!Idrivers/scsi/libata-core.c
+  </chapter>
+
+  <chapter id="libataScsiInt">
+     <title>libata SCSI translation/emulation</title>
+!Edrivers/scsi/libata-scsi.c
+!Idrivers/scsi/libata-scsi.c
+  </chapter>
+
+  <chapter id="SILInt">
+     <title>ata_sil Internals</title>
+!Idrivers/scsi/sata_sil.c
+  </chapter>
+
+</book>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/cciss.txt linux-2.4.27-rc4/Documentation/cciss.txt
--- linux-2.4.26/Documentation/cciss.txt	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/cciss.txt	2004-07-30 16:25:50.000000000 +0000
@@ -14,6 +14,8 @@ This driver is known to work with the fo
 	* SA 6400
 	* SA 6400 U320 Expansion Module
 	* SA 6i
+	* SA 6422
+	* SA V100
 
 If nodes are not already created in the /dev/cciss directory
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/crypto/api-intro.txt linux-2.4.27-rc4/Documentation/crypto/api-intro.txt
--- linux-2.4.26/Documentation/crypto/api-intro.txt	2004-04-14 13:05:24.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/crypto/api-intro.txt	2004-07-30 16:32:06.584888352 +0000
@@ -187,6 +187,7 @@ Original developers of the crypto algori
   Brian Gladman (AES)
   Kartikey Mahendra Bhatt (CAST6)
   Jon Oberheide (ARC4)
+  Jouni Malinen (Michael MIC)
 
 SHA1 algorithm contributors:
   Jean-Francois Dive
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/filesystems/hpfs.txt linux-2.4.27-rc4/Documentation/filesystems/hpfs.txt
--- linux-2.4.26/Documentation/filesystems/hpfs.txt	2001-06-12 02:15:27.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/filesystems/hpfs.txt	2004-07-30 16:27:30.000000000 +0000
@@ -1,5 +1,5 @@
-Read/Write HPFS 2.05
-1998-2001, Mikulas Patocka
+Read/Write HPFS 2.09
+1998-2004, Mikulas Patocka
 
 email: mikulas@artax.karlin.mff.cuni.cz
 homepage: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
@@ -283,6 +283,14 @@ History
 2.05 Fixed crash when got mount parameters without =
      Fixed crash when allocation of anode failed due to full disk
      Fixed some crashes when block io or inode allocation failed
+2.06 Fixed some crash on corrupted disk structures
+     Better allocation strategy
+     Reschedule points added so that it doesn't lock CPU long time
+     It should work in read-only mode on Warp Server
+2.07 More fixes for Warp Server. Now it really works
+2.08 Creating new files is not so slow on large disks
+     An attempt to sync deleted file does not generate filesystem error
+2.09 Fixed error on extremly fragmented files
 
 
  vim: set textwidth=80:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/filesystems/xfs.txt linux-2.4.27-rc4/Documentation/filesystems/xfs.txt
--- linux-2.4.26/Documentation/filesystems/xfs.txt	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/filesystems/xfs.txt	2004-07-30 16:26:24.000000000 +0000
@@ -123,9 +123,15 @@ The following sysctls are available for 
 	in /proc/fs/xfs/stat.  It then immediately reset to "0".
   	
   fs.xfs.sync_interval		(Min: HZ  Default: 30*HZ  Max: 60*HZ)
-	The interval at which the xfssyncd thread for xfs filesystems
-	flushes metadata out to disk. This thread will flush log
-	activity out, and do some processing on unlinked inodes
+	The interval at which the xfssyncd thread flushes metadata
+	out to disk.  This thread will flush log activity out, and
+	do some processing on unlinked inodes.
+
+  fs.xfs.age_buffer             (Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
+	The age at which xfsbufd flushes dirty metadata buffers to disk.
+
+  fs.xfs.flush_interval         (Min: HZ/2  Default: HZ  Max: 30*HZ)
+	The interval at which xfsbufd scans the dirty metadata buffers list.
 
   fs.xfs.error_level		(Min: 0  Default: 3  Max: 11)
 	A volume knob for error reporting when internal errors occur.
@@ -190,14 +196,3 @@ The following sysctls are available for 
 	Setting this to "1" will cause the "noatime" flag set 
 	by the chattr(1) command on a directory to be
 	inherited by files in that directory.
-
-  vm.pagebuf.stats_clear	(Min: 0  Default: 0  Max: 1)
-	Setting this to "1" clears accumulated pagebuf statistics 
-	in /proc/fs/pagebuf/stat.  It then immediately reset to "0".
-  	
-  vm.pagebuf.flush_age		(Min: 1*HZ  Default: 15*HZ  Max: 300*HZ)
-	The age at which dirty metadata buffers are flushed to disk
-
-  vm.pagebuf.flush_int		(Min: HZ/2  Default: HZ  Max: 30*HZ)
-	The interval at which the list of dirty metadata buffers is
-	scanned.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/ioctl-number.txt linux-2.4.27-rc4/Documentation/ioctl-number.txt
--- linux-2.4.26/Documentation/ioctl-number.txt	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/ioctl-number.txt	2004-07-30 16:31:37.392326296 +0000
@@ -183,5 +183,6 @@ 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>
-
+0xF3    00-3F   linux/sisfb.h 		SiS framebuffer device driver
+					<mailto:thomas@winischhofer.net>
 0xFE	00-9F	Logical Volume Manager	<mailto:linux-lvm@sistina.com>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/kernel-parameters.txt linux-2.4.27-rc4/Documentation/kernel-parameters.txt
--- linux-2.4.26/Documentation/kernel-parameters.txt	2004-04-14 13:05:24.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/kernel-parameters.txt	2004-07-30 16:32:20.003848360 +0000
@@ -69,8 +69,9 @@ running once the system is up.
 	53c7xx=		[HW,SCSI] Amiga SCSI controllers.
 
 	acpi=		[HW,ACPI] Advanced Configuration and Power Interface 
-		force	Force ACPI on, even if blacklisted platform
-		off	Disable ACPI
+		force	Enable ACPI if default was off
+		off	Disable ACPI if default was on
+		noirq	Do not use ACPI for IRQ routing (see pci=noacpi)
 		ht	Limit ACPI to boot-time LAPIC enumeration for HT,
 			disabling the run-time AML interpreter.
 		strict	Be less tolerant of platforms that are not
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/networking/bridge.txt linux-2.4.27-rc4/Documentation/networking/bridge.txt
--- linux-2.4.26/Documentation/networking/bridge.txt	2000-11-09 23:57:53.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/networking/bridge.txt	2004-07-30 16:29:28.000000000 +0000
@@ -1,11 +1,8 @@
-In order to use the ethernet bridging functionality you'll need the
-userspace tools available at http://www.math.leidenuniv.nl/~buytenh/bridge.
-The tarball available there contains extensive documentation, but if you
-still have questions, don't hesitate to post to the mailing list (more info
-at http://www.math.leidenuniv.nl/mailman/listinfo/bridge). You can also
-mail me at buytenh@gnu.org.
+In order to use the Ethernet bridging functionality, you'll need the
+userspace tools. These programs and documentation are available
+at http://bridge.sourceforge.net.  The download page is
+http://prdownloads.sourceforge.net/bridge.
 
+If you still have questions, don't hesitate to post to the mailing list 
+(more info http://lists.osdl.org/mailman/listinfo/bridge).
 
-
-Lennert Buytenhek
-<buytenh@gnu.org>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/networking/ip-sysctl.txt linux-2.4.27-rc4/Documentation/networking/ip-sysctl.txt
--- linux-2.4.26/Documentation/networking/ip-sysctl.txt	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/networking/ip-sysctl.txt	2004-07-30 16:27:53.000000000 +0000
@@ -289,6 +289,44 @@ tcp_low_latency - BOOLEAN
 	changed would be a Beowulf compute cluster.
 	Default: 0
 
+tcp_vegas_cong_avoid - BOOLEAN
+	Enable TCP Vegas congestion avoidance algorithm.
+	TCP Vegas is a sender-side only change to TCP that anticipates
+	the onset of congestion by estimating the bandwidth. TCP Vegas
+	adjusts the sending rate by modifying the congestion
+	window. TCP Vegas should provide less packet loss, but it is
+	not as aggressive as TCP Reno.
+	Default:0
+
+tcp_bic - BOOLEAN
+	Enable BIC TCP congestion control algorithm.
+	BIC-TCP is a sender-side only change that ensures a linear RTT
+	fairness under large windows while offering both scalability and
+	bounded TCP-friendliness. The protocol combines two schemes
+	called additive increase and binary search increase. When the
+	congestion window is large, additive increase with a large
+	increment ensures linear RTT fairness as well as good
+	scalability. Under small congestion windows, binary search
+	increase provides TCP friendliness.
+	Default: 0
+
+tcp_bic_low_window - INTEGER
+	Sets the threshold window (in packets) where BIC TCP starts to
+	adjust the congestion window. Below this threshold BIC TCP behaves
+	the same as the default TCP Reno. 
+	Default: 14
+
+tcp_bic_fast_convergence - BOOLEAN
+	Forces BIC TCP to more quickly respond to changes in congestion
+	window. Allows two flows sharing the same connection to converge
+	more rapidly.
+	Default: 1
+
+tcp_default_win_scale - INTEGER
+	Sets the minimum window scale TCP will negotiate for on all
+	conections.
+	Default: 7
+
 ip_local_port_range - 2 INTEGERS
 	Defines the local port range that is used by TCP and UDP to
 	choose the local port. The first number is the first, the 
@@ -603,9 +641,11 @@ accept_redirects - BOOLEAN
 			    disabled if local forwarding is enabled.
 
 autoconf - BOOLEAN
-	Configure link-local addresses using L2 hardware addresses.
+	Autoconfigure addresses using Prefix Information in Router 
+	Advertisements.
 
-	Default: TRUE
+	Functional default: enabled if accept_ra is enabled.
+			    disabled if accept_ra is disabled.
 
 dad_transmits - INTEGER
 	The amount of Duplicate Address Detection probes to send.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/networking/packet_mmap.txt linux-2.4.27-rc4/Documentation/networking/packet_mmap.txt
--- linux-2.4.26/Documentation/networking/packet_mmap.txt	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/networking/packet_mmap.txt	2004-07-30 16:32:19.986850944 +0000
@@ -1,11 +1,3 @@
-
-DaveM:
-
-If you agree with it I will send two small patches to modify
-kernel's configure help. 
-
-	Ulisses
-
 --------------------------------------------------------------------------------
 + ABSTRACT
 --------------------------------------------------------------------------------
@@ -405,8 +397,3 @@ then poll for frames.
    
    Jesse Brandeburg, for fixing my grammathical/spelling errors
 
->>> EOF
--
-To unsubscribe from this list: send the line "unsubscribe linux-net" in
-the body of a message to majordomo@vger.kernel.org
-More majordomo info at  http://vger.kernel.org/majordomo-info.html
\ No newline at end of file
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Documentation/usb/silverlink.txt linux-2.4.27-rc4/Documentation/usb/silverlink.txt
--- linux-2.4.26/Documentation/usb/silverlink.txt	2002-11-28 23:53:08.000000000 +0000
+++ linux-2.4.27-rc4/Documentation/usb/silverlink.txt	2004-07-30 16:25:50.000000000 +0000
@@ -8,7 +8,7 @@ Homepage: http://lpg.ticalc.org/prj_usb
 INTRODUCTION:
 
 This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable 
-designed by TI for connecting their TI8x/9x calculators to a computer 
+designed by TI for connecting their TI8x/9x graphing handhelds to a computer 
 (PC or Mac usually).
 
 If you need more information, please visit the 'SilverLink drivers' homepage 
@@ -16,10 +16,8 @@ at the above URL.
 
 WHAT YOU NEED:
 
-A TI calculator of course and a program capable to communicate with your 
-calculator.
-TiLP will work for sure (since I am his developer !). yal92 may be able to use
-it by changing tidev for tiglusb (may require some hacking...).
+A TI calculator/handheld of course and a program capable to communicate with 
+your calculator. A good choice is TiLP (http://www.tilp.info).
 
 HOW TO USE IT:
 
@@ -58,14 +56,19 @@ MODULE PARAMETERS:
 QUIRKS:
 
 The following problem seems to be specific to the link cable since it appears 
-on all platforms (Linux, Windows, Mac OS-X). 
+on all platforms (Linux, Windows, Mac OS-X). A guy told me it was a common but
+weird behaviour with Cypress microcontrollers (it uses an CY7C64013).
 
-In some very particular cases, the driver returns with success but
+In some very particular cases, the driver returns with success (no error) but
 without any data. The application should retry a read operation at least once.
 
+This problem and the need to issue IOCTL_TIUSB_RESET_PIPES before doing any
+packet transfer (like TI's software do) make this driver difficult to use in 
+pure raw access.
+
 HOW TO CONTACT US:
 
-You can email me at roms@lpg.ticalc.org. Please prefix the subject line
+You can email me at roms@tilp.info. Please prefix the subject line
 with "TIGLUSB: " so that I am certain to notice your message.
 You can also mail JB at jb@jblache.org: he has written the first release of 
 this driver but he better knows the Mac OS-X driver.
@@ -73,4 +76,4 @@ this driver but he better knows the Mac 
 CREDITS:
 
 The code is based on dabusb.c, printer.c and scanner.c !
-The driver has been developed independantly of Texas Instruments.
+The driver has been developed without any support from Texas Instruments Inc.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/MAINTAINERS linux-2.4.27-rc4/MAINTAINERS
--- linux-2.4.26/MAINTAINERS	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/MAINTAINERS	2004-07-30 16:29:20.000000000 +0000
@@ -113,6 +113,12 @@ M:	jgarzik@pobox.com
 W:	http://sourceforge.net/projects/gkernel/
 S:	Maintained
 
+8169 10/100/1000 GIGABIT ETHERNET DRIVER
+P:	Francois Romieu
+M:	romieu@fr.zoreil.com
+L:	netdev@oss.sgi.com
+S:	Maintained
+
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
 P:	Theodore Ts'o
 M:	tytso@mit.edu
@@ -328,6 +334,8 @@ P:	Maxim Krasnyansky
 M:	maxk@qualcomm.com
 L:	bluez-devel@lists.sf.net
 W:	http://bluez.sf.net
+W:	http://www.bluez.org
+W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
 BLUETOOTH RFCOMM LAYER
@@ -335,7 +343,6 @@ P:	Marcel Holtmann
 M:	marcel@holtmann.org
 P:	Maxim Krasnyansky
 M:	maxk@qualcomm.com
-W:	http://bluez.sf.net
 S:	Maintained
 
 BLUETOOTH BNEP LAYER
@@ -343,65 +350,60 @@ P:	Marcel Holtmann
 M:	marcel@holtmann.org
 P:	Maxim Krasnyansky
 M:	maxk@qualcomm.com
-W:	http://bluez.sf.net
 S:	Maintained
 
 BLUETOOTH CMTP LAYER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
-W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
-BLUETOOTH HCI USB DRIVER
+BLUETOOTH HCI UART DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
 P:	Maxim Krasnyansky
 M:	maxk@qualcomm.com
-W:	http://bluez.sf.net
 S:	Maintained
 
-BLUETOOTH HCI UART DRIVER
+BLUETOOTH HCI USB DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
 P:	Maxim Krasnyansky
 M:	maxk@qualcomm.com
-W:	http://bluez.sf.net
+S:	Maintained
+
+BLUETOOTH HCI BCM203X DRIVER
+P:	Marcel Holtmann
+M:	marcel@holtmann.org
 S:	Maintained
 
 BLUETOOTH HCI BFUSB DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
-W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
 BLUETOOTH HCI DTL1 DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
-W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
 BLUETOOTH HCI BLUECARD DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
-W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
 BLUETOOTH HCI BT3C DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
-W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
 BLUETOOTH HCI BTUART DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
-W:	http://www.holtmann.org/linux/bluetooth/
 S:	Maintained
 
 BLUETOOTH HCI VHCI DRIVER
 P:	Maxim Krasnyansky
 M:	maxk@qualcomm.com
-W:	http://bluez.sf.net
 S:	Maintained
 
 BONDING DRIVER
@@ -954,11 +956,21 @@ P:	Tigran Aivazian
 M:	tigran@veritas.com
 S:	Maintained
 
+INTEL PRO/100 ETHERNET SUPPORT
+P:	John Ronciak
+M:	john.ronciak@intel.com
+P:	Ganesh Venkatesan
+M:	Ganesh.Venkatesan@intel.com
+W:	http://sourceforge.net/projects/e1000/
+S:	Supported
+
 INTEL PRO/1000 GIGABIT ETHERNET SUPPORT
 P:	Jeb Cramer
 M:	cramerj@intel.com
-P:	Scott Feldman
-M:	scott.feldman@intel.com
+P:	John Ronciak
+M:	john.ronciak@intel.com
+P:	Ganesh Venkatesan
+M:	Ganesh.Venkatesan@intel.com
 W:	http://sourceforge.net/projects/e1000/
 S:	Supported
 
@@ -1141,11 +1153,14 @@ M:	groudier@free.fr
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
 
-M68K
-P:	Jes Sorensen
-M:	jes@trained-monkey.org
-W:	http://www.clark.net/pub/lawrencc/linux/index.html
+M68K ARCHITECTURE
+P:	Geert Uytterhoeven
+M:	geert@linux-m68k.org
+P:	Roman Zippel
+M:	zippel@linux-m68k.org
 L:	linux-m68k@lists.linux-m68k.org
+W:	http://www.linux-m68k.org/
+W:	http://linux-m68k-cvs.ubb.ca/
 S:	Maintained
 
 M68K ON APPLE MACINTOSH
@@ -1306,6 +1321,8 @@ P:	James Morris
 M:	jmorris@intercode.com.au
 P:	Hideaki YOSHIFUJI
 M:	yoshfuji@linux-ipv6.org
+P:	Patrick McHardy
+M:	kaber@coreworks.de
 L:	netdev@oss.sgi.com
 S:	Maintained
 
@@ -1638,6 +1655,12 @@ M:	christer@weinigel.se
 W:	http://www.weinigel.se
 S:	Supported
 
+SERIAL ATA (SATA) SUBSYSTEM:
+P:	Jeff Garzik
+M:	jgarzik@pobox.com
+L:	linux-ide@vger.kernel.org
+S:	Supported
+
 SGI VISUAL WORKSTATION 320 AND 540
 P:	Bent Hagemark
 M:	bh@sgi.com
@@ -2161,7 +2184,7 @@ S:	Maintained
 
 XFS FILESYSTEM
 P:	Silicon Graphics Inc
-M:	owner-xfs@oss.sgi.com
+M:	xfs-masters@oss.sgi.com
 M:	nathans@sgi.com
 L:	linux-xfs@oss.sgi.com
 W:	http://oss.sgi.com/projects/xfs
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/Makefile linux-2.4.27-rc4/Makefile
--- linux-2.4.26/Makefile	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/Makefile	2004-07-30 16:29:41.000000000 +0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 26
-EXTRAVERSION =
+SUBLEVEL = 27
+EXTRAVERSION = -rc4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -175,6 +175,7 @@ DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4
 DRIVERS-$(CONFIG_PPC32) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_ISAPNP) += drivers/pnp/pnp.o
+DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
 DRIVERS-$(CONFIG_VT) += drivers/video/video.o
 DRIVERS-$(CONFIG_PARIDE) += drivers/block/paride/paride.a
 DRIVERS-$(CONFIG_HAMRADIO) += drivers/net/hamradio/hamradio.o
@@ -186,7 +187,6 @@ DRIVERS-$(CONFIG_INPUT) += drivers/input
 DRIVERS-$(CONFIG_HIL) += drivers/hil/hil.o
 DRIVERS-$(CONFIG_I2O) += drivers/message/i2o/i2o.o
 DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
-DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
 DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
 DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
 DRIVERS-$(CONFIG_GSC) += drivers/gsc/gscbus.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/alpha/kernel/sys_eiger.c linux-2.4.27-rc4/arch/alpha/kernel/sys_eiger.c
--- linux-2.4.26/arch/alpha/kernel/sys_eiger.c	2001-10-12 22:35:53.000000000 +0000
+++ linux-2.4.27-rc4/arch/alpha/kernel/sys_eiger.c	2004-07-30 16:25:27.000000000 +0000
@@ -193,27 +193,20 @@ eiger_swizzle(struct pci_dev *dev, u8 *p
 	   case 0x0f: bridge_count = 4; break; /* 4 */
 	};
 
-	/*  Check first for the built-in bridges on hose 0. */
-	if (hose->index == 0
-	    && PCI_SLOT(dev->bus->self->devfn) > 20-bridge_count) {
-		slot = PCI_SLOT(dev->devfn);
-	} else {
-		/* Must be a card-based bridge.  */
-		do {
-			/* Check for built-in bridges on hose 0. */
-			if (hose->index == 0
-			    && (PCI_SLOT(dev->bus->self->devfn)
-				> 20 - bridge_count)) {
-                  		slot = PCI_SLOT(dev->devfn);
-				break;
-			}
-			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
-
-			/* Move up the chain of bridges.  */
-			dev = dev->bus->self;
-			/* Slot of the next bridge.  */
+	slot = PCI_SLOT(dev->devfn);
+	while (dev->bus->self) {
+		/* Check for built-in bridges on hose 0. */
+		if (hose->index == 0
+		    && (PCI_SLOT(dev->bus->self->devfn)
+			> 20 - bridge_count)) {
 			slot = PCI_SLOT(dev->devfn);
-		} while (dev->bus->self);
+			break;
+		}
+		/* Must be a card-based bridge.  */
+		pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+		/* Move up the chain of bridges.  */
+		dev = dev->bus->self;
 	}
 	*pinp = pin;
 	return slot;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/alpha/kernel/sys_takara.c linux-2.4.27-rc4/arch/alpha/kernel/sys_takara.c
--- linux-2.4.26/arch/alpha/kernel/sys_takara.c	2000-10-27 17:55:01.000000000 +0000
+++ linux-2.4.27-rc4/arch/alpha/kernel/sys_takara.c	2004-07-30 16:25:57.000000000 +0000
@@ -230,8 +230,12 @@ takara_swizzle(struct pci_dev *dev, u8 *
 	int slot = PCI_SLOT(dev->devfn);
 	int pin = *pinp;
 	unsigned int ctlreg = inl(0x500);
-	unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
+	unsigned int busslot;
 
+	if (!dev->bus->self)
+		return slot;
+
+	busslot = PCI_SLOT(dev->bus->self->devfn);
 	/* Check for built-in bridges.  */
 	if (dev->bus->number != 0
 	    && busslot > 16
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/acpi.c linux-2.4.27-rc4/arch/i386/kernel/acpi.c
--- linux-2.4.26/arch/i386/kernel/acpi.c	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/acpi.c	2004-07-30 16:30:37.000000000 +0000
@@ -59,7 +59,10 @@ int acpi_sci_override_gsi __initdata;
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
 
-int acpi_noirq __initdata = 0;  /* skip ACPI IRQ initialization */
+#ifdef CONFIG_ACPI_PCI
+int acpi_noirq __initdata;	/* skip ACPI IRQ initialization */
+int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
+#endif
 int acpi_ht __initdata = 1;     /* enable HT */
 
 enum acpi_irq_model_id		acpi_irq_model;
@@ -105,6 +108,35 @@ char *__acpi_map_table(unsigned long phy
 	return ((unsigned char *) base + offset);
 }
 
+#ifdef CONFIG_ACPI_MMCONFIG
+
+u32 pci_mmcfg_base_addr;
+
+static int __init 
+acpi_parse_mcfg(unsigned long phys_addr,
+		unsigned long size)
+{
+	struct acpi_table_mcfg *mcfg = NULL;
+
+	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_ACPI_MMCONFIG */
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
@@ -406,6 +438,15 @@ acpi_boot_init (void)
 		return result;
 	}
 
+#ifdef CONFIG_ACPI_MMCONFIG
+	result = acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+	if (result < 0) {
+		printk(KERN_ERR PREFIX "Error %d parsing MCFG\n", result);
+	} else if (result > 1) {
+		printk(KERN_WARNING PREFIX "Multiple MCFG tables exist\n");
+	}
+#endif
+
 #ifdef CONFIG_X86_LOCAL_APIC
 
 	/* 
@@ -491,6 +532,11 @@ acpi_boot_init (void)
 		return 1;
         }
 
+	result = mp_irqs_alloc();	/* Dynamically allocate mp_irqs[] */
+	if (result < 0)  {
+		acpi_noirq = 1;
+		return result;
+	}
 
 	result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic);
 	if (!result) { 
@@ -502,9 +548,6 @@ acpi_boot_init (void)
 		return result;
 	}
 
-	/* Build a default routing table for legacy (ISA) interrupts. */
-	mp_config_acpi_legacy_irqs();
-
 	/* Record sci_int for use when looking for MADT sci_int override */
 	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
 
@@ -522,6 +565,9 @@ acpi_boot_init (void)
 	if (!acpi_sci_override_gsi)
 		acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
 
+	/* Fill in identity legacy mapings where no override */
+	mp_config_acpi_legacy_irqs();
+
 	result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
 	if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/edd.c linux-2.4.27-rc4/arch/i386/kernel/edd.c
--- linux-2.4.26/arch/i386/kernel/edd.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/edd.c	2004-07-30 16:26:20.000000000 +0000
@@ -46,9 +46,8 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@
 MODULE_DESCRIPTION("proc interface to BIOS EDD information");
 MODULE_LICENSE("GPL");
 
-#define EDD_VERSION "0.10 2003-Dec-05"
+#define EDD_VERSION "0.11 2004-Jun-21"
 #define EDD_DEVICE_NAME_SIZE 16
-#define REPORT_URL "http://domsch.com/linux/edd30/results.html"
 
 #define left (count - (p - page) - 1)
 
@@ -312,10 +311,6 @@ edd_show_raw_data(char *page, char **sta
 	}
 
 out:
-	p += snprintf(p, left, "\nPlease check %s\n", REPORT_URL);
-	p += snprintf(p, left, "to see if this device has been reported.  If not,\n");
-	p += snprintf(p, left, "please send the information requested there.\n");
-
 	return proc_calc_metrics(page, start, off, count, eof, (p - page));
 }
 
@@ -405,7 +400,7 @@ edd_show_default_cylinders(char *page, c
 		return proc_calc_metrics(page, start, off, count, eof, 0);
 	}
 
-	p += snprintf(p, left, "0x%x\n", info->params.num_default_cylinders);
+	p += snprintf(p, left, "%u\n", info->params.num_default_cylinders);
 	return proc_calc_metrics(page, start, off, count, eof, (p - page));
 }
 
@@ -418,7 +413,7 @@ edd_show_default_heads(char *page, char 
 		return proc_calc_metrics(page, start, off, count, eof, 0);
 	}
 
-	p += snprintf(p, left, "0x%x\n", info->params.num_default_heads);
+	p += snprintf(p, left, "%u\n", info->params.num_default_heads);
 	return proc_calc_metrics(page, start, off, count, eof, (p - page));
 }
 
@@ -431,7 +426,7 @@ edd_show_default_sectors_per_track(char 
 		return proc_calc_metrics(page, start, off, count, eof, 0);
 	}
 
-	p += snprintf(p, left, "0x%x\n", info->params.sectors_per_track);
+	p += snprintf(p, left, "%u\n", info->params.sectors_per_track);
 	return proc_calc_metrics(page, start, off, count, eof, (p - page));
 }
 
@@ -444,7 +439,7 @@ edd_show_sectors(char *page, char **star
 		return proc_calc_metrics(page, start, off, count, eof, 0);
 	}
 
-	p += snprintf(p, left, "0x%llx\n", info->params.number_of_sectors);
+	p += snprintf(p, left, "%llu\n", info->params.number_of_sectors);
 	return proc_calc_metrics(page, start, off, count, eof, (p - page));
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/i8259.c linux-2.4.27-rc4/arch/i386/kernel/i8259.c
--- linux-2.4.26/arch/i386/kernel/i8259.c	2001-09-18 06:03:09.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/i8259.c	2004-07-30 16:31:28.000000000 +0000
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/acpi.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -498,7 +499,8 @@ void __init init_IRQ(void)
 	outb(LATCH >> 8 , 0x40);	/* MSB */
 
 #ifndef CONFIG_VISWS
-	setup_irq(2, &irq2);
+	if (!acpi_ioapic)
+		setup_irq(2, &irq2);
 #endif
 
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/io_apic.c linux-2.4.27-rc4/arch/i386/kernel/io_apic.c
--- linux-2.4.26/arch/i386/kernel/io_apic.c	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/io_apic.c	2004-07-30 16:27:18.000000000 +0000
@@ -1691,18 +1691,10 @@ static inline void check_timer(void)
 
 /*
  *
- * IRQ's that are handled by the old PIC in all cases:
+ * IRQ's that are handled by the PIC in the MPS IOAPIC case.
  * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
  *   Linux doesn't really care, as it's not actually used
  *   for any interrupt handling anyway.
- * - There used to be IRQ13 here as well, but all
- *   MPS-compliant must not use it for FPU coupling and we
- *   want to use exception 16 anyway.  And there are
- *   systems who connect it to an I/O APIC for other uses.
- *   Thus we don't mark it special any longer.
- *
- * Additionally, something is definitely wrong with irq9
- * on PIIX4 boards.
  */
 #define PIC_IRQS	(1<<2)
 
@@ -1710,7 +1702,11 @@ void __init setup_IO_APIC(void)
 {
 	enable_IO_APIC();
 
-	io_apic_irqs = ~PIC_IRQS;
+	if (acpi_ioapic)
+		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
+	else
+		io_apic_irqs = ~PIC_IRQS;
+
 	printk("ENABLING IO-APIC IRQs\n");
 
 	/*
@@ -1872,7 +1868,7 @@ int io_apic_set_pci_routing (int ioapic,
 
 	entry.vector = assign_irq_vector(irq);
 
-	printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
+	Dprintk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
 		"IRQ %d Mode:%i Active:%i)\n", ioapic,
 		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/mpparse.c linux-2.4.27-rc4/arch/i386/kernel/mpparse.c
--- linux-2.4.26/arch/i386/kernel/mpparse.c	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/mpparse.c	2004-07-30 16:27:11.000000000 +0000
@@ -1104,6 +1104,20 @@ void __init mp_register_ioapic (
 }
 
 
+/* allocate mp_irqs[] for ACPI parsing table parsing */
+int __init mp_irqs_alloc()
+{
+	int size = (MAX_IRQ_SOURCES * sizeof(int)) * 4;
+
+	mp_irqs = (struct mpc_config_intsrc *)alloc_bootmem(size);
+	if (!mp_irqs) {
+		printk(KERN_ERR "mp_irqs_alloc(): alloc_bootmem(%d) failed!\n", size);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+
 void __init mp_override_legacy_irq (
 	u8			bus_irq,
 	u8			polarity, 
@@ -1111,8 +1125,6 @@ void __init mp_override_legacy_irq (
 	u32			global_irq)
 {
 	struct mpc_config_intsrc intsrc;
-	int			i = 0;
-	int			found = 0;
 	int			ioapic = -1;
 	int			pin = -1;
 
@@ -1145,23 +1157,9 @@ void __init mp_override_legacy_irq (
 		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
 		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
 
-	/* 
-	 * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it.
-	 * Otherwise create a new entry (e.g. global_irq == 2).
-	 */
-	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
-			&& (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) {
-			mp_irqs[i] = intsrc;
-			found = 1;
-			break;
-		}
-	}
-	if (!found) {
-		mp_irqs[mp_irq_entries] = intsrc;
-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
-			panic("Max # of irq sources exceeded!\n");
-	}
+	mp_irqs[mp_irq_entries] = intsrc;
+	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+		panic("Max # of irq sources exceeded!\n");
 
 	return;
 }
@@ -1179,7 +1177,6 @@ void __init mp_config_acpi_legacy_irqs (
 	int count;
 
 	count = (MAX_MP_BUSSES * sizeof(int)) * 4;
-	count += (MAX_IRQ_SOURCES * sizeof(int)) * 4;
 	bus_data = alloc_bootmem(count);
 	if (!bus_data) {
 		panic("Fatal: can't allocate bus memory for ACPI legacy IRQ!");
@@ -1188,7 +1185,7 @@ void __init mp_config_acpi_legacy_irqs (
 	mp_bus_id_to_node = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int))];
 	mp_bus_id_to_local = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 2];
 	mp_bus_id_to_pci_bus = (int *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 3];
-	mp_irqs = (struct mpc_config_intsrc *)&bus_data[(MAX_MP_BUSSES * sizeof(int)) * 4];
+
 	for (i = 0; i < MAX_MP_BUSSES; ++i)
 	  mp_bus_id_to_pci_bus[i] = -1;
 
@@ -1206,13 +1203,20 @@ void __init mp_config_acpi_legacy_irqs (
 		return;
 
 	/* 
-	 * Use the default configuration for the IRQs 0-15.  These may be
+	 * Use the default configuration for the IRQs 0-15.  Unless
 	 * overriden by (MADT) interrupt source override entries.
 	 */
 	for (i = 0; i < 16; i++) {
+		int idx;
 
-		if (i == 2)
-			continue;			/* Don't connect IRQ2 */
+		for (idx = 0; idx < mp_irq_entries; idx++)
+			if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS &&
+				(mp_irqs[idx].mpc_dstapic == mp_ioapics[ioapic].mpc_apicid) &&
+				(mp_irqs[idx].mpc_srcbusirq == i ||
+				mp_irqs[idx].mpc_dstirq == i))
+					break;
+		if (idx != mp_irq_entries)
+			continue;			  /* IRQ already used */
 
 		mp_irqs[mp_irq_entries].mpc_type = MP_INTSRC;
 		mp_irqs[mp_irq_entries].mpc_irqflag = 0;	/* Conforming */
@@ -1308,11 +1312,13 @@ void __init mp_parse_prt (void)
 		if (!io_apic_set_pci_routing(ioapic, ioapic_pin, irq, edge_level, active_high_low))
 			entry->irq = irq;
 
-		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> IRQ %d\n",
-			entry->id.segment, entry->id.bus, 
-			entry->id.device, ('A' + entry->pin), 
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, 
-			entry->irq);
+                printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d"
+                        " -> IRQ %d %s %s\n", entry->id.segment, entry->id.bus,
+                        entry->id.device, ('A' + entry->pin),
+                        mp_ioapic_routing[ioapic].apic_id, ioapic_pin,
+                        entry->irq, edge_level ? "level" : "edge",
+                        active_high_low ? "low" : "high");
+
 	}
 	
 	print_IO_APIC();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/pci-irq.c linux-2.4.27-rc4/arch/i386/kernel/pci-irq.c
--- linux-2.4.26/arch/i386/kernel/pci-irq.c	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/pci-irq.c	2004-07-30 16:32:00.910750952 +0000
@@ -1067,6 +1067,7 @@ void pcibios_enable_irq(struct pci_dev *
 {
 	u8 pin;
 	extern int interrupt_line_quirk;
+ 	struct pci_dev *temp_dev;
 	
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
@@ -1076,9 +1077,44 @@ void pcibios_enable_irq(struct pci_dev *
 		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
 			return;
 
-		if (io_apic_assign_pci_irqs)
-			msg = " Probably buggy MP table.";
-		else if (pci_probe & PCI_BIOS_IRQ_SCAN)
+		if (io_apic_assign_pci_irqs) {
+			int irq;
+
+			if (pin) {
+				pin--;		/* interrupt pins are numbered starting from 1 */
+				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
+				/*
+				 * Busses behind bridges are typically not listed in the MP-table.
+				 * In this case we have to look up the IRQ based on the parent bus,
+				 * parent slot, and pin number. The SMP code detects such bridged
+				 * busses itself so we should get into this branch reliably.
+				 */
+				temp_dev = dev;
+				while (irq < 0 && dev->bus->parent) { /* go back to the bridge */
+					struct pci_dev * bridge = dev->bus->self;
+
+					pin = (pin + PCI_SLOT(dev->devfn)) % 4;
+					irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number, 
+							PCI_SLOT(bridge->devfn), pin);
+					if (irq >= 0)
+						printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", 
+							bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
+					dev = bridge;
+				}
+				dev = temp_dev;
+				if (irq >= 0) {
+#ifdef CONFIG_PCI_USE_VECTOR
+					if (!platform_legacy_irq(irq))
+						irq = IO_APIC_VECTOR(irq);
+#endif
+					printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
+						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+					dev->irq = irq;
+					return;
+				} else
+					msg = " Probably buggy MP table.";
+			}
+		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
 			msg = "";
 		else
 			msg = " Please try using pci=biosirq.";
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/pci-pc.c linux-2.4.27-rc4/arch/i386/kernel/pci-pc.c
--- linux-2.4.26/arch/i386/kernel/pci-pc.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/pci-pc.c	2004-07-30 16:27:44.000000000 +0000
@@ -1321,13 +1321,46 @@ static void __init pci_fixup_via_northbr
  * system to PCI bus no matter what are their window settings, so they are
  * "transparent" (or subtractive decoding) from programmers point of view.
  */
-static void __init pci_fixup_transparent_bridge(struct pci_dev *dev)
+static void __devinit pci_fixup_transparent_bridge(struct pci_dev *dev)
 {
 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
 	    (dev->device & 0xff00) == 0x2400)
 		dev->transparent = 1;
 }
 
+/*
+ * Fixup for C1 Halt Disconnect problem on nForce2 systems.
+ *
+ * From information provided by "Allen Martin" <AMartin@nvidia.com>:
+ *
+ * A hang is caused when the CPU generates a very fast CONNECT/HALT cycle
+ * sequence.  Workaround is to set the SYSTEM_IDLE_TIMEOUT to 80 ns.
+ * This allows the state-machine and timer to return to a proper state within
+ * 80 ns of the CONNECT and probe appearing together.  Since the CPU will not
+ * issue another HALT within 80 ns of the initial HALT, the failure condition
+ * is avoided.
+ */
+static void __devinit pci_fixup_nforce2(struct pci_dev *dev)
+{
+	u32 val, fixed_val;
+	u8 rev;
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+
+	/*
+	* Chip 	Old value   	New value
+	* C17  	0x1F0FFF01  	0x1F01FF01
+	* C18D 	0x9F0FFF01  	0x9F01FF01
+	*/
+	fixed_val = rev < 0xC1 ? 0x1F01FF01 : 0x9F01FF01;
+
+	pci_read_config_dword(dev, 0x6c, &val);
+	if (val != fixed_val) {
+		printk(KERN_WARNING "PCI: nForce2 C1 Halt Disconnect fixup\n");
+		pci_write_config_dword(dev, 0x6c, fixed_val);
+	}
+}
+
 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 },
@@ -1343,6 +1376,7 @@ struct pci_fixup pcibios_fixups[] = {
 	{ 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 },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE2,	pci_fixup_nforce2},
 	{ 0 }
 };
 
@@ -1433,7 +1467,6 @@ void __init pcibios_init(void)
 	if (!acpi_noirq && !acpi_pci_irq_init()) {
 		pci_using_acpi_prt = 1;
 		printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-		printk(KERN_INFO "PCI: if you experience problems, try using option 'pci=noacpi' or even 'acpi=off'\n");
 	}
 #endif
 	if (!pci_using_acpi_prt) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/kernel/setup.c linux-2.4.27-rc4/arch/i386/kernel/setup.c
--- linux-2.4.26/arch/i386/kernel/setup.c	2004-04-14 13:05:25.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/kernel/setup.c	2004-07-30 16:28:28.000000000 +0000
@@ -2333,6 +2333,7 @@ static struct _cache_table cache_table[]
 	{ 0x43, LVL_2,      512 },
 	{ 0x44, LVL_2,      1024 },
 	{ 0x45, LVL_2,      2048 },
+	{ 0x60, LVL_1_DATA, 16 },
 	{ 0x66, LVL_1_DATA, 8 },
 	{ 0x67, LVL_1_DATA, 16 },
 	{ 0x68, LVL_1_DATA, 32 },
@@ -2443,6 +2444,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);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/mm/fault.c linux-2.4.27-rc4/arch/i386/mm/fault.c
--- linux-2.4.26/arch/i386/mm/fault.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/mm/fault.c	2004-07-30 16:24:27.000000000 +0000
@@ -71,7 +71,7 @@ good_area:
 		if (!vma || vma->vm_start != start)
 			goto bad_area;
 		if (!(vma->vm_flags & VM_WRITE))
-			goto bad_area;;
+			goto bad_area;
 	}
 	return 1;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/i386/mm/pageattr.c linux-2.4.27-rc4/arch/i386/mm/pageattr.c
--- linux-2.4.26/arch/i386/mm/pageattr.c	2002-11-28 23:53:09.000000000 +0000
+++ linux-2.4.27-rc4/arch/i386/mm/pageattr.c	2004-07-30 16:27:14.000000000 +0000
@@ -52,11 +52,9 @@ static struct page *split_large_page(uns
 
 static void flush_kernel_map(void * address) 
 { 
-	if (!test_bit(X86_FEATURE_SELFSNOOP, boot_cpu_data.x86_capability)) {
-		/* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */
-		if (boot_cpu_data.x86_model >= 4) 
-			asm volatile("wbinvd":::"memory"); 	
-	} 
+	/* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */
+	if (boot_cpu_data.x86_model >= 4) 
+		asm volatile("wbinvd":::"memory"); 	
 
 	/* Do global flush here to work around large page flushing errata 
 	   in some early Athlons */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/configs/dig linux-2.4.27-rc4/arch/ia64/configs/dig
--- linux-2.4.26/arch/ia64/configs/dig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/configs/dig	2004-07-30 16:29:27.000000000 +0000
@@ -28,9 +28,9 @@ CONFIG_ITANIUM=y
 # CONFIG_MCKINLEY is not set
 # CONFIG_IA64_GENERIC is not set
 CONFIG_IA64_DIG=y
-# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -116,7 +116,6 @@ CONFIG_INET=y
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -265,6 +264,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -293,6 +293,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -430,6 +431,7 @@ CONFIG_EEPRO100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -511,6 +513,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -586,6 +589,7 @@ CONFIG_INPUT_SERPORT=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_INTEL_RNG is not set
 # CONFIG_HW_RANDOM is not set
@@ -727,6 +731,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -940,7 +949,6 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/configs/generic linux-2.4.27-rc4/arch/ia64/configs/generic
--- linux-2.4.26/arch/ia64/configs/generic	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/configs/generic	2004-07-30 16:25:17.000000000 +0000
@@ -28,9 +28,9 @@ CONFIG_ITANIUM=y
 # CONFIG_MCKINLEY is not set
 CONFIG_IA64_GENERIC=y
 # CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -116,7 +116,6 @@ CONFIG_INET=y
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -265,6 +264,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
 CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -294,6 +294,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -436,6 +437,7 @@ CONFIG_EEPRO100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -517,6 +519,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -592,6 +595,7 @@ CONFIG_INPUT_SERPORT=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_FETCHOP is not set
 # CONFIG_INTEL_RNG is not set
@@ -734,6 +738,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -947,7 +956,6 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/configs/numa linux-2.4.27-rc4/arch/ia64/configs/numa
--- linux-2.4.26/arch/ia64/configs/numa	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/configs/numa	2004-07-30 16:29:14.000000000 +0000
@@ -28,9 +28,9 @@ CONFIG_ITANIUM=y
 # CONFIG_MCKINLEY is not set
 CONFIG_IA64_GENERIC=y
 # CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -118,7 +118,6 @@ CONFIG_INET=y
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -267,6 +266,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
 CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -296,6 +296,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -438,6 +439,7 @@ CONFIG_EEPRO100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -519,6 +521,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -594,6 +597,7 @@ CONFIG_INPUT_SERPORT=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_FETCHOP is not set
 # CONFIG_INTEL_RNG is not set
@@ -736,6 +740,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -949,7 +958,6 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/configs/ski linux-2.4.27-rc4/arch/ia64/configs/ski
--- linux-2.4.26/arch/ia64/configs/ski	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/configs/ski	2004-07-30 16:26:40.000000000 +0000
@@ -28,9 +28,9 @@ CONFIG_ITANIUM=y
 # CONFIG_MCKINLEY is not set
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
-CONFIG_IA64_HP_SIM=y
 # CONFIG_IA64_HP_ZX1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
+CONFIG_IA64_HP_SIM=y
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -83,7 +83,6 @@ CONFIG_INET=y
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -202,6 +201,7 @@ CONFIG_SCSI_LOGGING=y
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -256,6 +256,7 @@ CONFIG_PSMOUSE=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_INTEL_RNG is not set
 # CONFIG_HW_RANDOM is not set
@@ -374,6 +375,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/configs/zx1 linux-2.4.27-rc4/arch/ia64/configs/zx1
--- linux-2.4.26/arch/ia64/configs/zx1	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/configs/zx1	2004-07-30 16:30:52.000000000 +0000
@@ -28,9 +28,9 @@ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_MCKINLEY=y
 # CONFIG_IA64_GENERIC is not set
 # CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
 CONFIG_IA64_HP_ZX1=y
 # CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -117,7 +117,6 @@ CONFIG_INET=y
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -266,6 +265,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -294,6 +294,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -431,6 +432,7 @@ CONFIG_EEPRO100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -512,6 +514,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -587,6 +590,7 @@ CONFIG_INPUT_SERPORT=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_INTEL_RNG is not set
 # CONFIG_HW_RANDOM is not set
@@ -728,6 +732,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -941,7 +950,6 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/defconfig linux-2.4.27-rc4/arch/ia64/defconfig
--- linux-2.4.26/arch/ia64/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/defconfig	2004-07-30 16:25:26.000000000 +0000
@@ -28,9 +28,9 @@ CONFIG_ITANIUM=y
 # CONFIG_MCKINLEY is not set
 CONFIG_IA64_GENERIC=y
 # CONFIG_IA64_DIG is not set
-# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_HP_ZX1 is not set
 # CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_HP_SIM is not set
 # CONFIG_IA64_PAGE_SIZE_4KB is not set
 # CONFIG_IA64_PAGE_SIZE_8KB is not set
 CONFIG_IA64_PAGE_SIZE_16KB=y
@@ -116,7 +116,6 @@ CONFIG_INET=y
 #
 #    SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
 # CONFIG_VLAN_8021Q is not set
@@ -265,6 +264,7 @@ CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
 # CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_ATIIXP is not set
 CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_TRIFLEX is not set
 # CONFIG_BLK_DEV_CY82C693 is not set
@@ -294,6 +294,7 @@ CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_ATARAID is not set
 # CONFIG_BLK_DEV_ATARAID_PDC is not set
 # CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
 # CONFIG_BLK_DEV_ATARAID_SII is not set
 
 #
@@ -436,6 +437,7 @@ CONFIG_EEPRO100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139CP is not set
@@ -517,6 +519,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_UINPUT is not set
 
 #
 # Character devices
@@ -592,6 +595,7 @@ CONFIG_INPUT_SERPORT=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_SCx200 is not set
 # CONFIG_SCx200_GPIO is not set
 # CONFIG_FETCHOP is not set
 # CONFIG_INTEL_RNG is not set
@@ -734,6 +738,11 @@ CONFIG_EXT2_FS=y
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_UFS_FS_WRITE is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_TRACE is not set
+# CONFIG_XFS_DEBUG is not set
 
 #
 # Network File Systems
@@ -947,7 +956,6 @@ CONFIG_USB_HIDDEV=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
-# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/ia32/binfmt_elf32.c linux-2.4.27-rc4/arch/ia64/ia32/binfmt_elf32.c
--- linux-2.4.26/arch/ia64/ia32/binfmt_elf32.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/ia32/binfmt_elf32.c	2004-07-30 16:31:28.000000000 +0000
@@ -17,6 +17,8 @@
 #include <asm/signal.h>
 #include <asm/ia32.h>
 
+#include "elfcore32.h"
+
 #define CONFIG_BINFMT_ELF32
 
 /* Override some function names */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/ia32/elfcore32.h linux-2.4.27-rc4/arch/ia64/ia32/elfcore32.h
--- linux-2.4.26/arch/ia64/ia32/elfcore32.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/ia32/elfcore32.h	2004-07-30 16:31:02.000000000 +0000
@@ -0,0 +1,133 @@
+/*
+ * IA-32 ELF core dump support.
+ *
+ * Copyright (C) 2003 Arun Sharma <arun.sharma@intel.com>
+ *
+ * Derived from the x86_64 version
+ */
+#ifndef _ELFCORE32_H_
+#define _ELFCORE32_H_
+
+#define USE_ELF_CORE_DUMP 1
+
+/* Override elfcore.h */ 
+#define _LINUX_ELFCORE_H 1
+typedef unsigned int elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct ia32_user_i387_struct elf_fpregset_t;
+typedef struct ia32_user_fxsr_struct elf_fpxregset_t;
+
+struct elf_siginfo
+{
+	int	si_signo;			/* signal number */
+	int	si_code;			/* extra code */
+	int	si_errno;			/* errno */
+};
+
+#define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0)
+
+struct compat_timeval
+{
+    int tv_sec, tv_usec;
+};
+
+struct elf_prstatus
+{
+	struct elf_siginfo pr_info;	/* Info associated with signal */
+	short	pr_cursig;		/* Current signal */
+	unsigned int pr_sigpend;	/* Set of pending signals */
+	unsigned int pr_sighold;	/* Set of held signals */
+	pid_t	pr_pid;
+	pid_t	pr_ppid;
+	pid_t	pr_pgrp;
+	pid_t	pr_sid;
+	struct compat_timeval pr_utime;	/* User time */
+	struct compat_timeval pr_stime;	/* System time */
+	struct compat_timeval pr_cutime;	/* Cumulative user time */
+	struct compat_timeval pr_cstime;	/* Cumulative system time */
+	elf_gregset_t pr_reg;	/* GP registers */
+	int pr_fpvalid;		/* True if math co-processor being used.  */
+};
+
+#define ELF_PRARGSZ	(80)	/* Number of chars for args */
+
+struct elf_prpsinfo
+{
+	char	pr_state;	/* numeric process state */
+	char	pr_sname;	/* char for pr_state */
+	char	pr_zomb;	/* zombie */
+	char	pr_nice;	/* nice val */
+	unsigned int pr_flag;	/* flags */
+	__u16	pr_uid;
+	__u16	pr_gid;
+	pid_t	pr_pid, pr_ppid, pr_pgrp, pr_sid;
+	/* Lots missing */
+	char	pr_fname[16];	/* filename of executable */
+	char	pr_psargs[ELF_PRARGSZ];	/* initial part of arg list */
+};
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs)       		\
+	pr_reg[0] = regs->r11;				\
+	pr_reg[1] = regs->r9;				\
+	pr_reg[2] = regs->r10;				\
+	pr_reg[3] = regs->r14;				\
+	pr_reg[4] = regs->r15;				\
+	pr_reg[5] = regs->r13;				\
+	pr_reg[6] = regs->r8;				\
+	pr_reg[7] = regs->r16 & 0xffff;			\
+	pr_reg[8] = (regs->r16 >> 16) & 0xffff;		\
+	pr_reg[9] = (regs->r16 >> 32) & 0xffff;		\
+	pr_reg[10] = (regs->r16 >> 48) & 0xffff;	\
+	pr_reg[11] = regs->r1; 				\
+	pr_reg[12] = regs->cr_iip;			\
+	pr_reg[13] = regs->r17 & 0xffff;		\
+	asm volatile ("mov %0=ar.eflag ;;"		\
+		      : "=r"(pr_reg[14]));		\
+	pr_reg[15] = regs->r12;				\
+	pr_reg[16] = (regs->r17 >> 16) & 0xffff;
+
+static inline void elf_core_copy_regs(elf_gregset_t *elfregs,
+				      struct pt_regs *regs)
+{
+	ELF_CORE_COPY_REGS((*elfregs), regs)
+}
+
+static inline int elf_core_copy_task_regs(struct task_struct *t,
+					  elf_gregset_t* elfregs)
+{	
+	struct pt_regs *pp = ia64_task_regs(t);
+	ELF_CORE_COPY_REGS((*elfregs), pp);
+	return 1; 
+}
+
+static inline int 
+elf_core_copy_task_fpregs(struct task_struct *tsk, elf_fpregset_t *fpu)
+{
+	struct ia32_user_i387_struct *fpstate = (void*)fpu;
+
+	if (!tsk->used_math) 
+		return 0;
+
+	save_ia32_fpstate(tsk, fpstate);
+
+	return 1; 
+}
+
+#define ELF_CORE_COPY_XFPREGS 1
+static inline int 
+elf_core_copy_task_xfpregs(struct task_struct *tsk, elf_fpxregset_t *xfpu)
+{
+	struct ia32_user_fxsr_struct *fpxstate = (void*) xfpu; 
+
+	if (!tsk->used_math) 
+		return 0;
+
+	save_ia32_fpxstate(tsk, fpxstate);
+	
+	return 1;
+}
+
+#endif /* _ELFCORE32_H_ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/ia32/sys_ia32.c linux-2.4.27-rc4/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.26/arch/ia64/ia32/sys_ia32.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/ia32/sys_ia32.c	2004-07-30 16:29:23.000000000 +0000
@@ -2949,7 +2949,7 @@ get_fpreg (int regno, struct _fpreg_ia32
 	return;
 }
 
-static int
+int
 save_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct *save)
 {
 	struct switch_stack *swp;
@@ -3011,7 +3011,7 @@ restore_ia32_fpstate (struct task_struct
 	return 0;
 }
 
-static int
+int
 save_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct *save)
 {
 	struct switch_stack *swp;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/kernel/efi.c linux-2.4.27-rc4/arch/ia64/kernel/efi.c
--- linux-2.4.26/arch/ia64/kernel/efi.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/kernel/efi.c	2004-07-30 16:25:04.000000000 +0000
@@ -673,8 +673,7 @@ efi_get_iobase (void)
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
 		if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
-			/* paranoia attribute checking */
-			if (md->attribute == (EFI_MEMORY_UC | EFI_MEMORY_RUNTIME))
+			if (md->attribute & EFI_MEMORY_UC)
 				return md->phys_addr;
 		}
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/kernel/palinfo.c linux-2.4.27-rc4/arch/ia64/kernel/palinfo.c
--- linux-2.4.26/arch/ia64/kernel/palinfo.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/kernel/palinfo.c	2004-07-30 16:24:41.000000000 +0000
@@ -509,10 +509,10 @@ static const char *bus_features[]={
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL,
-	"Enable Cache Line Repl. Exclusive",
 	"Enable Cache Line Repl. Shared",
+	"Enable Cache Line Repl. Exclusive",
 	"Disable Transaction Queuing",
-	"Disable Reponse Error Checking",
+	"Disable Response Error Checking",
 	"Disable Bus Error Checking",
 	"Disable Bus Requester Internal Error Signalling",
 	"Disable Bus Requester Error Signalling",
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/kernel/perfmon.c linux-2.4.27-rc4/arch/ia64/kernel/perfmon.c
--- linux-2.4.26/arch/ia64/kernel/perfmon.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/kernel/perfmon.c	2004-07-30 16:31:29.000000000 +0000
@@ -25,6 +25,7 @@
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 #include <linux/smp.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/errno.h>
@@ -887,6 +888,8 @@ pfm_smpl_buffer_alloc(pfm_context_t *ctx
 		DBprintk(("Cannot allocate vma\n"));
 		goto error_kmem;
 	}
+	memset(vma, 0, sizeof(*vma));
+
 	/*
 	 * partially initialize the vma for the sampling buffer
 	 *
@@ -3166,62 +3169,111 @@ pfm_interrupt_handler(int irq, void *arg
 	}
 }
 
-/* for debug only */
-static int
-pfm_proc_info(char *page)
+#define PFM_PROC_SHOW_HEADER	((void *)NR_CPUS+1)
+  
+static void *
+pfm_proc_start(struct seq_file *m, loff_t *pos)
 {
-	char *p = page;
-	int i;
-
-	p += sprintf(p, "fastctxsw              : %s\n", pfm_sysctl.fastctxsw > 0 ? "Yes": "No");
-	p += sprintf(p, "ovfl_mask              : 0x%lx\n", pmu_conf.ovfl_val);
-
-	for(i=0; i < NR_CPUS; i++) {
-		if (cpu_online(i) == 0) continue;
-		p += sprintf(p, "CPU%-2d overflow intrs   : %lu\n", i, pfm_stats[i].pfm_ovfl_intr_count);
-		p += sprintf(p, "CPU%-2d spurious intrs   : %lu\n", i, pfm_stats[i].pfm_spurious_ovfl_intr_count);
-		p += sprintf(p, "CPU%-2d recorded samples : %lu\n", i, pfm_stats[i].pfm_recorded_samples_count);
-		p += sprintf(p, "CPU%-2d smpl buffer full : %lu\n", i, pfm_stats[i].pfm_full_smpl_buffer_count);
-		p += sprintf(p, "CPU%-2d syst_wide        : %d\n", i, cpu_data(i)->pfm_syst_info & PFM_CPUINFO_SYST_WIDE ? 1 : 0);
-		p += sprintf(p, "CPU%-2d dcr_pp           : %d\n", i, cpu_data(i)->pfm_syst_info & PFM_CPUINFO_DCR_PP ? 1 : 0);
-		p += sprintf(p, "CPU%-2d exclude idle     : %d\n", i, cpu_data(i)->pfm_syst_info & PFM_CPUINFO_EXCL_IDLE ? 1 : 0);
-		p += sprintf(p, "CPU%-2d owner            : %d\n", i, pmu_owners[i].owner ? pmu_owners[i].owner->pid: -1);
-		p += sprintf(p, "CPU%-2d activations      : %lu\n", i, pmu_owners[i].activation_number);
+	if (*pos == 0) {
+		return PFM_PROC_SHOW_HEADER;
 	}
 
-	LOCK_PFS();
-
-	p += sprintf(p, "proc_sessions          : %u\n"
-			"sys_sessions           : %u\n"
-			"sys_use_dbregs         : %u\n"
-			"ptrace_use_dbregs      : %u\n", 
-			pfm_sessions.pfs_task_sessions, 
-			pfm_sessions.pfs_sys_sessions,
-			pfm_sessions.pfs_sys_use_dbregs,
-			pfm_sessions.pfs_ptrace_use_dbregs);
-
-	UNLOCK_PFS();
-
-	return p - page;
+	while (*pos <= NR_CPUS) {
+		if (cpu_online(*pos - 1)) {
+			return (void *)*pos;
+		}
+		++*pos;
+	}
+	return NULL;
+}
+ 
+static void *
+pfm_proc_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return pfm_proc_start(m, pos);
+}
+ 
+static void
+pfm_proc_stop(struct seq_file *m, void *v)
+{
 }
 
-/* /proc interface, for debug only */
+static void
+pfm_proc_show_header(struct seq_file *m)
+{
+ 	seq_printf(m,
+		"perfmon version           : %u.%u\n"
+		"fastctxsw                 : %s\n"
+		"ovfl_mask                 : 0x%lx\n",
+		PFM_VERSION_MAJ, PFM_VERSION_MIN,
+		pfm_sysctl.fastctxsw > 0 ? "Yes": "No",
+		pmu_conf.ovfl_val);
+  
+  	LOCK_PFS();
+  
+ 	seq_printf(m,
+ 		"proc_sessions             : %u\n"
+ 		"sys_sessions              : %u\n"
+ 		"sys_use_dbregs            : %u\n"
+ 		"ptrace_use_dbregs         : %u\n",
+ 		pfm_sessions.pfs_task_sessions, 
+ 		pfm_sessions.pfs_sys_sessions,
+ 		pfm_sessions.pfs_sys_use_dbregs,
+ 		pfm_sessions.pfs_ptrace_use_dbregs);
+  
+  	UNLOCK_PFS();
+}
+  
 static int
-perfmon_read_entry(char *page, char **start, off_t off, int count, int *eof, void *data)
+pfm_proc_show(struct seq_file *m, void *v)
 {
-	int len = pfm_proc_info(page);
+	int cpu;
 
-	if (len <= off+count) *eof = 1;
+	if (v == PFM_PROC_SHOW_HEADER) {
+		pfm_proc_show_header(m);
+		return 0;
+	}
 
-	*start = page + off;
-	len   -= off;
+	/* show info for CPU (v - 1) */
 
-	if (len>count) len = count;
-	if (len<0) len = 0;
+	cpu = (long)v - 1;
+	seq_printf(m,
+		"CPU%-2d overflow intrs      : %lu\n"
+		"CPU%-2d spurious intrs      : %lu\n"
+		"CPU%-2d recorded samples    : %lu\n"
+		"CPU%-2d smpl buffer full    : %lu\n"
+		"CPU%-2d syst_wide           : %d\n"
+		"CPU%-2d dcr_pp              : %d\n"
+		"CPU%-2d exclude idle        : %d\n"
+		"CPU%-2d owner               : %d\n"
+		"CPU%-2d activations         : %lu\n",
+		cpu, pfm_stats[cpu].pfm_ovfl_intr_count,
+		cpu, pfm_stats[cpu].pfm_spurious_ovfl_intr_count,
+		cpu, pfm_stats[cpu].pfm_recorded_samples_count,
+		cpu, pfm_stats[cpu].pfm_full_smpl_buffer_count,
+		cpu, cpu_data(cpu)->pfm_syst_info & PFM_CPUINFO_SYST_WIDE ? 1 : 0,
+		cpu, cpu_data(cpu)->pfm_syst_info & PFM_CPUINFO_DCR_PP ? 1 : 0,
+		cpu, cpu_data(cpu)->pfm_syst_info & PFM_CPUINFO_EXCL_IDLE ? 1 : 0,
+		cpu, pmu_owners[cpu].owner ? pmu_owners[cpu].owner->pid: -1,
+		cpu, pmu_owners[cpu].activation_number);
 
-	return len;
+	return 0;
 }
-
+ 
+struct seq_operations pfm_seq_ops = {
+	.start =	pfm_proc_start,
+ 	.next =		pfm_proc_next,
+ 	.stop =		pfm_proc_stop,
+ 	.show =		pfm_proc_show
+};
+ 
+static int
+pfm_proc_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &pfm_seq_ops);
+}
+ 
 /*
  * we come here as soon as local_cpu_data->pfm_syst_wide is set. this happens
  * during pfm_enable() hence before pfm_start(). We cannot assume monitoring
@@ -4448,6 +4500,13 @@ pfm_remove_alternate_syswide_subsystem(p
 	return 0;
 }
 
+static struct file_operations pfm_proc_fops = {
+	.open		= pfm_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 /*
  * perfmon initialization routine, called from the initcall() table
  */
@@ -4498,11 +4557,15 @@ pfm_init(void)
 	/*
 	 * for now here for debug purposes
 	 */
-	perfmon_dir = create_proc_read_entry ("perfmon", 0, 0, perfmon_read_entry, NULL);
+ 	perfmon_dir = create_proc_entry("perfmon", S_IRUGO, NULL);
 	if (perfmon_dir == NULL) {
 		printk(KERN_ERR "perfmon: cannot create /proc entry, perfmon disabled\n");
 		return -1;
 	}
+  	/*
+ 	 * install customized file operations for /proc/perfmon entry
+ 	 */
+ 	perfmon_dir->proc_fops = &pfm_proc_fops;
 
 	/*
 	 * create /proc/sys/kernel/perfmon
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/kernel/unwind.c linux-2.4.27-rc4/arch/ia64/kernel/unwind.c
--- linux-2.4.26/arch/ia64/kernel/unwind.c	2004-04-14 13:05:26.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/kernel/unwind.c	2004-07-30 16:32:20.033843800 +0000
@@ -1750,7 +1750,7 @@ run_script (struct unw_script *script, s
 			if (!state->pri_unat_loc)
 				state->pri_unat_loc = &state->sw->ar_unat;
 			/* register off. is a multiple of 8, so the least 3 bits (type) are 0 */
-			s[dst+1] = (*state->pri_unat_loc - s[dst]) | UNW_NAT_MEMSTK;
+			s[dst+1] = ((unsigned long) state->pri_unat_loc - s[dst]) | UNW_NAT_MEMSTK;
 			break;
 
 		      case UNW_INSN_SETNAT_TYPE:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ia64/mm/hugetlbpage.c linux-2.4.27-rc4/arch/ia64/mm/hugetlbpage.c
--- linux-2.4.26/arch/ia64/mm/hugetlbpage.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/ia64/mm/hugetlbpage.c	2004-07-30 16:27:29.000000000 +0000
@@ -73,8 +73,12 @@ huge_pte_offset (struct mm_struct *mm, u
 	pte_t *pte = NULL;
 
 	pgd = pgd_offset(mm, taddr);
-	pmd = pmd_offset(pgd, taddr);
-	pte = pte_offset(pmd, taddr);
+	if (pgd_present(*pgd)) {
+		pmd = pmd_offset(pgd, taddr);
+		if (pmd_present(*pmd))
+			pte = pte_offset(pmd, taddr);
+	}
+
 	return pte;
 }
 
@@ -269,7 +273,7 @@ void unmap_hugepage_range(struct vm_area
 
 	for (address = start; address < end; address += HPAGE_SIZE) {
 		pte = huge_pte_offset(mm, address);
-		if (pte_none(*pte))
+		if (!pte || pte_none(*pte))
 			continue;
 		page = pte_page(*pte);
 		huge_page_release(page);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/m68k/ifpsp060/iskeleton.S linux-2.4.27-rc4/arch/m68k/ifpsp060/iskeleton.S
--- linux-2.4.26/arch/m68k/ifpsp060/iskeleton.S	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/m68k/ifpsp060/iskeleton.S	2004-07-30 16:25:27.000000000 +0000
@@ -196,14 +196,58 @@ _060_real_cas2:
 | Expected outputs:
 |	d0 = 0 -> success; non-zero -> failure
 |
-| Linux/68k: As long as ints are disabled, no swapping out should
-| occur (hopefully...)
+| Linux/m68k: Make sure the page is properly paged in, so we use
+| plpaw and handle any exception here. The kernel must not be
+| preempted until _060_unlock_page(), so that the page stays mapped.
 |
 	.global		_060_real_lock_page
 _060_real_lock_page:
-	clr.l		%d0
+	move.l	%d2,-(%sp)
+	| load sfc/dfc
+	tst.b	%d0
+	jne	1f
+	moveq	#1,%d0
+	jra	2f
+1:	moveq	#5,%d0
+2:	movec.l	%dfc,%d2
+	movec.l	%d0,%dfc
+	movec.l	%d0,%sfc
+
+	clr.l	%d0
+	| prefetch address
+	.chip	68060
+	move.l	%a0,%a1
+1:	plpaw	(%a1)
+	addq.w	#1,%a0
+	tst.b	%d1
+	jeq	2f
+	addq.w	#2,%a0
+2:	plpaw	(%a0)
+3:	.chip	68k
+
+	| restore sfc/dfc
+	movec.l	%d2,%dfc
+	movec.l	%d2,%sfc
+	move.l	(%sp)+,%d2
 	rts
 
+.section __ex_table,"a"
+	.align	4
+	.long	1b,11f
+	.long	2b,21f
+.previous
+.section .fixup,"ax"
+	.even
+11:	move.l	#0x020003c0,%d0
+	or.l	%d2,%d0
+	swap	%d0
+	jra	3b
+21:	move.l	#0x02000bc0,%d0
+	or.l	%d2,%d0
+	swap	%d0
+	jra	3b
+.previous
+
 |
 | _060_unlock_page():
 |
@@ -216,8 +260,7 @@ _060_real_lock_page:
 |	d0 = `xxxxxxff -> supervisor; `xxxxxx00 -> user
 |	d1 = `xxxxxxff -> longword; `xxxxxx00 -> word
 |
-| Linux/68k: As we do no special locking operation, also no unlocking
-| is needed...
+| Linux/m68k: perhaps reenable preemption here...
 
 	.global		_060_real_unlock_page
 _060_real_unlock_page:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/m68k/kernel/setup.c linux-2.4.27-rc4/arch/m68k/kernel/setup.c
--- linux-2.4.26/arch/m68k/kernel/setup.c	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/m68k/kernel/setup.c	2004-07-30 16:31:37.000000000 +0000
@@ -244,6 +244,18 @@ void __init setup_arch(char **cmdline_p)
 	else if (CPU_IS_060)
 		m68k_is040or060 = 6;
 
+	if (CPU_IS_060) {
+		u32 pcr;
+
+		asm (".chip 68060; movec %%pcr,%0; .chip 68k"
+		     : "=d" (pcr));
+		if (((pcr >> 8) & 0xff) <= 5) {
+			printk("Enabling workaround for errata I14\n");
+			asm (".chip 68060; movec %0,%%pcr; .chip 68k"
+			     : : "d" (pcr | 0x20));
+		}
+	}
+
 	/* FIXME: m68k_fputype is passed in by Penguin booter, which can
 	 * be confused by software FPU emulation. BEWARE.
 	 * We should really do our own FPU check at startup.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/m68k/mac/iop.c linux-2.4.27-rc4/arch/m68k/mac/iop.c
--- linux-2.4.26/arch/m68k/mac/iop.c	2003-06-13 14:51:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/m68k/mac/iop.c	2004-07-30 16:31:29.000000000 +0000
@@ -261,7 +261,7 @@ void __init iop_preinit(void)
 		} else {
 			iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA;
 		}
-		iop_base[IOP_NUM_SCC]->status_ctrl = 0;
+		iop_base[IOP_NUM_ISM]->status_ctrl = 0;
 		iop_ism_present = 1;
 	} else {
 		iop_base[IOP_NUM_ISM] = NULL;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ppc/boot/simple/m8260_tty.c linux-2.4.27-rc4/arch/ppc/boot/simple/m8260_tty.c
--- linux-2.4.26/arch/ppc/boot/simple/m8260_tty.c	2004-04-14 13:05:27.000000000 +0000
+++ linux-2.4.27-rc4/arch/ppc/boot/simple/m8260_tty.c	2004-07-30 16:30:02.000000000 +0000
@@ -156,7 +156,7 @@ serial_init(int ignored, bd_t *bd)
 	sccp->scc_sccm = 0;
 	sccp->scc_scce = 0xffff;
 	sccp->scc_dsr = 0x7e7e;
-	sccp->scc_pmsr = 0x3000;
+	sccp->scc_psmr = 0x3000;
 
 	/* Wire BRG1 to SCC1.  The console driver will take care of
 	 * others.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ppc/cpm2_io/fcc_enet.c linux-2.4.27-rc4/arch/ppc/cpm2_io/fcc_enet.c
--- linux-2.4.26/arch/ppc/cpm2_io/fcc_enet.c	2004-04-14 13:05:27.000000000 +0000
+++ linux-2.4.27-rc4/arch/ppc/cpm2_io/fcc_enet.c	2004-07-30 16:28:21.000000000 +0000
@@ -305,6 +305,8 @@ struct fcc_enet_private {
 	ushort	skb_cur;
 	ushort	skb_dirty;
 
+	atomic_t n_pkts;        /* Number of packets in tx ring */
+
 	/* CPM dual port RAM relative addresses.
 	*/
 	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
@@ -396,13 +398,15 @@ fcc_enet_start_xmit(struct sk_buff *skb,
 	bdp->cbd_datlen = skb->len;
 	bdp->cbd_bufaddr = __pa(skb->data);
 
+	spin_lock_irq(&cep->lock);
+
 	/* Save skb pointer. */
 	cep->tx_skbuff[cep->skb_cur] = skb;
 
 	cep->stats.tx_bytes += skb->len;
 	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
 
-	spin_lock_irq(&cep->lock);
+	atomic_inc(&cep->n_pkts);
 
 	/* Send it on its way.  Tell CPM its ready, interrupt when done,
 	 * its the last BD of the frame, and to put the CRC on the end.
@@ -421,9 +425,12 @@ fcc_enet_start_xmit(struct sk_buff *skb,
 	else
 		bdp++;
 
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		netif_stop_queue(dev);
+	/* If the tx_ring is full, stop the queue */
+	if (atomic_read(&cep->n_pkts) >= (TX_RING_SIZE-1)) {
+	  if (!netif_queue_stopped(dev)) {
+	  	netif_stop_queue(dev);
 		cep->tx_full = 1;
+	  }
 	}
 
 	cep->cur_tx = (cbd_t *)bdp;
@@ -542,6 +549,8 @@ fcc_enet_interrupt(int irq, void * dev_i
 		dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]);
 		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
+		atomic_dec(&cep->n_pkts);
+
 		/* Update pointer to next buffer descriptor to be transmitted. */
 		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
 			bdp = cep->tx_bd_base;
@@ -1782,6 +1791,7 @@ init_fcc_param(fcc_info_t *fip, struct n
 	while (cp->cp_cpcr & CPM_CR_FLG);
 
 	cep->skb_cur = cep->skb_dirty = 0;
+	atomic_set(&cep->n_pkts, 0);
 }
 
 /* Let 'er rip.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ppc/kernel/head_44x.S linux-2.4.27-rc4/arch/ppc/kernel/head_44x.S
--- linux-2.4.26/arch/ppc/kernel/head_44x.S	2004-04-14 13:05:27.000000000 +0000
+++ linux-2.4.27-rc4/arch/ppc/kernel/head_44x.S	2004-07-30 16:24:40.000000000 +0000
@@ -3,9 +3,26 @@
  *
  * Kernel execution entry point code.
  *
- * Matt Porter <mporter@mvista.com>
- *
- * Copyright 2002-2003 MontaVista Software, Inc.
+ *    Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org>
+ *      Initial PowerPC version.
+ *    Copyright (c) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *      Rewritten for PReP
+ *    Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
+ *      Low-level exception handers, MMU support, and rewrite.
+ *    Copyright (c) 1997 Dan Malek <dmalek@jlc.net>
+ *      PowerPC 8xx modifications.
+ *    Copyright (c) 1998-1999 TiVo, Inc.
+ *      PowerPC 403GCX modifications.
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *      PowerPC 403GCX/405GP modifications.
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405 modifications
+ *      PowerPC 403GCX/405GP modifications.
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *    Copyright 2002-2004 MontaVista Software, Inc.
+ *      PowerPC 44x support, Matt Porter <mporter@kernel.crashing.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
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/ppc/kernel/m8260_setup.c linux-2.4.27-rc4/arch/ppc/kernel/m8260_setup.c
--- linux-2.4.26/arch/ppc/kernel/m8260_setup.c	2004-04-14 13:05:27.000000000 +0000
+++ linux-2.4.27-rc4/arch/ppc/kernel/m8260_setup.c	2004-07-30 16:28:42.000000000 +0000
@@ -93,7 +93,7 @@ m8260_calibrate_decr(void)
  */
 static uint rtc_time;
 
-static static int
+static int
 m8260_set_rtc_time(unsigned long time)
 {
 	rtc_time = time;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/config.in linux-2.4.27-rc4/arch/sh64/config.in
--- linux-2.4.26/arch/sh64/config.in	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/config.in	2004-07-30 16:32:12.000000000 +0000
@@ -58,8 +58,7 @@ bool 'Fixup misaligned loads/stores occu
 
 # Use 32-bit addressing for now.
 # EMI based.
-# P2 (UNCACHED) required to use identity mapping
-# P1 (CACHED) assumes non-identity.
+# (CACHED) assumes non-identity.
 
 #
 # Memory options
@@ -68,7 +67,6 @@ comment 'Memory options'
 
 int 'Memory size (in MB)' CONFIG_MEMORY_SIZE_IN_MB 64
 hex 'Cached Area Offset' CONFIG_CACHED_MEMORY_OFFSET 20000000
-hex 'Uncached Area Offset' CONFIG_UNCACHED_MEMORY_OFFSET 00000000
 hex 'Physical memory start address' CONFIG_MEMORY_START 80000000
 
 #
@@ -304,6 +302,7 @@ bool 'GDB Stub kernel debug' CONFIG_DEBU
 bool "Debug: audit page tables on return from syscall/exception/interrupt" CONFIG_SH64_PAGE_TABLE_AUDIT
 dep_bool "Debug: report TLB fill/purge activity through /proc/tlb" CONFIG_SH64_PROC_TLB $CONFIG_PROC_FS
 dep_bool "Debug: report ASIDS through /proc/asids" CONFIG_SH64_PROC_ASIDS $CONFIG_PROC_FS
+bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" CONFIG_SH64_SR_WATCH
 
 int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/defconfig linux-2.4.27-rc4/arch/sh64/defconfig
--- linux-2.4.26/arch/sh64/defconfig	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/defconfig	2004-07-30 16:31:38.000000000 +0000
@@ -490,6 +490,7 @@ CONFIG_FONT_8x16=y
 # CONFIG_SH64_PAGE_TABLE_AUDIT is not set
 # CONFIG_SH64_PROC_TLB is not set
 # CONFIG_SH64_PROC_ASIDS is not set
+# CONFIG_SH64_SR_WATCH is not set
 
 #
 # Library routines
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/kernel/entry.S linux-2.4.27-rc4/arch/sh64/kernel/entry.S
--- linux-2.4.26/arch/sh64/kernel/entry.S	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/kernel/entry.S	2004-07-30 16:29:27.000000000 +0000
@@ -1607,12 +1607,6 @@ poke_real_address_q:
 	shlli	r36, 31, r36
 	andc	r1, r36, r1	/* turn sr.mmu off in real mode section */
 
-	/* Bodge : force sr.watch high on return.  Can't understand why else this
-	   isn't happening. */
-	movi	1, r38
-	shlli	r38, 26, r38
-	or	r38, r0, r0
-
 	putcon	r1, ssr
 	_loada	.poke0-CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */
 	_loada	1f, r37		/* virtual mode return addr */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/kernel/head.S linux-2.4.27-rc4/arch/sh64/kernel/head.S
--- linux-2.4.26/arch/sh64/kernel/head.S	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/kernel/head.S	2004-07-30 16:27:29.000000000 +0000
@@ -37,18 +37,29 @@
 #define MMUDR_END	DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP
 #define MMUDR_STEP	TLB_STEP
 
+/* Safety check : CONFIG_CACHED_MEMORY_OFFSET has to be a multiple of 512Mb */
+#if (CONFIG_CACHED_MEMORY_OFFSET & ((1UL<<29)-1))
+#error "CONFIG_CACHED_MEMORY_OFFSET must be a multiple of 512Mb"
+#endif
+
 /*
  * MMU defines: Fixed TLBs.
  */
-#define MMUIR_TEXT_H	0x0000000000000003 | (CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START)
+/* Deal safely with the case where the base of RAM is not 512Mb aligned */
+
+#define ALIGN_512M_MASK (0xffffffffe0000000)
+#define ALIGNED_EFFECTIVE ((CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START) & ALIGN_512M_MASK)
+#define ALIGNED_PHYSICAL (CONFIG_MEMORY_START & ALIGN_512M_MASK)
+
+#define MMUIR_TEXT_H	(0x0000000000000003 | ALIGNED_EFFECTIVE)
 			/* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */
 
-#define MMUIR_TEXT_L	0x000000000000009a | (CONFIG_MEMORY_START)
+#define MMUIR_TEXT_L	(0x000000000000009a | ALIGNED_PHYSICAL)
 			/* 512 Mb, Cacheable, Write-back, execute, Not User, Ph. Add. */
 
-#define MMUDR_CACHED_H	0x0000000000000003 | (CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START)
+#define MMUDR_CACHED_H	0x0000000000000003 | ALIGNED_EFFECTIVE
 			/* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */
-#define MMUDR_CACHED_L	0x000000000000015a | (CONFIG_MEMORY_START)
+#define MMUDR_CACHED_L	0x000000000000015a | ALIGNED_PHYSICAL
 			/* 512 Mb, Cacheable, Write-back, read/write, Not User, Ph. Add. */
 
 #ifdef CONFIG_ICACHE_DISABLED
@@ -209,15 +220,19 @@ clear_DTLB:
 	/* Map one big (512Mb) page for ITLB */
 	movi	MMUIR_FIRST, r21
 	movi	MMUIR_TEXT_L, r22	/* PTEL first */
+	add.l	r22, r63, r22		/* Sign extend */
 	putcfg	r21, 1, r22		/* Set MMUIR[0].PTEL */
 	movi	MMUIR_TEXT_H, r22	/* PTEH last */
+	add.l	r22, r63, r22		/* Sign extend */
 	putcfg	r21, 0, r22		/* Set MMUIR[0].PTEH */
 	
 	/* Map one big CACHED (512Mb) page for DTLB */
 	movi	MMUDR_FIRST, r21
 	movi	MMUDR_CACHED_L, r22	/* PTEL first */
+	add.l	r22, r63, r22		/* Sign extend */
 	putcfg	r21, 1, r22		/* Set MMUDR[0].PTEL */
 	movi	MMUDR_CACHED_H, r22	/* PTEH last */
+	add.l	r22, r63, r22		/* Sign extend */
 	putcfg	r21, 0, r22		/* Set MMUDR[0].PTEH */
 	
 	/*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/kernel/pci_sh5.c linux-2.4.27-rc4/arch/sh64/kernel/pci_sh5.c
--- linux-2.4.26/arch/sh64/kernel/pci_sh5.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/kernel/pci_sh5.c	2004-07-30 16:24:18.000000000 +0000
@@ -320,43 +320,70 @@ static int __init map_cayman_irq(struct 
 {
 	int result = -1;
 
-	if (dev->bus->number == 0) {
-	        switch ((slot + (pin-1)) & 3) {
-	        case 0:
-	          result = IRQ_INTA;
-		  break;
-                case 1:
-	          result = IRQ_INTB;
-		  break;
-                case 2:
-	          result = IRQ_INTC;
-		  break;
-		case 3:
-		  result = IRQ_INTD;
-		  break;
-                }
-        }
-
-	if (dev->bus->number == 2) {
-	        switch((slot + (pin-1)) & 3) {
-	        case 0:
-	          result = IRQ_P2INTA;
-		  break;
-                case 1:
-	          result = IRQ_P2INTB;
-		  break;
-                case 2:
-	          result = IRQ_P2INTC;
-		  break;
-                case 3:
-	          result = IRQ_P2INTD;
-		  break;
-                }
-        }
-
-	dprintk("map_cayman_irq for dev %d on bus %d slot %d, pin is %d : irq=%d\n",
-	       dev->devfn,dev->bus->number,slot,pin,result);
+	/* The complication here is that the PCI IRQ lines from the Cayman's 2
+	   5V slots get into the CPU via a different path from the IRQ lines
+	   from the 3 3.3V slots.  Thus, we have to detect whether the card's
+	   interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
+	   at the point where we cross from 5V to 3.3V is not the normal case.
+
+	   The added complication is that we don't know that the 5V slots are
+	   always bus 2, because a card containing a PCI-PCI bridge may be
+	   plugged into a 3.3V slot, and this changes the bus numbering.
+
+	   Also, the Cayman has an intermediate PCI bus that goes a custom
+	   expansion board header (and to the secondary bridge).  This bus has
+	   never been used in practice.
+
+	   The 1ary onboard PCI-PCI bridge is device 3 on bus 0
+	   The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge.
+	   */
+
+	struct slot_pin {
+		int slot;
+		int pin;
+	} path[4];
+	int i=0;
+	int base;
+
+	while (dev->bus->number > 0) {
+
+		slot = path[i].slot = PCI_SLOT(dev->devfn);
+		pin = path[i].pin = bridge_swizzle(pin, slot);
+		dev = dev->bus->self;
+		i++;
+		if (i > 3) panic("PCI path to root bus too long!\n");
+	}
 
+	slot = PCI_SLOT(dev->devfn);
+	/* This is the slot on bus 0 through which the device is eventually
+	   reachable. */
+
+	/* Now work back up. */
+	if ((slot < 3) || (i == 0)) {
+		/* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
+		   swizzle now. */
+		result = IRQ_INTA + bridge_swizzle(pin, slot) - 1;
+	} else {
+		i--;
+		slot = path[i].slot;
+		pin  = path[i].pin;
+		if (slot > 0) {
+			panic("PCI expansion bus device found - not handled!\n");
+		} else {
+			if (i > 0) {
+				/* 5V slots */
+				i--;
+				slot = path[i].slot;
+				pin  = path[i].pin;
+				/* 'pin' was swizzled earlier wrt slot, don't do it again. */
+				result = IRQ_P2INTA + (pin - 1);
+			} else {
+				/* IRQ for 2ary PCI-PCI bridge : unused */
+				result = -1;
+			}
+		}
+	}
+	
 	return result;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/kernel/time.c linux-2.4.27-rc4/arch/sh64/kernel/time.c
--- linux-2.4.26/arch/sh64/kernel/time.c	2004-02-18 13:36:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/kernel/time.c	2004-07-30 16:29:47.000000000 +0000
@@ -404,13 +404,14 @@ static __init unsigned int get_cpu_mhz(v
 {
 	unsigned int count;
 	unsigned long __dummy;
-	
+	unsigned long ctc_val_init, ctc_val;
+
 	/*
 	** Regardless the toolchain, force the compiler to use the
 	** arbitrary register r3 as a clock tick counter.
 	** NOTE: r3 must be in accordance with rtc_interrupt()
 	*/
-	register unsigned long long  __clock_tick_count __asm__ ("r3");
+	register unsigned long long  __rtc_irq_flag __asm__ ("r3");
 
 	sti();
 	do {} while (ctrl_inb(R64CNT) != 0);
@@ -419,13 +420,17 @@ static __init unsigned int get_cpu_mhz(v
 	/*
 	 * r3 is arbitrary. CDC does not support "=z".
 	 */
+	ctc_val_init = 0xffffffff;
+	ctc_val = ctc_val_init;
+
 	asm volatile("gettr	" __t0 ", %1\n\t"
+		     "putcon	%0, cr62\n\t"
 		     "and	%2, r63, %2\n\t"
 		     "_pta	4, " __t0 "\n\t"
-		     "addi	%0, 1, %0\n\t"
 		     "beq/l	%2, r63, " __t0 "\n\t"
 		     "ptabs	%1, " __t0 "\n\t"
-		: "=r"(count), "=r" (__dummy), "=r" (__clock_tick_count)
+		     "getcon	cr62, %0\n\t"
+		: "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag)
 		: "0" (0));
 	cli();
 	/*
@@ -445,11 +450,13 @@ static __init unsigned int get_cpu_mhz(v
          * ....
 	 *
 	 * SH-5:
-	 * CPU clock = 2 stages * loop
-         * ....
+	 * Use CTC register to count.  This approach returns the right value
+	 * even if the I-cache is disabled (e.g. whilst debugging.)
 	 *
 	 */
 
+	count = ctc_val_init - ctc_val; /* CTC counts down */
+
 #if defined (CONFIG_SH_SIMULATOR)
 	/*
 	 * Let's pretend we are a 5MHz SH-5 to avoid a too
@@ -457,18 +464,13 @@ static __init unsigned int get_cpu_mhz(v
 	 * calibration within a reasonable time.
 	 */
 	return 5000000;
-#elif defined (CONFIG_ICACHE_DISABLED)
-	/*
-	 * Let's pretend we are a 300MHz SH-5.
-	 */
-	return 300000000;
 #else
 	/*
 	 * This really is count by the number of clock cycles
-         * per loop (2) by the ratio between a complete R64CNT
+         * by the ratio between a complete R64CNT
          * wrap-around (128) and CUI interrupt being raised (64).
 	 */
-	return count*2*2;
+	return count*2;
 #endif
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/lib/io.c linux-2.4.27-rc4/arch/sh64/lib/io.c
--- linux-2.4.26/arch/sh64/lib/io.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/lib/io.c	2004-07-30 16:25:22.000000000 +0000
@@ -27,17 +27,23 @@
 
 #define dprintk(x...)
 
-//#define io_addr(x)  (((unsigned)(x) & 0x000fffff)| PCI_ST50_IO_ADDR )
-
+static int io_addr(int x) {
+	if (x < 0x400) {
 #ifdef CONFIG_SH_CAYMAN
-extern unsigned long smsc_virt;
-extern unsigned long pciio_virt;
-#define io_addr(x)  ( ((x)<0x400) ? \
-			(((x) << 2)|smsc_virt) : \
-			((unsigned long)(x)+pciio_virt) )
+		return (x << 2) | smsc_superio_virt;
+#else
+		panic ("Illegal access to I/O port 0x%04x\n", x);
+		return 0;
+#endif
+	} else {
+#ifdef CONFIG_PCI
+		return (x + pciio_virt);
 #else
-#define io_addr(x)  ((unsigned long)(x)+pciio_virt)
+		panic ("Illegal access to I/O port 0x%04x\n", x);
+		return 0;
 #endif
+	}
+}
 
 unsigned long inb(unsigned long port)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/mach-cayman/irq.c linux-2.4.27-rc4/arch/sh64/mach-cayman/irq.c
--- linux-2.4.26/arch/sh64/mach-cayman/irq.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/mach-cayman/irq.c	2004-07-30 16:30:20.000000000 +0000
@@ -27,9 +27,12 @@ unsigned long epld_virt;
 #define EPLD_STATUS_BASE (epld_virt + 0x10)
 #define EPLD_MASK_BASE   (epld_virt + 0x20)
 
+/* Note the SMSC SuperIO chip and SMSC LAN chip interrupts are all muxed onto
+   the same SH-5 interrupt */
+
 static void cayman_interrupt_smsc(int irq, void *dev_id, struct pt_regs *regs)
 {
-        printk(KERN_INFO "CAYMAN: spurious interrupt\n");
+        printk(KERN_INFO "CAYMAN: spurious SMSC interrupt\n");
 }
 
 static void cayman_interrupt_pci2(int irq, void *dev_id, struct pt_regs *regs)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/mach-cayman/setup.c linux-2.4.27-rc4/arch/sh64/mach-cayman/setup.c
--- linux-2.4.26/arch/sh64/mach-cayman/setup.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/mach-cayman/setup.c	2004-07-30 16:25:15.000000000 +0000
@@ -74,7 +74,7 @@
 #define ITI TOP_PRIORITY	/* WDT Ints */
 
 /* Setup for the SMSC FDC37C935 */
-#define SMSC_BASE               0x04000000
+#define SMSC_SUPERIO_BASE	0x04000000
 #define SMSC_CONFIG_PORT_ADDR	0x3f0
 #define SMSC_INDEX_PORT_ADDR	SMSC_CONFIG_PORT_ADDR
 #define SMSC_DATA_PORT_ADDR	0x3f1
@@ -91,14 +91,14 @@
 
 #define SMSC_KEYBOARD_DEVICE 7
 
-#define SMSC_READ_INDEXED(index) ({ \
+#define SMSC_SUPERIO_READ_INDEXED(index) ({ \
 	outb((index), SMSC_INDEX_PORT_ADDR); \
 	inb(SMSC_DATA_PORT_ADDR); })
-#define SMSC_WRITE_INDEXED(val, index) ({ \
+#define SMSC_SUPERIO_WRITE_INDEXED(val, index) ({ \
 	outb((index), SMSC_INDEX_PORT_ADDR); \
 	outb((val),   SMSC_DATA_PORT_ADDR); })
 
-unsigned long smsc_virt;
+unsigned long smsc_superio_virt;
 
 /*
  * Platform dependent structures: maps and parms block.
@@ -145,13 +145,13 @@ int platform_int_priority[NR_INTC_IRQS] 
 	RES, RES, RES, RES, RES, RES, RES, ITI,	/* IRQ 56-63 */
 };
 
-static int __init smsc_setup(void)
+static int __init smsc_superio_setup(void)
 {
 	unsigned char devid, devrev;
 
-	smsc_virt = onchip_remap(SMSC_BASE, 1024, "SMSC");
-	if (!smsc_virt) {
-		panic("Unable to remap SMSC\n");
+	smsc_superio_virt = onchip_remap(SMSC_SUPERIO_BASE, 1024, "SMSC SuperIO");
+	if (!smsc_superio_virt) {
+		panic("Unable to remap SMSC SuperIO\n");
 	}
 
 	/* Initially the chip is in run state */
@@ -160,20 +160,20 @@ static int __init smsc_setup(void)
 	outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
 
 	/* Read device ID info */
-	devid = SMSC_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
-	devrev = SMSC_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
-	printk("SMSC devid %02x rev %02x\n", devid, devrev);
+	devid = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_ID_INDEX);
+	devrev = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_REV_INDEX);
+	printk("SMSC SuperIO devid %02x rev %02x\n", devid, devrev);
 
 	/* Select the keyboard device */
-	SMSC_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+	SMSC_SUPERIO_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX);
 
 	/* enable it */
-	SMSC_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);	
+	SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);	
 
 	/* Select the interrupts */
 	/* On a PC keyboard is IRQ1, mouse is IRQ12 */
-	SMSC_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX);
-	SMSC_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX);
+	SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX);
+	SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX);
 
 	/* Exit the configuraton state */
 	outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
@@ -184,7 +184,7 @@ static int __init smsc_setup(void)
 /* This is grotty, but, because kernel is always referenced on the link line
  * before any devices, this is safe.
  */
-__initcall(smsc_setup);
+__initcall(smsc_superio_setup);
 
 void __init platform_setup(void)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/mm/cache.c linux-2.4.27-rc4/arch/sh64/mm/cache.c
--- linux-2.4.26/arch/sh64/mm/cache.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/mm/cache.c	2004-07-30 16:28:38.000000000 +0000
@@ -474,7 +474,7 @@ static void sh64_dcache_purge_kernel_ran
 
 /* Assumes this address (+ (2**n_synbits) pages up from it) aren't used for
    anything else in the kernel */
-#define MAGIC_PAGE0_START 0xffffffffe0000000ULL
+#define MAGIC_PAGE0_START 0xffffffffec000000ULL
 
 static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned long eaddr)
 {
@@ -740,8 +740,8 @@ static void sh64_dcache_wback_current_us
 /****************************************************************************/
 
 /* These *MUST* lie in an area of virtual address space that's otherwise unused. */
-#define UNIQUE_EADDR_START 0xc0000000UL
-#define UNIQUE_EADDR_END   0xd0000000UL
+#define UNIQUE_EADDR_START 0xe0000000UL
+#define UNIQUE_EADDR_END   0xe8000000UL
 
 static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned long paddr)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sh64/vmlinux.lds.S linux-2.4.27-rc4/arch/sh64/vmlinux.lds.S
--- linux-2.4.26/arch/sh64/vmlinux.lds.S	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sh64/vmlinux.lds.S	2004-07-30 16:27:19.000000000 +0000
@@ -38,7 +38,6 @@ OUTPUT_FORMAT("elf32-sh64", "elf32-sh64"
 OUTPUT_ARCH(sh:sh5)
 
 #define C_PHYS(x) AT (ADDR(x) - CONFIG_CACHED_MEMORY_OFFSET)
-#define U_PHYS(x) AT (ADDR(x) - CONFIG_UNCACHED_MEMORY_OFFSET)
 
 ENTRY(__start)
 SECTIONS
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc/Makefile linux-2.4.27-rc4/arch/sparc/Makefile
--- linux-2.4.26/arch/sparc/Makefile	2001-07-28 19:12:37.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc/Makefile	2004-07-30 16:25:59.000000000 +0000
@@ -16,7 +16,7 @@ SHELL  =/bin/bash
 # 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)
+NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
 
 ifeq ($(NEW_GAS),y)
 AS              := $(AS) -32
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc/kernel/process.c linux-2.4.27-rc4/arch/sparc/kernel/process.c
--- linux-2.4.26/arch/sparc/kernel/process.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc/kernel/process.c	2004-07-30 16:25:59.000000000 +0000
@@ -54,6 +54,12 @@ void (*pm_idle)(void);
  */
 void (*pm_power_off)(void);
 
+/*
+ * sysctl - toggle power-off restriction for serial console 
+ * systems in machine_power_off()
+ */
+int scons_pwroff = 1;
+
 extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
 
 struct task_struct *last_task_used_math = NULL;
@@ -189,7 +195,7 @@ void machine_restart(char * cmd)
 void machine_power_off(void)
 {
 #ifdef CONFIG_SUN_AUXIO
-	if (auxio_power_register && !serial_console)
+	if (auxio_power_register && (!serial_console || scons_pwroff))
 		*auxio_power_register |= AUXIO_POWER_OFF;
 #endif
 	machine_halt();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc/kernel/unaligned.c linux-2.4.27-rc4/arch/sparc/kernel/unaligned.c
--- linux-2.4.26/arch/sparc/kernel/unaligned.c	2002-02-25 19:37:56.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc/kernel/unaligned.c	2004-07-30 16:26:58.000000000 +0000
@@ -136,8 +136,8 @@ static inline unsigned long *fetch_reg_a
 	return &win->locals[reg - 16];
 }
 
-static inline unsigned long compute_effective_address(struct pt_regs *regs,
-						      unsigned int insn)
+static unsigned long compute_effective_address(struct pt_regs *regs,
+					       unsigned int insn)
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
@@ -152,8 +152,8 @@ static inline unsigned long compute_effe
 	}
 }
 
-static inline unsigned long safe_compute_effective_address(struct pt_regs *regs,
-							   unsigned int insn)
+unsigned long safe_compute_effective_address(struct pt_regs *regs,
+					     unsigned int insn)
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc/mm/fault.c linux-2.4.27-rc4/arch/sparc/mm/fault.c
--- linux-2.4.26/arch/sparc/mm/fault.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc/mm/fault.c	2004-07-30 16:27:20.000000000 +0000
@@ -200,6 +200,25 @@ asmlinkage int lookup_fault(unsigned lon
 	return 0;
 }
 
+extern unsigned long safe_compute_effective_address(struct pt_regs *,
+						    unsigned int);
+
+static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
+{
+	unsigned int insn;
+
+	if (text_fault)
+		return regs->pc;
+
+	if (regs->psr & PSR_PS) {
+		insn = *(unsigned int *) regs->pc;
+	} else {
+		__get_user(insn, (unsigned int *) regs->pc);
+	}
+
+	return safe_compute_effective_address(regs, insn);
+}
+
 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
 			       unsigned long address)
 {
@@ -306,7 +325,7 @@ bad_area_nosemaphore:
 		info.si_errno = 0;
 		/* info.si_code set above to make clear whether
 		   this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
-		info.si_addr = (void *)address;
+		info.si_addr = (void *) compute_si_addr(regs, text_fault);
 		info.si_trapno = 0;
 		force_sig_info (SIGSEGV, &info, tsk);
 		return;
@@ -360,7 +379,7 @@ do_sigbus:
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *)address;
+	info.si_addr = (void *) compute_si_addr(regs, text_fault);
 	info.si_trapno = 0;
 	force_sig_info (SIGBUS, &info, tsk);
 	if (!from_user)
@@ -523,7 +542,7 @@ bad_area:
 	info.si_errno = 0;
 	/* info.si_code set above to make clear whether
 	   this was a SEGV_MAPERR or SEGV_ACCERR fault.  */
-	info.si_addr = (void *)address;
+	info.si_addr = (void *) address;
 	info.si_trapno = 0;
 	force_sig_info (SIGSEGV, &info, tsk);
 	return;
@@ -533,7 +552,7 @@ do_sigbus:
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = BUS_ADRERR;
-	info.si_addr = (void *)address;
+	info.si_addr = (void *) address;
 	info.si_trapno = 0;
 	force_sig_info (SIGBUS, &info, tsk);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc/prom/memory.c linux-2.4.27-rc4/arch/sparc/prom/memory.c
--- linux-2.4.26/arch/sparc/prom/memory.c	2000-02-01 07:37:19.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc/prom/memory.c	2004-07-30 16:32:12.000000000 +0000
@@ -156,7 +156,7 @@ void __init prom_meminit(void)
 			prom_prom_taken[iter].num_bytes =
 				(unsigned long) prom_reg_memlist[iter].reg_size;
 			prom_prom_taken[iter].theres_more =
-				&prom_phys_total[iter+1];
+				&prom_prom_taken[iter+1];
 		}
 		prom_prom_taken[iter-1].theres_more = 0x0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/Makefile linux-2.4.27-rc4/arch/sparc64/Makefile
--- linux-2.4.26/arch/sparc64/Makefile	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/Makefile	2004-07-30 16:31:54.000000000 +0000
@@ -12,7 +12,7 @@
 # line...
 SHELL  =/bin/bash
 
-CC		:= $(shell if gcc -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo gcc; else echo sparc64-linux-gcc; fi )
+CC		:= $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo $(CC); else echo sparc64-linux-gcc; fi )
 
 NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
 NEW_GAS := $(shell if $(LD) -V 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/config.in linux-2.4.27-rc4/arch/sparc64/config.in
--- linux-2.4.26/arch/sparc64/config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/config.in	2004-07-30 16:27:09.000000000 +0000
@@ -21,6 +21,8 @@ endmenu
 mainmenu_option next_comment
 comment 'General setup'
 
+source drivers/i2c/Config.in
+
 tristate 'UltraSPARC-III bootbus i2c controller driver' CONFIG_BBC_I2C
 
 define_bool CONFIG_VT y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/defconfig linux-2.4.27-rc4/arch/sparc64/defconfig
--- linux-2.4.26/arch/sparc64/defconfig	2004-04-14 13:05:27.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/defconfig	2004-07-30 16:27:19.000000000 +0000
@@ -17,6 +17,20 @@ CONFIG_KMOD=y
 #
 # General setup
 #
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+# CONFIG_SCx200_I2C is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PROC=y
 CONFIG_BBC_I2C=m
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
@@ -428,6 +442,7 @@ CONFIG_BLK_DEV_ALI15X3=y
 # CONFIG_WDC_ALI15X3 is not set
 CONFIG_BLK_DEV_AMD74XX=m
 # CONFIG_AMD74XX_OVERRIDE is not set
+CONFIG_BLK_DEV_ATIIXP=m
 CONFIG_BLK_DEV_CMD64X=y
 # CONFIG_BLK_DEV_TRIFLEX is not set
 CONFIG_BLK_DEV_CY82C693=m
@@ -1121,6 +1136,7 @@ CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/ioctl32.c linux-2.4.27-rc4/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.26/arch/sparc64/kernel/ioctl32.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/ioctl32.c	2004-07-30 16:31:09.000000000 +0000
@@ -1271,6 +1271,7 @@ static int fd_ioctl_trans(unsigned int f
 		case FDGETPRM32:
 		{
 			struct floppy_struct *f;
+			u32 u_name;
 
 			f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
 			if (!karg)
@@ -1286,7 +1287,8 @@ static int fd_ioctl_trans(unsigned int f
 			err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
 			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
 			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
-			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			err |= __get_user(u_name, &((struct floppy_struct32 *)arg)->name);
+			f->name = (void *) (long) u_name;
 			if (err) {
 				err = -EFAULT;
 				goto out;
@@ -3810,13 +3812,15 @@ static int blkpg_ioctl_trans(unsigned in
 {
 	struct blkpg_ioctl_arg a;
 	struct blkpg_partition p;
+	u32 u_data;
 	int err;
 	mm_segment_t old_fs = get_fs();
 	
 	err = get_user(a.op, &arg->op);
 	err |= __get_user(a.flags, &arg->flags);
 	err |= __get_user(a.datalen, &arg->datalen);
-	err |= __get_user((long)a.data, &arg->data);
+	err |= __get_user(u_data, &arg->data);
+	a.data = (void *) (long) u_data;
 	if (err) return err;
 	switch (a.op) {
 	case BLKPG_ADD_PARTITION:
@@ -4416,6 +4420,7 @@ COMPATIBLE_IOCTL(HDIO_SET_NOWERR)
 COMPATIBLE_IOCTL(HDIO_SET_32BIT)
 COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
 COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+COMPATIBLE_IOCTL(HDIO_DRIVE_TASK)
 COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
 COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
 COMPATIBLE_IOCTL(HDIO_SET_NICE)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/power.c linux-2.4.27-rc4/arch/sparc64/kernel/power.c
--- linux-2.4.26/arch/sparc64/kernel/power.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/power.c	2004-07-30 16:31:04.000000000 +0000
@@ -17,6 +17,12 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 
+/*
+ * sysctl - toggle power-off restriction for serial console 
+ * systems in machine_power_off()
+ */
+int scons_pwroff = 1; 
+
 #ifdef CONFIG_PCI
 static unsigned long power_reg = 0UL;
 
@@ -40,7 +46,7 @@ extern int serial_console;
 
 void machine_power_off(void)
 {
-	if (!serial_console) {
+	if (!serial_console || scons_pwroff) {
 #ifdef CONFIG_PCI
 		if (power_reg != 0UL) {
 			/* Both register bits seem to have the
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/process.c linux-2.4.27-rc4/arch/sparc64/kernel/process.c
--- linux-2.4.26/arch/sparc64/kernel/process.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/process.c	2004-07-30 16:27:53.000000000 +0000
@@ -453,7 +453,7 @@ void flush_thread(void)
 					page = pmd_alloc_one(NULL, 0);
 				pgd_set(pgd0, page);
 			}
-			pgd_cache = pgd_val(*pgd0) << 11UL;
+			pgd_cache = ((unsigned long) pgd_val(*pgd0)) << 11UL;
 		}
 		__asm__ __volatile__("stxa %0, [%1] %2\n\t"
 				     "membar #Sync"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/signal32.c linux-2.4.27-rc4/arch/sparc64/kernel/signal32.c
--- linux-2.4.26/arch/sparc64/kernel/signal32.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/signal32.c	2004-07-30 16:24:24.000000000 +0000
@@ -393,7 +393,7 @@ asmlinkage void do_rt_sigreturn32(struct
 {
 	struct rt_signal_frame32 *sf;
 	unsigned int psr;
-	unsigned pc, npc, fpu_save;
+	unsigned pc, npc, fpu_save, u_ss_sp;
 	mm_segment_t old_fs;
 	sigset_t set;
 	sigset_t32 seta;
@@ -444,7 +444,8 @@ asmlinkage void do_rt_sigreturn32(struct
 	if (fpu_save)
 		err |= restore_fpu_state32(regs, &sf->fpu_state);
 	err |= copy_from_user(&seta, &sf->mask, sizeof(sigset_t32));
-	err |= __get_user((long)st.ss_sp, &sf->stack.ss_sp);
+	err |= __get_user(u_ss_sp, &sf->stack.ss_sp);
+	st.ss_sp = (void *) (long) u_ss_sp;
 	err |= __get_user(st.ss_flags, &sf->stack.ss_flags);
 	err |= __get_user(st.ss_size, &sf->stack.ss_size);
 	if (err)
@@ -1030,7 +1031,7 @@ asmlinkage int svr4_setcontext(svr4_ucon
 	struct thread_struct *tp = &current->thread;
 	svr4_gregset_t  *gr;
 	mm_segment_t old_fs;
-	u32 pc, npc, psr;
+	u32 pc, npc, psr, u_ss_sp;
 	sigset_t set;
 	svr4_sigset_t setv;
 	int i, err;
@@ -1075,7 +1076,8 @@ asmlinkage int svr4_setcontext(svr4_ucon
 	if (_NSIG_WORDS >= 2)
 		set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32);
 	
-	err |= __get_user((long)st.ss_sp, &c->stack.sp);
+	err |= __get_user(u_ss_sp, &c->stack.sp);
+	st.ss_sp = (void *) (long) u_ss_sp;
 	err |= __get_user(st.ss_flags, &c->stack.flags);
 	err |= __get_user(st.ss_size, &c->stack.size);
 	if (err)
@@ -1545,9 +1547,9 @@ asmlinkage int do_sys32_sigstack(u32 u_s
 	
 	/* Now see if we want to update the new state. */
 	if (ssptr) {
-		void *ss_sp;
+		u32 ss_sp;
 
-		if (get_user((long)ss_sp, &ssptr->the_stack))
+		if (get_user(ss_sp, &ssptr->the_stack))
 			goto out;
 		/* If the current stack was set with sigaltstack, don't
 		   swap stacks while we are on it.  */
@@ -1570,13 +1572,15 @@ out:
 asmlinkage int do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp)
 {
 	stack_t uss, uoss;
+	u32 u_ss_sp = 0;
 	int ret;
 	mm_segment_t old_fs;
 	
-	if (ussa && (get_user((long)uss.ss_sp, &((stack_t32 *)(long)ussa)->ss_sp) ||
+	if (ussa && (get_user(u_ss_sp, &((stack_t32 *)(long)ussa)->ss_sp) ||
 		    __get_user(uss.ss_flags, &((stack_t32 *)(long)ussa)->ss_flags) ||
 		    __get_user(uss.ss_size, &((stack_t32 *)(long)ussa)->ss_size)))
 		return -EFAULT;
+	uss.ss_sp = (void *) (long) u_ss_sp;
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
 	ret = do_sigaltstack(ussa ? &uss : NULL, uossa ? &uoss : NULL, sp);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/sparc64_ksyms.c linux-2.4.27-rc4/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.4.26/arch/sparc64/kernel/sparc64_ksyms.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/sparc64_ksyms.c	2004-07-30 16:30:40.000000000 +0000
@@ -89,6 +89,7 @@ extern long sparc32_open(const char * fi
 extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
 extern int unregister_ioctl32_conversion(unsigned int cmd);
 extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space);
+extern void (*prom_palette)(int);
                 
 extern int __ashrdi3(int, int);
 
@@ -371,3 +372,5 @@ EXPORT_SYMBOL(do_BUG);
 #endif
 
 EXPORT_SYMBOL(tick_ops);
+
+EXPORT_SYMBOL(prom_palette);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/sys_sparc32.c linux-2.4.27-rc4/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.26/arch/sparc64/kernel/sys_sparc32.c	2004-04-14 13:05:27.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/sys_sparc32.c	2004-07-30 16:29:31.000000000 +0000
@@ -1316,7 +1316,7 @@ static int filldir(void * __buf, const c
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = (void *) dirent + reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
@@ -3056,9 +3056,12 @@ asmlinkage int sys32_sigaction (int sig,
 
         if (act) {
 		old_sigset_t32 mask;
+		u32 u_handler, u_restorer;
 		
-		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
-		ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
+		ret = get_user(u_handler, &act->sa_handler);
+		new_ka.sa.sa_handler = (void *) (long) u_handler;
+		ret |= __get_user(u_restorer, &act->sa_restorer);
+		new_ka.sa.sa_restorer = (void *) (long) u_restorer;
 		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
 		ret |= __get_user(mask, &act->sa_mask);
 		if (ret)
@@ -3097,8 +3100,11 @@ sys32_rt_sigaction(int sig, struct sigac
 	current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
 
         if (act) {
+		u32 u_handler, u_restorer;
+
 		new_ka.ka_restorer = restorer;
-		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret = get_user(u_handler, &act->sa_handler);
+		new_ka.sa.sa_handler = (void *) (long) u_handler;
 		ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
 		switch (_NSIG_WORDS) {
 		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
@@ -3107,7 +3113,8 @@ sys32_rt_sigaction(int sig, struct sigac
 		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
 		}
 		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
+		ret |= __get_user(u_restorer, &act->sa_restorer);
+		new_ka.sa.sa_restorer = (void *) (long) u_restorer;
                 if (ret)
                 	return -EFAULT;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/sys_sunos32.c linux-2.4.27-rc4/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.26/arch/sparc64/kernel/sys_sunos32.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/sys_sunos32.c	2004-07-30 16:29:24.000000000 +0000
@@ -296,7 +296,7 @@ static int sunos_filldir(void * __buf, c
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = (void *) dirent + reclen;
 	buf->curr = dirent;
 	buf->count -= reclen;
 	return 0;
@@ -376,7 +376,7 @@ static int sunos_filldirentry(void * __b
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	((char *) dirent) += reclen;
+	dirent = (void *) dirent + reclen;
 	buf->curr = dirent;
 	buf->count -= reclen;
 	return 0;
@@ -1309,10 +1309,12 @@ asmlinkage int sunos_sigaction (int sig,
 
 	if (act) {
 		old_sigset_t32 mask;
+		u32 u_handler;
 
-		if (get_user((long)new_ka.sa.sa_handler, &((struct old_sigaction32 *)A(act))->sa_handler) ||
+		if (get_user(u_handler, &((struct old_sigaction32 *)A(act))->sa_handler) ||
 		    __get_user(new_ka.sa.sa_flags, &((struct old_sigaction32 *)A(act))->sa_flags))
 			return -EFAULT;
+		new_ka.sa.sa_handler = (void *) (long) u_handler;
 		__get_user(mask, &((struct old_sigaction32 *)A(act))->sa_mask);
 		new_ka.sa.sa_restorer = NULL;
 		new_ka.ka_restorer = NULL;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/kernel/unaligned.c linux-2.4.27-rc4/arch/sparc64/kernel/unaligned.c
--- linux-2.4.26/arch/sparc64/kernel/unaligned.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/kernel/unaligned.c	2004-07-30 16:27:17.000000000 +0000
@@ -149,8 +149,8 @@ static unsigned long *fetch_reg_addr(uns
 	}
 }
 
-static inline unsigned long compute_effective_address(struct pt_regs *regs,
-						      unsigned int insn, unsigned int rd)
+unsigned long compute_effective_address(struct pt_regs *regs,
+					unsigned int insn, unsigned int rd)
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
@@ -166,7 +166,7 @@ static inline unsigned long compute_effe
 }
 
 /* This is just to make gcc think die_if_kernel does return... */
-static void unaligned_panic(char *str, struct pt_regs *regs)
+static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs)
 {
 	die_if_kernel(str, regs);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/mm/fault.c linux-2.4.27-rc4/arch/sparc64/mm/fault.c
--- linux-2.4.26/arch/sparc64/mm/fault.c	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/mm/fault.c	2004-07-30 16:31:44.000000000 +0000
@@ -203,14 +203,21 @@ outret:
 	return insn;
 }
 
-static void do_fault_siginfo(int code, int sig, unsigned long address)
+extern unsigned long compute_effective_address(struct pt_regs *, unsigned int, unsigned int);
+
+static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
+			     unsigned int insn, int fault_code)
 {
 	siginfo_t info;
 
 	info.si_code = code;
 	info.si_signo = sig;
 	info.si_errno = 0;
-	info.si_addr = (void *) address;
+	if (fault_code & FAULT_CODE_ITLB)
+		info.si_addr = (void *) regs->tpc;
+	else
+		info.si_addr = (void *)
+			compute_effective_address(regs, insn, 0);
 	info.si_trapno = 0;
 	force_sig_info(sig, &info, current);
 }
@@ -291,7 +298,7 @@ static void do_kernel_fault(struct pt_re
 		/* The si_code was set to make clear whether
 		 * this was a SEGV_MAPERR or SEGV_ACCERR fault.
 		 */
-		do_fault_siginfo(si_code, SIGSEGV, address);
+		do_fault_siginfo(si_code, SIGSEGV, regs, insn, fault_code);
 		return;
 	}
 
@@ -467,7 +474,7 @@ do_sigbus:
 	 * Send a sigbus, regardless of whether we were in kernel
 	 * or user mode.
 	 */
-	do_fault_siginfo(BUS_ADRERR, SIGBUS, address);
+	do_fault_siginfo(BUS_ADRERR, SIGBUS, regs, insn, fault_code);
 
 	/* Kernel mode? Handle exceptions or die */
 	if (regs->tstate & TSTATE_PRIV)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/mm/init.c linux-2.4.27-rc4/arch/sparc64/mm/init.c
--- linux-2.4.26/arch/sparc64/mm/init.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/mm/init.c	2004-07-30 16:27:29.000000000 +0000
@@ -1433,8 +1433,10 @@ void __init paging_init(void)
 	/* Now can init the kernel/bad page tables. */
 	pgd_set(&swapper_pg_dir[0], swapper_pmd_dir + (shift / sizeof(pgd_t)));
 	
-	sparc64_vpte_patchme1[0] |= (pgd_val(init_mm.pgd[0]) >> 10);
-	sparc64_vpte_patchme2[0] |= (pgd_val(init_mm.pgd[0]) & 0x3ff);
+	sparc64_vpte_patchme1[0] |=
+		(((unsigned long)pgd_val(init_mm.pgd[0])) >> 10);
+	sparc64_vpte_patchme2[0] |=
+		(((unsigned long)pgd_val(init_mm.pgd[0])) & 0x3ff);
 	flushi((long)&sparc64_vpte_patchme1[0]);
 	
 	/* Setup bootmem... */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/sparc64/prom/memory.c linux-2.4.27-rc4/arch/sparc64/prom/memory.c
--- linux-2.4.26/arch/sparc64/prom/memory.c	1999-08-31 18:23:30.000000000 +0000
+++ linux-2.4.27-rc4/arch/sparc64/prom/memory.c	2004-07-30 16:30:17.000000000 +0000
@@ -114,7 +114,7 @@ void __init prom_meminit(void)
 		prom_prom_taken[iter].num_bytes =
 			prom_reg_memlist[iter].reg_size;
 		prom_prom_taken[iter].theres_more =
-			&prom_phys_total[iter+1];
+			&prom_prom_taken[iter+1];
 	}
 	prom_prom_taken[iter-1].theres_more = 0x0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/boot/bootsect.S linux-2.4.27-rc4/arch/x86_64/boot/bootsect.S
--- linux-2.4.26/arch/x86_64/boot/bootsect.S	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/boot/bootsect.S	2004-07-30 16:30:03.000000000 +0000
@@ -234,9 +234,10 @@ read_it:
 die:	jne	die			# %es must be at 64kB boundary
 	xorw	%bx, %bx		# %bx is starting address within segment
 rp_read:
-#ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
+#ifdef __BIG_KERNEL__				
+					# look in setup.S for bootsect_kludge
 	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
-	lcall	bootsect_kludge		# bootsector + bootsect_kludge offset
+	lcall	*bootsect_kludge		# bootsector + bootsect_kludge offset
 #else
 	movw	%es, %ax
 	subw	$SYSSEG, %ax
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/ia32/ia32entry.S linux-2.4.27-rc4/arch/x86_64/ia32/ia32entry.S
--- linux-2.4.26/arch/x86_64/ia32/ia32entry.S	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/ia32/ia32entry.S	2004-07-30 16:26:38.000000000 +0000
@@ -71,7 +71,7 @@ ia32_tracesys:			 
 	movq %rsp,%rdi        /* &pt_regs -> arg1 */
 	call syscall_trace
 	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
-	addq $ARGOFFSET,%rsp	
+	RESTORE_REST
 	cmpl $(IA32_NR_syscalls),%eax
 	jae  1f
 	IA32_ARG_FIXUP
@@ -81,7 +81,7 @@ ia32_tracesys_end:	
 1:	SAVE_REST
 	movq %rsp,%rdi		/* &pt_regs -> arg1 */ 
 	call syscall_trace
-	addq $ARGOFFSET,%rsp
+	RESTORE_REST
 	jmp int_ret_from_sys_call
 		
 ia32_badsys:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/Makefile linux-2.4.27-rc4/arch/x86_64/kernel/Makefile
--- linux-2.4.26/arch/x86_64/kernel/Makefile	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/Makefile	2004-07-30 16:26:13.000000000 +0000
@@ -14,7 +14,8 @@ all: kernel.o head.o head64.o init_task.
 
 O_TARGET := kernel.o
 
-export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o pci-gart.o setup.o swiotlb.o
+export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o pci-gart.o setup.o \
+		swiotlb.o  bluesmoke.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/acpi.c linux-2.4.27-rc4/arch/x86_64/kernel/acpi.c
--- linux-2.4.26/arch/x86_64/kernel/acpi.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/acpi.c	2004-07-30 16:31:42.000000000 +0000
@@ -56,7 +56,10 @@ int acpi_sci_override_gsi __initdata;
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
    -------------------------------------------------------------------------- */
-
+#ifdef CONFIG_ACPI_PCI
+int acpi_noirq __initdata;	/* skip ACPI IRQ initialization */
+int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
+#endif
 int acpi_ht __initdata = 1;	/* enable HT */
 
 enum acpi_irq_model_id		acpi_irq_model;
@@ -119,11 +122,40 @@ __acpi_map_table (
 #endif
 }
 
+#ifdef CONFIG_ACPI_MMCONFIG
+
+u32 pci_mmcfg_base_addr;
+
+static int __init 
+acpi_parse_mcfg(unsigned long phys_addr,
+		unsigned long size)
+{
+	struct acpi_table_mcfg *mcfg = NULL;
+
+	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_ACPI_MMCONFIG */
+
 #ifdef CONFIG_X86_LOCAL_APIC
 
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 
-
 static int __init
 acpi_parse_madt (
 	unsigned long		phys_addr,
@@ -330,7 +362,7 @@ acpi_parse_nmi_src (
 
 #endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
 
-
+#ifdef CONFIG_HPET_TIMER
 static int __init
 acpi_parse_hpet (
 	unsigned long		phys_addr,
@@ -351,6 +383,7 @@ acpi_parse_hpet (
 
 	return 0;
 } 
+#endif	/* CONFIG_HPET_TIMER */
 
 #ifdef CONFIG_ACPI_BUS
 /*
@@ -457,17 +490,16 @@ acpi_boot_init (void)
 		return result;
 	}
 
-#ifdef CONFIG_X86_LOCAL_APIC
+#ifdef CONFIG_ACPI_MMCONFIG
+	result = acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
+	if (result < 0) {
+		printk(KERN_ERR PREFIX "Error %d parsing MCFG\n", result);
+	} else if (result > 1) {
+		printk(KERN_WARNING PREFIX "Multiple MCFG tables exist\n");
+	}
+#endif
 
-	/* this check should not need to be here -lenb */
-	/* If "nolocalapic" is specified don't look further */
-	extern int apic_disabled;
-	if (apic_disabled) {
-		printk(KERN_INFO PREFIX "Skipping Local/IO-APIC probe due to \"nolocalapic\"\n");
-		return 0;	
-	}	
-	printk(KERN_INFO PREFIX "Parsing Local APIC info in MADT\n"); 
-	
+#ifdef CONFIG_X86_LOCAL_APIC
 
 	/* 
 	 * MADT
@@ -573,9 +605,6 @@ acpi_boot_init (void)
 		return result;
 	}
 
-	/* Build a default routing table for legacy (ISA) interrupts. */
-	mp_config_acpi_legacy_irqs();
-
 	/* Record sci_int for use when looking for MADT sci_int override */
 	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);
 
@@ -593,6 +622,9 @@ acpi_boot_init (void)
 	if (!acpi_sci_override_gsi)
 		acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
 
+	/* Fill in identity legacy mapings where no override */
+	mp_config_acpi_legacy_irqs();
+
 	result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
 	if (result < 0) {
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
@@ -609,9 +641,11 @@ acpi_boot_init (void)
 	if (acpi_lapic && acpi_ioapic)
 		smp_found_config = 1;
 
+#ifdef CONFIG_HPET_TIMER
 	result = acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
 	if (result < 0) 
 		printk("ACPI: no HPET table found (%d).\n", result); 
+#endif
 
 #endif /*CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER*/
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/bluesmoke.c linux-2.4.27-rc4/arch/x86_64/kernel/bluesmoke.c
--- linux-2.4.26/arch/x86_64/kernel/bluesmoke.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/bluesmoke.c	2004-07-30 16:30:33.000000000 +0000
@@ -1,19 +1,25 @@
 /* 
  * Machine check handler.
  * K8 parts Copyright 2002,2003 Andi Kleen, SuSE Labs.
- * Rest from unknown author(s). 
+ * Additional K8 decoding and simplification Copyright 2003 Eric Morton, Newisys Inc
+ * Rest from unknown author(s).
  */
+#include <linux/config.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/notifier.h>
+#include <asm/bluesmoke.h>
 #include <asm/processor.h> 
 #include <asm/msr.h>
 #include <asm/kdebug.h>
-#include <linux/pci.h>
-#include <linux/timer.h>
+#include <asm/smp.h>
 
 static int mce_disabled __initdata;
 static unsigned long mce_cpus; 
@@ -25,18 +31,27 @@ static unsigned long mce_cpus; 
 static int banks;
 static unsigned long ignored_banks, disabled_banks;
 
+struct notifier_block *mc_notifier_list = NULL;
+EXPORT_SYMBOL(mc_notifier_list);
+
 static void generic_machine_check(struct pt_regs * regs, long error_code)
 {
 	int recover=1;
 	u32 alow, ahigh, high, low;
 	u32 mcgstl, mcgsth;
 	int i;
-	
+	struct notifier_mc_err mc_err;
+
 	rdmsr(MSR_IA32_MCG_STATUS, mcgstl, mcgsth);
 	if(mcgstl&(1<<0))	/* Recoverable ? */
 		recover=0;
 
-	printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", smp_processor_id(), mcgsth, mcgstl);
+	/* Make sure unrecoverable MCEs reach the console */
+	if(recover & 3)
+		oops_in_progress++;
+
+	printk(KERN_EMERG "CPU %d: Machine Check Exception: %08x%08x\n", 
+				smp_processor_id(), mcgsth, mcgstl);
 	
 	if (regs && (mcgstl & 2))
 		printk(KERN_EMERG "RIP <%02lx>:%016lx RSP %016lx\n", 
@@ -50,6 +65,10 @@ static void generic_machine_check(struct
 		rdmsr(MSR_IA32_MC0_STATUS+i*4,low, high);
 		if(high&(1<<31))
 		{
+			memset(&mc_err, 0x00, sizeof(mc_err));
+			mc_err.cpunum = safe_smp_processor_id();
+			mc_err.banknum = i;
+			mc_err.mci_status = ((u64)high << 32) | low;
 			if(high&(1<<29))
 				recover|=1;
 			if(high&(1<<25))
@@ -59,19 +78,26 @@ static void generic_machine_check(struct
 			if(high&(1<<27))
 			{
 				rdmsr(MSR_IA32_MC0_MISC+i*4, alow, ahigh);
+				mc_err.mci_misc = ((u64)ahigh << 32) | alow;
 				printk("[%08x%08x]", alow, ahigh);
 			}
 			if(high&(1<<26))
 			{
 				rdmsr(MSR_IA32_MC0_ADDR+i*4, alow, ahigh);
-				printk(" at %08x%08x", 
+				mc_err.mci_addr = ((u64)ahigh << 32) | alow;
+				printk(" at %08x%08x",
 					ahigh, alow);
 			}
+			rdmsr(MSR_IA32_MC0_CTL+i*4, alow, ahigh);
+			mc_err.mci_ctl = ((u64)ahigh << 32) | alow;
+
 			printk("\n");
+
 			/* Clear it */
 			wrmsr(MSR_IA32_MC0_STATUS+i*4, 0UL, 0UL);
 			/* Serialize */
 			wmb();
+			notifier_call_chain(&mc_notifier_list, X86_VENDOR_INTEL, &mc_err);
 		}
 	}
 
@@ -105,56 +131,51 @@ void do_machine_check(struct pt_regs * r
  *	K8 machine check.
  */
 
-static struct pci_dev *find_k8_nb(void)
-{ 
-	struct pci_dev *dev;
-	int cpu = smp_processor_id(); 
-	pci_for_each_dev(dev) {
-		if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 &&
-		    PCI_SLOT(dev->devfn) == (24+cpu))
-			return dev;
-	}
-	return NULL;
-}
-
+static char *k8bank[] = {
+	"data cache",
+	"instruction cache",
+	"bus unit",
+	"load/store unit",
+	"northbridge"
+};
 static char *transaction[] = { 
 	"instruction", "data", "generic", "reserved"
 }; 
 static char *cachelevel[] = { 
-	"level 0", "level 1", "level 2", "level generic"
+	"0", "1", "2", "generic"
 };
 static char *memtrans[] = { 
 	"generic error", "generic read", "generic write", "data read",
-	"data write", "instruction fetch", "prefetch", "snoop",
+	"data write", "instruction fetch", "prefetch", "evict", "snoop",
 	"?", "?", "?", "?", "?", "?", "?"
 };
 static char *partproc[] = { 
 	"local node origin", "local node response", 
-	"local node observed", "generic" 
+	"local node observed", "generic participation"
 };
 static char *timeout[] = { 
 	"request didn't time out",
 	"request timed out"
 };
 static char *memoryio[] = { 
-	"memory access", "res.", "i/o access", "generic"
-}; 
-static char *extendederr[] = { 
-	"ecc error", 
-	"crc error",
-	"sync error",
-	"mst abort",
-	"tgt abort",
-	"gart error",
-	"rmw error",
-	"wdog error",
-	"chipkill ecc error", 
+	"memory", "res.", "i/o", "generic"
+};
+static char *nbextendederr[] = { 
+	"ECC error", 
+	"CRC error",
+	"Sync error",
+	"Master abort",
+	"Target abort",
+	"GART error",
+	"RMW error",
+	"Watchdog error",
+	"Chipkill ECC error", 
 	"<9>","<10>","<11>","<12>",
 	"<13>","<14>","<15>"
-}; 
+};
 static char *highbits[32] = { 
-	[31] = "previous error lost", 
-	[30] = "error overflow",
+	[31] = "valid",
+	[30] = "error overflow (multiple errors)",
 	[29] = "error uncorrected",
 	[28] = "error enable",
 	[27] = "misc error valid",
@@ -169,128 +190,290 @@ static char *highbits[32] = { 
 	[11] = "res11",
 	[10] = "res10",
 	[9] = "res9",
-	[8] = "dram scrub error", 
+	[8] = "error found by scrub", 
 	[7] = "res7",
 	/* 6-4 ht link number of error */ 
 	[3] = "res3",
 	[2] = "res2",
-	[1] = "err cpu0",
-	[0] = "err cpu1",
+	[1] = "err cpu1",
+	[0] = "err cpu0",
 };
 
-static void check_k8_nb(int header)
-{
-	struct pci_dev *nb;
-	nb = find_k8_nb(); 
-	if (nb == NULL)
-		return;
-
-	u32 statuslow, statushigh;
-	pci_read_config_dword(nb, 0x48, &statuslow);
-	pci_read_config_dword(nb, 0x4c, &statushigh);
-	if (!(statushigh & (1<<31)))
-		return;
-	if (header) 
-		printk(KERN_ERR "CPU %d: Silent Northbridge MCE\n", smp_processor_id());
 
-	printk(KERN_ERR "Northbridge status %08x:%08x\n",
-	       statushigh,statuslow); 
+static void decode_k8_generic_errcode(unsigned int cpunum, u64 status)
+{
+	unsigned short errcode = status & 0xffff;
+	int i;
 
-	printk(KERN_ERR "    Error %s\n", extendederr[(statuslow >> 16) & 0xf]); 
+	for (i=0; i<32; i++) {
+		if (i==31 || i==28 || i==26)
+			continue;
+		if (highbits[i] && (status & (1UL<<(i+32)))) {
+			printk(KERN_ERR "CPU%d:   bit%d = %s\n", cpunum, i+32, highbits[i]);
+		}
+	}
 
-	unsigned short errcode = statuslow & 0xffff;	
-	switch ((statuslow >> 16) & 0xF) { 
-	case 5: 					
-		printk(KERN_ERR "    GART TLB error %s %s\n", 
-		       transaction[(errcode >> 2) & 3], 
+	if ((errcode & 0xFFF0) == 0x0010) {
+		printk(KERN_ERR "CPU%d: TLB error '%s transaction, level %s'\n",
+		       cpunum,
+		       transaction[(errcode >> 2) & 3],
 		       cachelevel[errcode & 3]);
-		break;
-	case 8:
-		printk(KERN_ERR "    ECC error syndrome %x\n", 
-		       (((statuslow >> 24) & 0xff)  << 8) | ((statushigh >> 15) & 0x7f));		
-		/*FALL THROUGH*/
-	default:
-		printk(KERN_ERR "    bus error %s, %s\n    %s\n    %s, %s\n",
+	}
+	else if ((errcode & 0xFF00) == 0x0100) {
+		printk(KERN_ERR "CPU%d: memory/cache error '%s mem transaction, %s transaction, level %s'\n",
+		       cpunum,
+		       memtrans[(errcode >> 4) & 0xf],
+		       transaction[(errcode >> 2) & 3],
+		       cachelevel[errcode & 3]);
+	}
+	else if ((errcode & 0xF800) == 0x0800) {
+		printk(KERN_ERR "CPU%d: bus error '%s, %s\n      %s mem transaction\n      %s access, level %s'\n",
+		       cpunum,
 		       partproc[(errcode >> 9) & 0x3],
 		       timeout[(errcode >> 8) & 1],
-			       memtrans[(errcode >> 4) & 0xf],
-			       memoryio[(errcode >> 2) & 0x3], 
-			       cachelevel[(errcode & 0x3)]); 
-		/* should only print when it was a HyperTransport related error. */
-		printk(KERN_ERR "    link number %x\n", (statushigh >> 4) & 3);
+		       memtrans[(errcode >> 4) & 0xf],
+		       memoryio[(errcode >> 2) & 0x3],
+		       cachelevel[(errcode & 0x3)]);
+	}
+}
+
+static void decode_k8_dc_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+	unsigned short errcode = status & 0xffff;
+
+	if(status&(3UL<<45)) {
+		printk(KERN_ERR "CPU%d: Data cache ECC error (syndrome %x)",
+		       cpunum,
+		       (u32) (status >> 47) & 0xff);
+		if(status&(1UL<<40)) {
+			printk(" found by scrubber");
+		}
+		printk("\n");
+	}
+
+	if ((errcode & 0xFFF0) == 0x0010) {
+		printk(KERN_ERR "CPU%d: TLB parity error in %s array\n",
+		       cpunum,
+		       (exterrcode == 0) ? "physical" : "virtual");
+	}
+
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_ic_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+	unsigned short errcode = status & 0xffff;
+
+	if(status&(3UL<<45)) {
+		printk(KERN_ERR "CPU%d: Instruction cache ECC error\n",
+		       cpunum);
+	}
+
+	if ((errcode & 0xFFF0) == 0x0010) {
+		printk(KERN_ERR "CPU%d: TLB parity error in %s array\n",
+		       cpunum,
+		       (exterrcode == 0) ? "physical" : "virtual");
+	}
+
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_bu_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+
+	if(status&(3UL<<45)) {
+		printk(KERN_ERR "CPU%d: L2 cache ECC error\n",
+		       cpunum);
+	}
+
+	printk(KERN_ERR "CPU%d: %s array error\n",
+	       cpunum,
+	       (exterrcode == 0) ? "Bus or cache" : "Cache tag");
+
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_ls_mc(unsigned int cpunum, u64 status)
+{
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_nb_mc(unsigned int cpunum, u64 status)
+{
+	unsigned short exterrcode = (status >> 16) & 0x0f;
+
+	printk(KERN_ERR "CPU%d: Northbridge %s\n", cpunum, nbextendederr[exterrcode]);
+
+	switch (exterrcode) { 
+	case 0:
+		printk(KERN_ERR "CPU%d: ECC syndrome = %x\n",
+		       cpunum,
+		       (u32) (status >> 47) & 0xff);
 		break;
-	} 
-	
+	case 8:	
+		printk(KERN_ERR "CPU%d: Chipkill ECC syndrome = %x\n",
+		       cpunum,
+	    	   (u32) ((((status >> 24) & 0xff) << 8) | ((status >> 47) & 0xff)));
+		break;
+	case 1: 
+	case 2:
+	case 3:
+	case 4:
+	case 6:
+		printk(KERN_ERR "CPU%d: link number = %x\n",
+		       cpunum,
+		       (u32) (status >> 36) & 0x7);
+		break;		   
+	}
 
-	int i;
-	for (i = 0; i < 32; i++) { 
-		if (i == 26 || i == 28) 
-			continue;
-		if (highbits[i] && (statushigh & (1<<i)))
-			printk(KERN_ERR "    %s\n", highbits[i]); 
+	decode_k8_generic_errcode(cpunum, status);
+}
+
+static void decode_k8_mc(unsigned int banknum, unsigned int cpunum, u64 status)
+{
+	switch(banknum) {
+		case 0:
+			decode_k8_dc_mc(cpunum, status);
+			break;
+		case 1:
+			decode_k8_ic_mc(cpunum, status);
+			break;
+		case 2:
+			decode_k8_bu_mc(cpunum, status);
+			break;
+		case 3:
+			decode_k8_ls_mc(cpunum, status);
+			break;
+		case 4:
+			decode_k8_nb_mc(cpunum, status);
+			break;
 	}
+}
 
-	if (statushigh & (1<<26)) { 
-		u32 addrhigh, addrlow; 
-		pci_read_config_dword(nb, 0x54, &addrhigh); 
-		pci_read_config_dword(nb, 0x50, &addrlow); 
-		printk(KERN_ERR "    NB error address %08x%08x\n", addrhigh,addrlow); 
+static void k8_poll_machine_check(void)
+{
+	int cpunum = safe_smp_processor_id();
+	int banknum;
+	u64 address, status, ctl;
+	struct notifier_mc_err mc_err;
+
+	for(banknum=0; banknum<banks; banknum++) {
+		if ((1UL<<banknum) & ignored_banks)
+			continue;
+
+		rdmsrl(MSR_IA32_MC0_STATUS+banknum*4, status);
+		if(status&(1UL<<63)) {
+			mc_err.cpunum = cpunum;
+			mc_err.banknum = banknum;
+			mc_err.mci_status = status;
+	        	rdmsrl(MSR_IA32_MC0_ADDR+banknum*4, address);
+			mc_err.mci_addr = address;
+
+			/* Can't write anything but zeros to status, or K8 will GPF */
+			wrmsrl(MSR_IA32_MC0_STATUS+banknum*4, 0UL);
+			printk(KERN_ERR "CPU%d %s polled machine check error status: %016Lx",
+			       cpunum,
+			       k8bank[banknum],
+			       status);
+			if(status&(1UL<<58)) {
+				printk(" at address %016Lx", address);
+			}
+			printk("\n");
+			rdmsrl(MSR_IA32_MC0_CTL+banknum*4, ctl);
+			mc_err.mci_ctl = ctl;
+			notifier_call_chain(&mc_notifier_list, X86_VENDOR_AMD, &mc_err);
+			decode_k8_mc(banknum, cpunum, status);
+		}
 	}
-	statushigh &= ~(1<<31); 
-	pci_write_config_dword(nb, 0x4c, statushigh); 		
 }
 
 static void k8_machine_check(struct pt_regs * regs, long error_code)
-{ 
-	u64 status, nbstatus;
-
-	rdmsrl(MSR_IA32_MCG_STATUS, status); 
-	if ((status & (1<<2)) == 0) { 
-		if (!regs) 
-			check_k8_nb(1);
-		return; 
+{
+	int norecover=1;
+	u64 addr, status, ctl, mcgst;
+	int banknum;
+	unsigned int cpunum = safe_smp_processor_id();
+	struct notifier_mc_err mc_err;
+
+	rdmsrl(MSR_IA32_MCG_STATUS, mcgst); 
+	if(mcgst&(1UL<<0)) {	/* Recoverable ? */
+		norecover=0;
 	}
-	printk(KERN_EMERG "CPU %d: Machine Check Exception: %016Lx\n", smp_processor_id(), status);
 
-	if (status & 1)
-		printk(KERN_EMERG "MCG_STATUS: unrecoverable\n"); 
+	/* Make sure unrecoverable MCEs reach the console */
+	if(norecover)
+		oops_in_progress++;
+
+	printk(KERN_EMERG "CPU %d: Machine Check Exception: %016Lx\n", cpunum, mcgst);
+
+	if (regs && (mcgst & (1UL<<1))) {
+		printk(KERN_EMERG "CPU%d: RIP <%02lx>:%016lx RSP %016lx %s\n",
+		       cpunum, regs->cs, regs->rip, regs->rsp,
+			   (mcgst & 1) ? "" : "!INEXACT!");
+	}
 
-	rdmsrl(MSR_IA32_MC0_STATUS+4*4, nbstatus); 
-	if ((nbstatus & (1UL<<63)) == 0)
-		goto others; 
-	
-	printk(KERN_EMERG "Northbridge Machine Check %s %016lx %lx\n", 
-	       regs ? "exception" : "timer",
-	       (unsigned long)nbstatus, error_code); 
-	if (nbstatus & (1UL<<62))
-		printk(KERN_EMERG "Lost at least one NB error condition\n"); 	
-	if (nbstatus & (1UL<<61))
-		printk(KERN_EMERG "Uncorrectable condition\n"); 
-	if (nbstatus & (1UL<57))
-		printk(KERN_EMERG "Unrecoverable condition\n"); 
-		
-	check_k8_nb(0);
+	for(banknum=0; banknum<banks; banknum++) {
+		if ((1UL<<banknum) & ignored_banks)
+			continue;
+		rdmsrl(MSR_IA32_MC0_STATUS+banknum*4, status);
+		if(status&(1UL<<63)) {
+			memset(&mc_err, 0x00, sizeof(mc_err));
+			mc_err.cpunum = cpunum;
+			mc_err.banknum = banknum;
+			mc_err.mci_status = status;
+			if(status&(1UL<<61)) {
+				norecover|=1; /* uncorrectable */
+			}
+			if(status &(1UL<<57)) {
+				norecover|=2; /* processor context corrupt */
+			}
+			printk(KERN_EMERG "CPU%d %s error status: %016Lx",
+			       cpunum,
+			       k8bank[banknum],
+			       status);
+			if(status&(1UL<<58)) {
+				rdmsrl(MSR_IA32_MC0_ADDR+banknum*4, addr);
+				mc_err.mci_addr = addr;
+				printk(" at address %016Lx", addr);
+			} else if ((banknum==4) && (((status>>16)&0x0f)==7)) {
+				/* NB watchdog, address reg has details but validity bit is not set */
+				rdmsrl(MSR_IA32_MC0_ADDR+banknum*4, addr);
+				mc_err.mci_addr = addr;
+				printk(" error details %016Lx", addr);
+			}
+			printk("\n");
+			rdmsrl(MSR_IA32_MC0_CTL+banknum*4, ctl);
+			mc_err.mci_ctl = ctl;
+			/* Clear it */
+            /* Can't write anything but zeros to status, or K8 will GPF */
+			wrmsrl(MSR_IA32_MC0_STATUS+banknum*4, 0UL);
+			/* Serialize */
+			wmb();
+			notifier_call_chain(&mc_notifier_list, X86_VENDOR_AMD, &mc_err);
+		}
+	}
 
-	if (nbstatus & (1UL<<58)) { 
-		u64 adr;
-		rdmsrl(MSR_IA32_MC0_ADDR+4*4, adr);
-		printk(KERN_EMERG "Address: %016lx\n", (unsigned long)adr);
+	if(norecover&2) {
+		panic("CPU context corrupt");
 	}
-	
-	wrmsrl(MSR_IA32_MC0_STATUS+4*4, 0); 
-	wrmsrl(MSR_IA32_MCG_STATUS, 0);
-       
- others:
-	generic_machine_check(regs, error_code); 
-} 
+	if(norecover&1) {
+		panic("Unable to continue");
+	}
+	printk(KERN_EMERG "Attempting to continue.\n");
+	mcgst&=~(1UL<<2);
+	wrmsrl(MSR_IA32_MCG_STATUS,mcgst);
+}
 
 static struct timer_list mcheck_timer;
-int mcheck_interval = 30*HZ; 
+int mcheck_interval = 60*HZ;
 
 #ifndef CONFIG_SMP 
 static void mcheck_timer_handler(unsigned long data)
 {
-	k8_machine_check(NULL,0);
+	k8_poll_machine_check();
 	mcheck_timer.expires = jiffies + mcheck_interval;
 	add_timer(&mcheck_timer);
 }
@@ -301,13 +484,13 @@ static void mcheck_timer_handler(unsigne
 
 static void mcheck_timer_other(void *data)
 { 
-	k8_machine_check(NULL, 0); 
+	k8_poll_machine_check();
 } 
 
 static void mcheck_timer_dist(void *data)
 { 
 	smp_call_function(mcheck_timer_other,0,0,0);
-	k8_machine_check(NULL, 0); 
+	k8_poll_machine_check();
 	mcheck_timer.expires = jiffies + mcheck_interval;
 	add_timer(&mcheck_timer);
 } 
@@ -334,17 +517,20 @@ static void __init k8_mcheck_init(struct
 
 	rdmsrl(MSR_IA32_MCG_CAP, cap); 
 	banks = cap&0xff; 
-	machine_check_vector = k8_machine_check; 
 	for (i = 0; i < banks; i++) { 
 		u64 val = ((1UL<<i) & disabled_banks) ? 0 : ~0UL; 
+		wrmsrl(MSR_IA32_MC0_STATUS+4*i,0UL);
+		wrmsrl(MSR_IA32_MC0_ADDR+4*i,0UL);
 		wrmsrl(MSR_IA32_MC0_CTL+4*i, val);
-		wrmsrl(MSR_IA32_MC0_STATUS+4*i,0); 
 	}
 
-	if (cap & (1<<8))
-		wrmsrl(MSR_IA32_MCG_CTL, 0xffffffffffffffffULL);
+	/* set up the vector first, before enabling MCG_CTL */
+	machine_check_vector = k8_machine_check;
+	set_in_cr4(X86_CR4_MCE);
 
-	set_in_cr4(X86_CR4_MCE);	   	
+	if (cap & (1<<8)) {
+		wrmsrl(MSR_IA32_MCG_CTL, 0xffffffffffffffffULL);
+	}
 
 	if (mcheck_interval && (smp_processor_id() == 0)) { 
 		init_timer(&mcheck_timer); 
@@ -399,7 +585,8 @@ static void __init generic_mcheck_init(s
 		wrmsr(MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
 	}
 	set_in_cr4(X86_CR4_MCE);
-	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", smp_processor_id());
+	printk(KERN_INFO "Intel machine check reporting enabled on CPU#%d.\n", 
+					 smp_processor_id());
 	done=1;
 }
 
@@ -419,8 +606,10 @@ void __init mcheck_init(struct cpuinfo_x
 	case X86_VENDOR_AMD:
 		if (c->x86 == 15 && !nok8) {
 			k8_mcheck_init(c); 
-			break;
+		} else {
+			generic_mcheck_init(c);
 		}
+		break;
 		/* FALL THROUGH */
 	default:
 	case X86_VENDOR_INTEL:
@@ -447,13 +636,13 @@ static int __init mcheck_enable(char *st
 	char *p;
 	while ((p = strsep(&str,",")) != NULL) { 
 		if (isdigit(*p))
-			mcheck_interval = simple_strtol(p,NULL,0) * HZ; 
+			mcheck_interval = simple_strtol(p,NULL,0) * HZ;
 		else if (!strcmp(p,"off"))
 			mce_disabled = 1; 
 		else if (!strncmp(p,"enable",6))
-			disabled_banks &= ~(1<<simple_strtol(p+6,NULL,0));
+			disabled_banks &= ~(1UL << simple_strtol(p+6,NULL,0));
 		else if (!strncmp(p,"disable",7))
-			disabled_banks |= ~(1<<simple_strtol(p+7,NULL,0));
+			disabled_banks |= 1UL << simple_strtol(p+7,NULL,0);
 		else if (!strcmp(p,"nok8"))
 			nok8 = 1;
 	}
@@ -461,4 +650,4 @@ static int __init mcheck_enable(char *st
 }
 
 __setup("nomce", mcheck_disable);
-__setup("mce", mcheck_enable);
+__setup("mce=", mcheck_enable);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/e820.c linux-2.4.27-rc4/arch/x86_64/kernel/e820.c
--- linux-2.4.26/arch/x86_64/kernel/e820.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/e820.c	2004-07-30 16:27:23.000000000 +0000
@@ -567,10 +567,10 @@ void __init parse_mem_cmdline (char ** c
 			acpi_strict = 1;
 		}
 
-		else if (!memcmp(from, "pci=noacpi", 10)) {
+		else if (!memcmp(from, "pci=noacpi", 10))
+			acpi_disable_pci();
+		else if (!memcmp(from, "acpi=noirq", 10))
 			acpi_noirq_set();
-		}
-
 		else if (!memcmp(from, "acpi_sci=edge", 13))
 			acpi_sci_flags.trigger =  1;
 		else if (!memcmp(from, "acpi_sci=level", 14))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/i8259.c linux-2.4.27-rc4/arch/x86_64/kernel/i8259.c
--- linux-2.4.26/arch/x86_64/kernel/i8259.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/i8259.c	2004-07-30 16:29:04.000000000 +0000
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/acpi.h>
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -439,6 +440,7 @@ void __init init_IRQ(void)
 #endif
 
 #ifndef CONFIG_VISWS
-	setup_irq(2, &irq2);
+	if (!acpi_ioapic)
+		setup_irq(2, &irq2);
 #endif
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/io_apic.c linux-2.4.27-rc4/arch/x86_64/kernel/io_apic.c
--- linux-2.4.26/arch/x86_64/kernel/io_apic.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/io_apic.c	2004-07-30 16:31:02.000000000 +0000
@@ -256,8 +256,9 @@ void __init check_ioapic(void) 
 							 PCI_VENDOR_ID);
 				vendor &= 0xffff;
 				switch (vendor) { 
-				case PCI_VENDOR_ID_NVIDIA: 
 				case PCI_VENDOR_ID_VIA:
+					return;
+				case PCI_VENDOR_ID_NVIDIA: 
 					printk(KERN_INFO 
      "PCI bridge %02x:%02x from %x found. Setting \"noapic\". Overwrite with \"apic\"\n",
 					       num,slot,vendor); 
@@ -1684,18 +1685,10 @@ static inline void check_timer(void)
 
 /*
  *
- * IRQ's that are handled by the old PIC in all cases:
+ * IRQ's that are handled by the PIC in the MPS IOAPIC case.
  * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
  *   Linux doesn't really care, as it's not actually used
  *   for any interrupt handling anyway.
- * - There used to be IRQ13 here as well, but all
- *   MPS-compliant must not use it for FPU coupling and we
- *   want to use exception 16 anyway.  And there are
- *   systems who connect it to an I/O APIC for other uses.
- *   Thus we don't mark it special any longer.
- *
- * Additionally, something is definitely wrong with irq9
- * on PIIX4 boards.
  */
 #define PIC_IRQS	(1<<2)
 
@@ -1703,7 +1696,11 @@ void __init setup_IO_APIC(void)
 {
 	enable_IO_APIC();
 
-	io_apic_irqs = ~PIC_IRQS;
+	if (acpi_ioapic)
+		io_apic_irqs = ~0;	/* all IRQs go through IOAPIC */
+	else
+		io_apic_irqs = ~PIC_IRQS;
+
 	printk("ENABLING IO-APIC IRQs\n");
 
 	/*
@@ -1858,7 +1855,7 @@ int io_apic_set_pci_routing (int ioapic,
 
 	entry.vector = assign_irq_vector(irq);
 
-	printk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
+	Dprintk(KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry (%d-%d -> 0x%x -> "
 		"IRQ %d Mode:%i Active:%i)\n", ioapic,
 		mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, edge_level, active_high_low);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/mpparse.c linux-2.4.27-rc4/arch/x86_64/kernel/mpparse.c
--- linux-2.4.26/arch/x86_64/kernel/mpparse.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/mpparse.c	2004-07-30 16:27:11.000000000 +0000
@@ -793,8 +793,6 @@ void __init mp_override_legacy_irq (
 	u32			global_irq)
 {
 	struct mpc_config_intsrc intsrc;
-	int			i = 0;
-	int			found = 0;
 	int			ioapic = -1;
 	int			pin = -1;
 
@@ -827,23 +825,9 @@ void __init mp_override_legacy_irq (
 		(intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, 
 		intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq);
 
-	/* 
-	 * If an existing [IOAPIC.PIN -> IRQ] routing entry exists we override it.
-	 * Otherwise create a new entry (e.g. global_irq == 2).
-	 */
-	for (i = 0; i < mp_irq_entries; i++) {
-		if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) 
-			&& (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) {
-			mp_irqs[i] = intsrc;
-			found = 1;
-			break;
-		}
-	}
-	if (!found) {
-		mp_irqs[mp_irq_entries] = intsrc;
-		if (++mp_irq_entries == MAX_IRQ_SOURCES)
-			panic("Max # of irq sources exceeded!\n");
-	}
+	mp_irqs[mp_irq_entries] = intsrc;
+	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+		panic("Max # of irq sources exceeded!\n");
 
 	return;
 }
@@ -874,13 +858,23 @@ void __init mp_config_acpi_legacy_irqs (
 	intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid;
 
 	/* 
-	 * Use the default configuration for the IRQs 0-15.  These may be
+	 * Use the default configuration for the IRQs 0-15.  Unless
 	 * overriden by (MADT) interrupt source override entries.
 	 */
 	for (i = 0; i < 16; i++) {
+		int idx;
 
-		if (i == 2)
-			continue;			/* Don't connect IRQ2 */
+		for (idx = 0; idx < mp_irq_entries; idx++)
+			if (mp_irqs[idx].mpc_srcbus == MP_ISA_BUS &&
+				(mp_irqs[idx].mpc_dstapic == intsrc.mpc_dstapic) &&
+				(mp_irqs[idx].mpc_srcbusirq == i ||
+				mp_irqs[idx].mpc_dstirq == i))
+					break;
+
+		if (idx != mp_irq_entries) {
+			printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+			continue;			  /* IRQ already used */
+		}
 
 		intsrc.mpc_irqtype = mp_INT;
 		intsrc.mpc_srcbusirq = i;		   /* Identity mapped */
@@ -942,8 +936,6 @@ void __init mp_parse_prt (void)
 			irq = entry->link.index;
 		}
 
-		irq = entry->link.index;
-
   		/* Don't set up the ACPI SCI because it's already set up */
                 if (acpi_fadt.sci_int == irq) {
                          entry->irq = irq; /*we still need to set entry's irq*/
@@ -982,10 +974,11 @@ void __init mp_parse_prt (void)
 			entry->irq = irq;
 
 		printk(KERN_DEBUG "%02x:%02x:%02x[%c] -> %d-%d -> vector 0x%02x"
-			" -> IRQ %d\n", entry->id.segment, entry->id.bus, 
-			entry->id.device, ('A' + entry->pin), 
-			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector, 
-			entry->irq);
+			" -> IRQ %d %s %s\n", entry->id.segment, entry->id.bus,
+			entry->id.device, ('A' + entry->pin),
+			mp_ioapic_routing[ioapic].apic_id, ioapic_pin, vector,
+			entry->irq, edge_level ? "level" : "edge",
+			active_high_low ? "low" : "high");
 	}
 
 	print_IO_APIC();
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/pci-gart.c linux-2.4.27-rc4/arch/x86_64/kernel/pci-gart.c
--- linux-2.4.26/arch/x86_64/kernel/pci-gart.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/pci-gart.c	2004-07-30 16:25:12.000000000 +0000
@@ -503,12 +503,13 @@ void __init pci_iommu_init(void)
 	no_agp = no_agp || (agp_init() < 0) || (agp_copy_info(&info) < 0); 
 #endif	
 
+#ifdef CONFIG_SWIOTLB
 	if (swiotlb) { 
 		no_iommu = 1;
 		printk(KERN_INFO "PCI-DMA: Using SWIOTLB\n"); 
 		return; 
-	} 
-
+	}
+#endif
 
 	if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT) || !iommu_aperture) { 
 		printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/pci-pc.c linux-2.4.27-rc4/arch/x86_64/kernel/pci-pc.c
--- linux-2.4.26/arch/x86_64/kernel/pci-pc.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/pci-pc.c	2004-07-30 16:29:40.000000000 +0000
@@ -646,7 +646,7 @@ char * __devinit pcibios_setup(char *str
 		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
 		return NULL;
 	} else if (!strncmp(str, "noacpi", 6)) {
-		acpi_noirq_set();
+		acpi_disable_pci();
 		return NULL;
 	}
 	return str;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/arch/x86_64/kernel/setup.c linux-2.4.27-rc4/arch/x86_64/kernel/setup.c
--- linux-2.4.26/arch/x86_64/kernel/setup.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/arch/x86_64/kernel/setup.c	2004-07-30 16:26:24.000000000 +0000
@@ -48,11 +48,8 @@
 #include <asm/bootsetup.h>
 #include <asm/proto.h>
 
-int acpi_disabled = 0;
-#ifdef	CONFIG_ACPI_BOOT
-int acpi_noirq __initdata = 0;	/* skip ACPI IRQ initialization */
-#endif
-
+int acpi_disabled;
+EXPORT_SYMBOL(acpi_disabled);
 
 int swiotlb;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/Config.in linux-2.4.27-rc4/crypto/Config.in
--- linux-2.4.26/crypto/Config.in	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/crypto/Config.in	2004-07-30 16:31:09.000000000 +0000
@@ -72,6 +72,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then
   tristate       '  AES cipher algorithms' CONFIG_CRYPTO_AES
   tristate       '  CAST5 (CAST-128) cipher algorithm' CONFIG_CRYPTO_CAST5
   tristate       '  CAST6 (CAST-256) cipher algorithm' CONFIG_CRYPTO_CAST6
+  tristate       '  TEA and XTEA cipher algorithms' CONFIG_CRYPTO_TEA
   tristate       '  ARC4 cipher algorithm' CONFIG_CRYPTO_ARC4
   if [ "$CONFIG_INET_IPCOMP" = "y" -o \
        "$CONFIG_INET_IPCOMP" = "m" -o \
@@ -81,6 +82,7 @@ if [ "$CONFIG_CRYPTO" = "y" ]; then
   else
     tristate       '  Deflate compression algorithm' CONFIG_CRYPTO_DEFLATE
   fi
+  tristate       '  Michael MIC keyed digest algorithm' CONFIG_CRYPTO_MICHAEL_MIC
   tristate       '  Testing module' CONFIG_CRYPTO_TEST
 fi
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/Makefile linux-2.4.27-rc4/crypto/Makefile
--- linux-2.4.26/crypto/Makefile	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/crypto/Makefile	2004-07-30 16:26:48.000000000 +0000
@@ -27,7 +27,9 @@ obj-$(CONFIG_CRYPTO_AES) += aes.o
 obj-$(CONFIG_CRYPTO_CAST5) += cast5.o
 obj-$(CONFIG_CRYPTO_CAST6) += cast6.o
 obj-$(CONFIG_CRYPTO_ARC4) += arc4.o
+obj-$(CONFIG_CRYPTO_TEA) += tea.o
 obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 
 obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/cipher.c linux-2.4.27-rc4/crypto/cipher.c
--- linux-2.4.26/crypto/cipher.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/crypto/cipher.c	2004-07-30 16:29:43.000000000 +0000
@@ -52,8 +52,8 @@ static int crypt(struct crypto_tfm *tfm,
 {
 	struct scatter_walk walk_in, walk_out;
 	const unsigned int bsize = crypto_tfm_alg_blocksize(tfm);
-	u8 tmp_src[nbytes > src->length ? bsize : 0];
-	u8 tmp_dst[nbytes > dst->length ? bsize : 0];
+	u8 tmp_src[bsize];
+	u8 tmp_dst[bsize];
 
 	if (!nbytes)
 		return 0;
@@ -68,19 +68,20 @@ static int crypt(struct crypto_tfm *tfm,
 
 	for(;;) {
 		u8 *src_p, *dst_p;
+		int in_place;
 
 		scatterwalk_map(&walk_in, 0);
 		scatterwalk_map(&walk_out, 1);
 		src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src);
 		dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst);
+		in_place = scatterwalk_samebuf(&walk_in, &walk_out,
+					       src_p, dst_p);
 
 		nbytes -= bsize;
 
 		scatterwalk_copychunks(src_p, &walk_in, bsize, 0);
 
-		prfn(tfm, dst_p, src_p, crfn, enc, info,
-		     scatterwalk_samebuf(&walk_in, &walk_out,
-					 src_p, dst_p));
+		prfn(tfm, dst_p, src_p, crfn, enc, info, in_place);
 
 		scatterwalk_done(&walk_in, 0, nbytes);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/digest.c linux-2.4.27-rc4/crypto/digest.c
--- linux-2.4.26/crypto/digest.c	2003-08-25 11:44:40.000000000 +0000
+++ linux-2.4.27-rc4/crypto/digest.c	2004-07-30 16:25:47.000000000 +0000
@@ -27,13 +27,28 @@ static void update(struct crypto_tfm *tf
                    struct scatterlist *sg, unsigned int nsg)
 {
 	unsigned int i;
-	
+
 	for (i = 0; i < nsg; i++) {
-		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
-		                                      p, sg[i].length);
-		crypto_kunmap(p, 0);
-		crypto_yield(tfm);
+
+		struct page *pg = sg[i].page;
+		unsigned int offset = sg[i].offset;
+		unsigned int l = sg[i].length;
+
+		do {
+			unsigned int bytes_from_page = min(l, ((unsigned int)
+							   (PAGE_SIZE)) - 
+							   offset);
+			char *p = crypto_kmap(pg, 0) + offset;
+
+			tfm->__crt_alg->cra_digest.dia_update
+					(crypto_tfm_ctx(tfm), p,
+					 bytes_from_page);
+			crypto_kunmap(p, 0);
+			crypto_yield(tfm);
+			offset = 0;
+			pg++;
+			l -= bytes_from_page;
+		} while (l > 0);
 	}
 }
 
@@ -42,6 +57,15 @@ static void final(struct crypto_tfm *tfm
 	tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
 }
 
+static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
+{
+	u32 flags;
+	if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
+		return -ENOSYS;
+	return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
+						     key, keylen, &flags);
+}
+
 static void digest(struct crypto_tfm *tfm,
                    struct scatterlist *sg, unsigned int nsg, u8 *out)
 {
@@ -72,6 +96,7 @@ int crypto_init_digest_ops(struct crypto
 	ops->dit_update	= update;
 	ops->dit_final	= final;
 	ops->dit_digest	= digest;
+	ops->dit_setkey	= setkey;
 	
 	return crypto_alloc_hmac_block(tfm);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/michael_mic.c linux-2.4.27-rc4/crypto/michael_mic.c
--- linux-2.4.26/crypto/michael_mic.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/crypto/michael_mic.c	2004-07-30 16:27:55.000000000 +0000
@@ -0,0 +1,193 @@
+/*
+ * Cryptographic API
+ *
+ * Michael MIC (IEEE 802.11i/TKIP) keyed digest
+ *
+ * Copyright (c) 2004 Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * 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/module.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+
+
+struct michael_mic_ctx {
+	u8 pending[4];
+	size_t pending_len;
+
+	u32 l, r;
+};
+
+
+static inline u32 rotl(u32 val, int bits)
+{
+	return (val << bits) | (val >> (32 - bits));
+}
+
+
+static inline u32 rotr(u32 val, int bits)
+{
+	return (val >> bits) | (val << (32 - bits));
+}
+
+
+static inline u32 xswap(u32 val)
+{
+	return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8);
+}
+
+
+#define michael_block(l, r)	\
+do {				\
+	r ^= rotl(l, 17);	\
+	l += r;			\
+	r ^= xswap(l);		\
+	l += r;			\
+	r ^= rotl(l, 3);	\
+	l += r;			\
+	r ^= rotr(l, 2);	\
+	l += r;			\
+} while (0)
+
+
+static inline u32 get_le32(const u8 *p)
+{
+	return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+
+static inline void put_le32(u8 *p, u32 v)
+{
+	p[0] = v;
+	p[1] = v >> 8;
+	p[2] = v >> 16;
+	p[3] = v >> 24;
+}
+
+
+static void michael_init(void *ctx)
+{
+	struct michael_mic_ctx *mctx = ctx;
+	mctx->pending_len = 0;
+}
+
+
+static void michael_update(void *ctx, const u8 *data, unsigned int len)
+{
+	struct michael_mic_ctx *mctx = ctx;
+
+	if (mctx->pending_len) {
+		int flen = 4 - mctx->pending_len;
+		if (flen > len)
+			flen = len;
+		memcpy(&mctx->pending[mctx->pending_len], data, flen);
+		mctx->pending_len += flen;
+		data += flen;
+		len -= flen;
+
+		if (mctx->pending_len < 4)
+			return;
+
+		mctx->l ^= get_le32(mctx->pending);
+		michael_block(mctx->l, mctx->r);
+		mctx->pending_len = 0;
+	}
+
+	while (len >= 4) {
+		mctx->l ^= get_le32(data);
+		michael_block(mctx->l, mctx->r);
+		data += 4;
+		len -= 4;
+	}
+
+	if (len > 0) {
+		mctx->pending_len = len;
+		memcpy(mctx->pending, data, len);
+	}
+}
+
+
+static void michael_final(void *ctx, u8 *out)
+{
+	struct michael_mic_ctx *mctx = ctx;
+	u8 *data = mctx->pending;
+
+	/* Last block and padding (0x5a, 4..7 x 0) */
+	switch (mctx->pending_len) {
+	case 0:
+		mctx->l ^= 0x5a;
+		break;
+	case 1:
+		mctx->l ^= data[0] | 0x5a00;
+		break;
+	case 2:
+		mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000;
+		break;
+	case 3:
+		mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) |
+			0x5a000000;
+		break;
+	}
+	michael_block(mctx->l, mctx->r);
+	/* l ^= 0; */
+	michael_block(mctx->l, mctx->r);
+
+	put_le32(out, mctx->l);
+	put_le32(out + 4, mctx->r);
+}
+
+
+static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
+			  u32 *flags)
+{
+	struct michael_mic_ctx *mctx = ctx;
+	if (keylen != 8) {
+		if (flags)
+			*flags = CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+	mctx->l = get_le32(key);
+	mctx->r = get_le32(key + 4);
+	return 0;
+}
+
+
+static struct crypto_alg michael_mic_alg = {
+	.cra_name	= "michael_mic",
+	.cra_flags	= CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	= 8,
+	.cra_ctxsize	= sizeof(struct michael_mic_ctx),
+	.cra_module	= THIS_MODULE,
+	.cra_list	= LIST_HEAD_INIT(michael_mic_alg.cra_list),
+	.cra_u		= { .digest = {
+	.dia_digestsize	= 8,
+	.dia_init	= michael_init,
+	.dia_update	= michael_update,
+	.dia_final	= michael_final,
+	.dia_setkey	= michael_setkey } }
+};
+
+
+static int __init michael_mic_init(void)
+{
+	return crypto_register_alg(&michael_mic_alg);
+}
+
+
+static void __exit michael_mic_exit(void)
+{
+	crypto_unregister_alg(&michael_mic_alg);
+}
+
+
+module_init(michael_mic_init);
+module_exit(michael_mic_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Michael MIC");
+MODULE_AUTHOR("Jouni Malinen <jkmaline@cc.hut.fi>");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/scatterwalk.h linux-2.4.27-rc4/crypto/scatterwalk.h
--- linux-2.4.26/crypto/scatterwalk.h	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/crypto/scatterwalk.h	2004-07-30 16:28:27.000000000 +0000
@@ -38,6 +38,7 @@ static inline int scatterwalk_samebuf(st
 				      void *src_p, void *dst_p)
 {
 	return walk_in->page == walk_out->page &&
+	       walk_in->offset == walk_out->offset &&
 	       walk_in->data == src_p && walk_out->data == dst_p;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/tcrypt.c linux-2.4.27-rc4/crypto/tcrypt.c
--- linux-2.4.26/crypto/tcrypt.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/crypto/tcrypt.c	2004-07-30 16:29:34.000000000 +0000
@@ -63,7 +63,7 @@ static char *tvmem;
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
 	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"arc4", "deflate", NULL
+	"arc4", "michael_mic", "deflate", "tea", "xtea", NULL
 };
 
 static void
@@ -114,6 +114,10 @@ test_hash (char * algo, struct hash_test
 		sg[0].length = hash_tv[i].psize;
 
 		crypto_digest_init (tfm);
+		if (tfm->crt_u.digest.dit_setkey) {
+			crypto_digest_setkey (tfm, hash_tv[i].key,
+					      hash_tv[i].ksize);
+		}
 		crypto_digest_update (tfm, sg, 1);
 		crypto_digest_final (tfm, result);
 
@@ -562,6 +566,15 @@ do_test(void)
 		test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS);
 		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
 
+		//TEA
+		test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS);
+		test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS);
+
+
+		//XTEA
+		test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
+		test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
+
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		test_deflate();		
@@ -570,6 +583,8 @@ do_test(void)
 		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);		
 		test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
 #endif		
+
+		test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
 		break;
 
 	case 1:
@@ -649,6 +664,20 @@ do_test(void)
 		test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS);
 		break;
 
+	case 17:
+		test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
+		break;
+
+	case 19:
+		test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS);
+		test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS);
+		break;
+
+	case 20:
+		test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS);
+		test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS);
+		break;
+
 #ifdef CONFIG_CRYPTO_HMAC
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/tcrypt.h linux-2.4.27-rc4/crypto/tcrypt.h
--- linux-2.4.26/crypto/tcrypt.h	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/crypto/tcrypt.h	2004-07-30 16:31:44.000000000 +0000
@@ -30,6 +30,8 @@ struct hash_testvec {
 	char digest[MAX_DIGEST_SIZE];
 	unsigned char np;
 	unsigned char tap[MAX_TAP];		
+	char key[128]; /* only used with keyed hash algorithms */
+	unsigned char ksize;
 };
 
 struct hmac_testvec {	
@@ -1628,6 +1630,195 @@ struct cipher_testvec arc4_dec_tv_templa
 	},
 };
 
+/* 
+ * TEA test vectors
+ */
+#define TEA_ENC_TEST_VECTORS	4
+#define TEA_DEC_TEST_VECTORS	4
+
+struct cipher_testvec tea_enc_tv_template[] =
+{
+	{
+		.key    = { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input  = { [0 ... 8] = 0x00 },
+		.ilen	= 8,
+		.result	= { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+		.klen	= 16,
+		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+		.ilen	= 8,
+		.result	= { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+		.klen	= 16,
+		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+		.ilen	= 16,
+		.result	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e, 
+			    0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+		.klen	= 16,
+		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+		.ilen	= 32,
+		.result	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47, 
+			    0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8, 
+			    0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a, 
+			    0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+		.rlen	= 32,
+	}
+};
+
+struct cipher_testvec tea_dec_tv_template[] =
+{
+	{
+		.key    = { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input	= { 0x0a, 0x3a, 0xea, 0x41, 0x40, 0xa9, 0xba, 0x94 },
+		.ilen	= 8,
+		.result = { [0 ... 8] = 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+		.klen	= 16,
+		.input	= { 0x77, 0x5d, 0x2a, 0x6a, 0xf6, 0xce, 0x92, 0x09 },
+		.ilen	= 8,
+		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+		.klen	= 16,
+		.input	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+                            0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+                .ilen   = 16,
+		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+		.klen	= 16,
+		.input	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+                            0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+                            0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+                            0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+		.ilen	= 32,
+		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+		.rlen	= 32,
+	}
+};
+
+/* 
+ * XTEA test vectors 
+ */
+#define XTEA_ENC_TEST_VECTORS	4
+#define XTEA_DEC_TEST_VECTORS	4
+
+struct cipher_testvec xtea_enc_tv_template[] =
+{
+	{
+		.key    = { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input  = { [0 ... 8] = 0x00 },
+		.ilen	= 8,
+		.result	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+		.klen	= 16,
+		.input	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+		.ilen	= 8,
+		.result	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+		.klen	= 16,
+		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+		.ilen	= 16,
+		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+		.klen	= 16,
+		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+		.ilen	= 32,
+		.result	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+		.rlen	= 32,
+	}
+};
+
+struct cipher_testvec xtea_dec_tv_template[] =
+{
+	{
+		.key    = { [0 ... 15] = 0x00 },
+		.klen	= 16,
+		.input	= { 0xaa, 0x22, 0x96, 0xe5, 0x6c, 0x61, 0xf3, 0x45 },
+		.ilen	= 8,
+		.result = { [0 ... 8] = 0x00 },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x2b, 0x02, 0x05, 0x68, 0x06, 0x14, 0x49, 0x76,
+			    0x77, 0x5d, 0x0e, 0x26, 0x6c, 0x28, 0x78, 0x43 },
+		.klen	= 16,
+		.input	= { 0x82, 0x3e, 0xeb, 0x35, 0xdc, 0xdd, 0xd9, 0xc3 },
+		.ilen	= 8,
+		.result	= { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x2e },
+		.rlen	= 8,
+	}, {
+		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
+			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
+		.klen	= 16,
+		.input	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
+		.ilen	= 16,
+		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
+		.rlen	= 16,
+	}, {
+		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
+			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
+		.klen	= 16,
+		.input	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
+			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
+			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
+		.ilen	= 32,
+		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
+		.rlen	= 32,
+	}
+};
+
+
 
 /*
  * Compression stuff.
@@ -1719,4 +1910,55 @@ struct comp_testvec deflate_decomp_tv_te
 	},
 };
 
+/*
+ * Michael MIC test vectors from IEEE 802.11i
+ */
+#define MICHAEL_MIC_TEST_VECTORS 6
+
+struct hash_testvec michael_mic_tv_template[] =
+{
+	{
+		.key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+		.ksize = 8,
+		.plaintext = { },
+		.psize = 0,
+		.digest = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 }
+	},
+	{
+		.key = { 0x82, 0x92, 0x5c, 0x1c, 0xa1, 0xd1, 0x30, 0xb8 },
+		.ksize = 8,
+		.plaintext = { 'M' },
+		.psize = 1,
+		.digest = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f }
+	},
+	{
+		.key = { 0x43, 0x47, 0x21, 0xca, 0x40, 0x63, 0x9b, 0x3f },
+		.ksize = 8,
+		.plaintext = { 'M', 'i' },
+		.psize = 2,
+		.digest = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 }
+	},
+	{
+		.key = { 0xe8, 0xf9, 0xbe, 0xca, 0xe9, 0x7e, 0x5d, 0x29 },
+		.ksize = 8,
+		.plaintext = { 'M', 'i', 'c' },
+		.psize = 3,
+		.digest = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb }
+	},
+	{
+		.key = { 0x90, 0x03, 0x8f, 0xc6, 0xcf, 0x13, 0xc1, 0xdb },
+		.ksize = 8,
+		.plaintext = { 'M', 'i', 'c', 'h' },
+		.psize = 4,
+		.digest = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 }
+	},
+	{
+		.key = { 0xd5, 0x5e, 0x10, 0x05, 0x10, 0x12, 0x89, 0x86 },
+		.ksize = 8,
+		.plaintext = { 'M', 'i', 'c', 'h', 'a', 'e', 'l' },
+		.psize = 7,
+		.digest = { 0x0a, 0x94, 0x2b, 0x12, 0x4e, 0xca, 0xa5, 0x46 },
+	}
+};
+
 #endif	/* _CRYPTO_TCRYPT_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/tea.c linux-2.4.27-rc4/crypto/tea.c
--- linux-2.4.26/crypto/tea.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/crypto/tea.c	2004-07-30 16:24:55.000000000 +0000
@@ -0,0 +1,246 @@
+/* 
+ * Cryptographic API.
+ *
+ * TEA and Xtended TEA Algorithms
+ *
+ * The TEA and Xtended TEA algorithms were developed by David Wheeler 
+ * and Roger Needham at the Computer Laboratory of Cambridge University.
+ *
+ * Copyright (c) 2004 Aaron Grothe ajgrothe@yahoo.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.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+#define TEA_KEY_SIZE		16
+#define TEA_BLOCK_SIZE		8
+#define TEA_ROUNDS		32
+#define TEA_DELTA		0x9e3779b9
+
+#define XTEA_KEY_SIZE		16
+#define XTEA_BLOCK_SIZE		8
+#define XTEA_ROUNDS		32
+#define XTEA_DELTA		0x9e3779b9
+
+#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from))
+
+struct tea_ctx {
+	u32 KEY[4];
+};
+
+struct xtea_ctx {
+	u32 KEY[4];
+};
+
+static int tea_setkey(void *ctx_arg, const u8 *in_key,
+                       unsigned int key_len, u32 *flags)
+{ 
+
+	struct tea_ctx *ctx = ctx_arg;
+	
+	if (key_len != 16)
+	{
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	ctx->KEY[0] = u32_in (in_key);
+	ctx->KEY[1] = u32_in (in_key + 4);
+	ctx->KEY[2] = u32_in (in_key + 8);
+	ctx->KEY[3] = u32_in (in_key + 12);
+
+	return 0; 
+
+}
+
+static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+	u32 y, z, n, sum = 0;
+	u32 k0, k1, k2, k3;
+
+	struct tea_ctx *ctx = ctx_arg;
+
+	y = u32_in (src);
+	z = u32_in (src + 4);
+
+	k0 = ctx->KEY[0];
+	k1 = ctx->KEY[1];
+	k2 = ctx->KEY[2];
+	k3 = ctx->KEY[3];
+
+	n = TEA_ROUNDS;
+
+	while (n-- > 0) {
+		sum += TEA_DELTA;
+		y += ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
+		z += ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
+	}
+	
+	u32_out (dst, y);
+	u32_out (dst + 4, z);
+}
+
+static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+	u32 y, z, n, sum;
+	u32 k0, k1, k2, k3;
+
+	struct tea_ctx *ctx = ctx_arg;
+
+	y = u32_in (src);
+	z = u32_in (src + 4);
+
+	k0 = ctx->KEY[0];
+	k1 = ctx->KEY[1];
+	k2 = ctx->KEY[2];
+	k3 = ctx->KEY[3];
+
+	sum = TEA_DELTA << 5;
+
+	n = TEA_ROUNDS;
+
+	while (n-- > 0) {
+		z -= ((y << 4) + k2) ^ (y + sum) ^ ((y >> 5) + k3);
+		y -= ((z << 4) + k0) ^ (z + sum) ^ ((z >> 5) + k1);
+		sum -= TEA_DELTA;
+	}
+	
+	u32_out (dst, y);
+	u32_out (dst + 4, z);
+
+}
+
+static int xtea_setkey(void *ctx_arg, const u8 *in_key,
+                       unsigned int key_len, u32 *flags)
+{ 
+
+	struct xtea_ctx *ctx = ctx_arg;
+	
+	if (key_len != 16)
+	{
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+
+	ctx->KEY[0] = u32_in (in_key);
+	ctx->KEY[1] = u32_in (in_key + 4);
+	ctx->KEY[2] = u32_in (in_key + 8);
+	ctx->KEY[3] = u32_in (in_key + 12);
+
+	return 0; 
+
+}
+
+static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+
+	u32 y, z, sum = 0;
+	u32 limit = XTEA_DELTA * XTEA_ROUNDS;
+
+	struct xtea_ctx *ctx = ctx_arg;
+
+	y = u32_in (src);
+	z = u32_in (src + 4);
+
+	while (sum != limit) {
+		y += (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum&3]; 
+		sum += TEA_DELTA;
+		z += (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 &3]; 
+	}
+	
+	u32_out (dst, y);
+	u32_out (dst + 4, z);
+
+}
+
+static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+{ 
+
+	u32 y, z, sum;
+	struct tea_ctx *ctx = ctx_arg;
+
+	y = u32_in (src);
+	z = u32_in (src + 4);
+
+	sum = XTEA_DELTA * XTEA_ROUNDS;
+
+	while (sum) {
+		z -= (y << 4 ^ y >> 5) + (y ^ sum) + ctx->KEY[sum>>11 & 3];
+		sum -= XTEA_DELTA;
+		y -= (z << 4 ^ z >> 5) + (z ^ sum) + ctx->KEY[sum & 3];
+	}
+	
+	u32_out (dst, y);
+	u32_out (dst + 4, z);
+
+}
+
+static struct crypto_alg tea_alg = {
+	.cra_name		=	"tea",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	TEA_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof (struct tea_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(tea_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	TEA_KEY_SIZE,
+	.cia_max_keysize	=	TEA_KEY_SIZE,
+	.cia_setkey		= 	tea_setkey,
+	.cia_encrypt		=	tea_encrypt,
+	.cia_decrypt		=	tea_decrypt } }
+};
+
+static struct crypto_alg xtea_alg = {
+	.cra_name		=	"xtea",
+	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+	.cra_blocksize		=	XTEA_BLOCK_SIZE,
+	.cra_ctxsize		=	sizeof (struct xtea_ctx),
+	.cra_module		=	THIS_MODULE,
+	.cra_list		=	LIST_HEAD_INIT(xtea_alg.cra_list),
+	.cra_u			=	{ .cipher = {
+	.cia_min_keysize	=	XTEA_KEY_SIZE,
+	.cia_max_keysize	=	XTEA_KEY_SIZE,
+	.cia_setkey		= 	xtea_setkey,
+	.cia_encrypt		=	xtea_encrypt,
+	.cia_decrypt		=	xtea_decrypt } }
+};
+
+static int __init init(void)
+{
+	int ret = 0;
+	
+	ret = crypto_register_alg(&tea_alg);
+	if (ret < 0)
+		goto out;
+
+	ret = crypto_register_alg(&xtea_alg);
+	if (ret < 0) {
+		crypto_unregister_alg(&tea_alg);
+		goto out;
+	}
+
+out:	
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&tea_alg);
+	crypto_unregister_alg(&xtea_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TEA & XTEA Cryptographic Algorithms");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/crypto/twofish.c linux-2.4.27-rc4/crypto/twofish.c
--- linux-2.4.26/crypto/twofish.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/crypto/twofish.c	2004-07-30 16:25:45.000000000 +0000
@@ -663,7 +663,10 @@ static int twofish_setkey(void *cx, cons
 
 	/* Check key length. */
 	if (key_len != 16 && key_len != 24 && key_len != 32)
+	{
+		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL; /* unsupported key length */
+	}
 
 	/* Compute the first two words of the S vector.  The magic numbers are
 	 * the entries of the RS matrix, preprocessed through poly_to_exp. The
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/Config.in linux-2.4.27-rc4/drivers/acpi/Config.in
--- linux-2.4.26/drivers/acpi/Config.in	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/Config.in	2004-07-30 16:30:53.000000000 +0000
@@ -16,6 +16,7 @@ if [ "$CONFIG_X86" = "y" ]; then
     define_bool CONFIG_ACPI_POWER		y
     if [ "$CONFIG_PCI" = "y" ]; then
       define_bool CONFIG_ACPI_PCI		y
+      define_bool CONFIG_ACPI_MMCONFIG		y
     fi
     define_bool CONFIG_ACPI_SLEEP		y
     define_bool CONFIG_ACPI_SYSTEM		y
@@ -28,7 +29,6 @@ if [ "$CONFIG_X86" = "y" ]; then
     tristate     '  ASUS Laptop Extras'  CONFIG_ACPI_ASUS
     tristate     '  Toshiba Laptop Extras'	CONFIG_ACPI_TOSHIBA
     bool         '  Debug Statements'	CONFIG_ACPI_DEBUG
-    bool         '  Relaxed AML Checking'	CONFIG_ACPI_RELAXED_AML
   else
     if [ "$CONFIG_SMP" = "y" ]; then
       define_bool CONFIG_ACPI_BOOT		y
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/ac.c linux-2.4.27-rc4/drivers/acpi/ac.c
--- linux-2.4.26/drivers/acpi/ac.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/ac.c	2004-07-30 16:30:33.000000000 +0000
@@ -156,6 +156,7 @@ acpi_ac_add_fs (
 			acpi_ac_dir);
 		if (!acpi_device_dir(device))
 			return_VALUE(-ENODEV);
+		acpi_device_dir(device)->owner = THIS_MODULE;
 	}
 
 	/* 'state' [R] */
@@ -168,6 +169,7 @@ acpi_ac_add_fs (
 	else {
 		entry->read_proc = acpi_ac_read_state;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	return_VALUE(0);
@@ -181,6 +183,8 @@ acpi_ac_remove_fs (
 	ACPI_FUNCTION_TRACE("acpi_ac_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_AC_FILE_STATE,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
 		acpi_device_dir(device) = NULL;
 	}
@@ -318,6 +322,7 @@ acpi_ac_init (void)
 	acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
 	if (!acpi_ac_dir)
 		return_VALUE(-ENODEV);
+	acpi_ac_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&acpi_ac_driver);
 	if (result < 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/asus_acpi.c linux-2.4.27-rc4/drivers/acpi/asus_acpi.c
--- linux-2.4.26/drivers/acpi/asus_acpi.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/asus_acpi.c	2004-07-30 16:29:25.000000000 +0000
@@ -40,8 +40,9 @@
 #include <linux/proc_fs.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
+#include <asm/uaccess.h>
 
-#define ASUS_ACPI_VERSION "0.27"
+#define ASUS_ACPI_VERSION "0.28"
 
 #define PROC_ASUS       "asus"	//the directory
 #define PROC_MLED       "mled"
@@ -125,12 +126,11 @@ struct asus_hotk {
 		L5x,      //L5800C 
 		L8L,      //L8400L
 		M1A,      //M1300A
-		M2E,      //M2400E
+		M2E,      //M2400E, L4400L
+		P30,	  //Samsung P30
 		S1x,      //S1300A, but also L1400B and M2400A (L84F)
 		S2x,      //S200 (J1 reported), Victor MP-XP7210
-		          //TODO  A1370D does not seem to have an ATK device 
-		          // L8400 model doesn't have ATK
-		xxN,      //M2400N, M3700N, S1300N (Centrino)
+		xxN,      //M2400N, M3700N, M6800N, S1300N, S5200N (Centrino)
 		END_MODEL
 	} model;              //Models currently supported
 	u16 event_count[128]; //count for each event TODO make this better
@@ -140,6 +140,7 @@ struct asus_hotk {
 #define A1x_PREFIX "\\_SB.PCI0.ISA.EC0."
 #define L3C_PREFIX "\\_SB.PCI0.PX40.ECD0."
 #define M1A_PREFIX "\\_SB.PCI0.PX40.EC0."
+#define P30_PREFIX "\\_SB.PCI0.LPCB.EC0."
 #define S1x_PREFIX "\\_SB.PCI0.PX40."
 #define S2x_PREFIX A1x_PREFIX
 #define xxN_PREFIX "\\_SB.PCI0.SBRG.EC0."
@@ -166,7 +167,7 @@ static struct model_data model_conf[END_
 		.mt_lcd_switch     = A1x_PREFIX "_Q10",
 		.lcd_status        = "\\BKLI",
 		.brightness_up     = A1x_PREFIX "_Q0E",
-		.brightness_down   = A1x_PREFIX "_Q0F",
+		.brightness_down   = A1x_PREFIX "_Q0F"
 	},
 
 	{
@@ -176,11 +177,8 @@ static struct model_data model_conf[END_
 		.wled_status       = "\\SG66",
 		.mt_lcd_switch     = "\\Q10",
 		.lcd_status        = "\\BAOF",
-		.brightness_up     = "\\Q0E",
-		.brightness_down   = "\\Q0F",
 		.brightness_set    = "SPLV",
 		.brightness_get    = "GPLV",
-		.brightness_status = "\\CMOD",
 		.display_set       = "SDSP",
 		.display_get       = "\\INFB"
 	},
@@ -217,11 +215,8 @@ static struct model_data model_conf[END_
 		.mt_wled           = "WLED",
 		.mt_lcd_switch     = L3C_PREFIX "_Q10",
 		.lcd_status        = "\\GL32",
-		.brightness_up     = L3C_PREFIX "_Q0F",
-		.brightness_down   = L3C_PREFIX "_Q0E",
 		.brightness_set    = "SPLV",
 		.brightness_get    = "GPLV",
-		.brightness_status = "\\BLVL",
 		.display_set       = "SDSP",
 		.display_get       = "\\_SB.PCI0.PCI1.VGAC.NMAP"
 	},
@@ -233,11 +228,8 @@ static struct model_data model_conf[END_
 		.mt_wled           = "WLED",
 		.mt_lcd_switch     = "\\Q10",
 		.lcd_status        = "\\BKLG",
-		.brightness_up     = "\\Q0E",
-		.brightness_down   = "\\Q0F",
 		.brightness_set    = "SPLV",
 		.brightness_get    = "GPLV",
-		.brightness_status = "\\BLVL",
 		.display_set       = "SDSP",
 		.display_get       = "\\INFB"
 	},
@@ -257,14 +249,10 @@ static struct model_data model_conf[END_
 	{
 		.name              = "L5x",
 		.mt_mled           = "MLED",
-//		.mt_wled           = "WLED",
-//		.wled_status       = "\\WRED",
-/* Present, but not controlled by ACPI */
+/* WLED present, but not controlled by ACPI */
 		.mt_tled           = "TLED",
 		.mt_lcd_switch     = "\\Q0D",
 		.lcd_status        = "\\BAOF",
-		.brightness_up     = "\\Q0C",
-		.brightness_down   = "\\Q0B",
 		.brightness_set    = "SPLV",
 		.brightness_get    = "GPLV",
 		.display_set       = "SDSP",
@@ -294,8 +282,6 @@ static struct model_data model_conf[END_
 		.mt_wled           = "WLED",
 		.mt_lcd_switch     = "\\Q10",
 		.lcd_status        = "\\GP06",
-		.brightness_up     = "\\Q0E",
-		.brightness_down   = "\\Q0F",
 		.brightness_set    = "SPLV",
 		.brightness_get    = "GPLV",
 		.display_set       = "SDSP",
@@ -303,17 +289,26 @@ static struct model_data model_conf[END_
 	},
 
 	{
+		.name              = "P30",
+		.mt_wled           = "WLED",
+		.mt_lcd_switch     = P30_PREFIX "_Q0E",
+		.lcd_status        = "\\BKLT",
+		.brightness_up     = P30_PREFIX "_Q68",
+		.brightness_down   = P30_PREFIX "_Q69",
+		.brightness_get    = "GPLV",
+		.display_set       = "SDSP",
+		.display_get       = "\\DNXT"
+	},
+
+	{
 		.name              = "S1x",
 		.mt_mled           = "MLED",
 		.mled_status       = "\\EMLE",
 		.mt_wled           = "WLED",
 		.mt_lcd_switch     = S1x_PREFIX "Q10" ,
 		.lcd_status        = "\\PNOF",
-		.brightness_up     = S1x_PREFIX "Q0F",
-		.brightness_down   = S1x_PREFIX "Q0E",
 		.brightness_set    = "SPLV",
-		.brightness_get    = "GPLV",
-		.brightness_status = "\\BRIT",
+		.brightness_get    = "GPLV"
 	},
 
 	{
@@ -323,22 +318,17 @@ static struct model_data model_conf[END_
 		.mt_lcd_switch     = S2x_PREFIX "_Q10",
 		.lcd_status        = "\\BKLI",
 		.brightness_up     = S2x_PREFIX "_Q0B",
-		.brightness_down   = S2x_PREFIX "_Q0A",
+		.brightness_down   = S2x_PREFIX "_Q0A"
 	},
 
 	{
 		.name              = "xxN",
 		.mt_mled           = "MLED",
-//		.mt_wled           = "WLED",
-//		.wled_status       = "\\PO33",
-/* Present, but not controlled by ACPI */
+/* WLED present, but not controlled by ACPI */
 		.mt_lcd_switch     = xxN_PREFIX "_Q10",
 		.lcd_status        = "\\BKLT",
-		.brightness_up     = xxN_PREFIX "_Q0F",
-		.brightness_down   = xxN_PREFIX "_Q0E",
 		.brightness_set    = "SPLV",
 		.brightness_get    = "GPLV",
-		.brightness_status = "\\LBTN",
 		.display_set       = "SDSP",
 		.display_get       = "\\ADVG"
 	}
@@ -466,6 +456,21 @@ proc_read_info(char *page, char **start,
 
 	return len;
 }
+ 
+static int parse_arg(const char *buf, unsigned long count, int *val)
+{
+	char s[32];
+	if (!count)
+		return 0;
+	if (count > 31)
+		return -EINVAL;
+	if (copy_from_user(s, buf, count))
+		return -EFAULT;
+	s[count] = 0;
+	if (sscanf(s, "%i", val) != 1)
+		return -EINVAL;
+	return count;
+}
 
 
 /*
@@ -497,11 +502,14 @@ static int
 write_led(const char *buffer, unsigned long count, struct asus_hotk *hotk, 
           char *ledname, int ledmask, int invert)
 {
-	int value;
+	int value, retval;
 	int led_out = 0;
 
-	if (sscanf(buffer, "%i", &value) == 1)
-		led_out = value ? 1 : 0;
+	retval = parse_arg(buffer, count, &value);
+	if (retval <= 0)
+		return retval;
+	count = retval;
+	led_out = value ? 1 : 0;
 
 	hotk->status =
 	    (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask);
@@ -654,15 +662,33 @@ static int
 proc_write_lcd(struct file *file, const char *buffer,
 	       unsigned long count, void *data)
 {
-	int value;
+	int value, retval;
 	struct asus_hotk *hotk = (struct asus_hotk *) data;
 	
-	if (sscanf(buffer, "%i", &value) == 1)
+	retval = parse_arg(buffer, count, &value);
+	if (retval > 0)
 		set_lcd_state(hotk, value);
-	return count;
+	return retval;
 }
 
 
+static int read_brightness(struct asus_hotk *hotk)
+{
+	int value;
+	
+	if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
+		if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, 
+				   &value))
+			printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
+	} else if (hotk->methods->brightness_status) { /* For D1 for example */
+		if (!read_acpi_int(NULL, hotk->methods->brightness_status, 
+				   &value))
+			printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
+	} else /* No GPLV method */
+		value = hotk->brightness;
+	return value;
+}
+
 /*
  * Change the brightness level
  */
@@ -679,7 +705,7 @@ static void set_brightness(int value, st
 	}
 
 	/* No SPLV method if we are here, act as appropriate */
-	value -= hotk->brightness;
+	value -= read_brightness(hotk);
 	while (value != 0) {
 		status = acpi_evaluate_object(NULL, (value > 0) ? 
 					      hotk->methods->brightness_up : 
@@ -692,23 +718,6 @@ static void set_brightness(int value, st
 	return;
 }
 
-static int read_brightness(struct asus_hotk *hotk)
-{
-	int value;
-	
-	if(hotk->methods->brightness_get) { /* SPLV/GPLV laptop */
-		if (!read_acpi_int(hotk->handle, hotk->methods->brightness_get, 
-				   &value))
-			printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
-	} else if (hotk->methods->brightness_status) { /* For D1 for example */
-		if (!read_acpi_int(NULL, hotk->methods->brightness_status, 
-				   &value))
-			printk(KERN_WARNING "Asus ACPI: Error reading brightness\n");
-	} else /* No GPLV method */
-		value = hotk->brightness;
-	return value;
-}
-
 static int
 proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
 	      void *data)
@@ -721,10 +730,11 @@ static int
 proc_write_brn(struct file *file, const char *buffer,
 	       unsigned long count, void *data)
 {
-	int value;
+	int value, retval;
 	struct asus_hotk *hotk = (struct asus_hotk *) data;
 
-	if (sscanf(buffer, "%d", &value) == 1) {
+	retval = parse_arg(buffer, count, &value);
+	if (retval > 0) {
 		value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
 			/* 0 <= value <= 15 */
 		set_brightness(value, hotk);
@@ -732,7 +742,7 @@ proc_write_brn(struct file *file, const 
 		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 	}
 
-	return count;
+	return retval;
 }
 
 static void set_display(int value, struct asus_hotk *hotk)
@@ -770,16 +780,17 @@ static int
 proc_write_disp(struct file *file, const char *buffer,
 	       unsigned long count, void *data)
 {
-	int value;
+	int value, retval;
 	struct asus_hotk *hotk = (struct asus_hotk *) data;
 
-	if (sscanf(buffer, "%d", &value) == 1)
+	retval = parse_arg(buffer, count, &value);
+	if (retval > 0)
 		set_display(value, hotk);
 	else {
 		printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
 	}
 
-	return count;
+	return retval;
 }
 
 
@@ -874,6 +885,28 @@ static int __init asus_hotk_add_fs(struc
 	return 0;
 }
 
+static int asus_hotk_remove_fs(struct acpi_device* device)
+{
+	struct asus_hotk* hotk = acpi_driver_data(device);
+
+	if(acpi_device_dir(device)){
+		remove_proc_entry(PROC_INFO,acpi_device_dir(device));
+		if (hotk->methods->mt_wled)
+			remove_proc_entry(PROC_WLED,acpi_device_dir(device));
+		if (hotk->methods->mt_mled)
+			remove_proc_entry(PROC_MLED,acpi_device_dir(device));
+		if (hotk->methods->mt_tled)
+			remove_proc_entry(PROC_TLED,acpi_device_dir(device));
+		if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) 
+			remove_proc_entry(PROC_LCD, acpi_device_dir(device));
+		if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_get)) 
+			remove_proc_entry(PROC_BRN, acpi_device_dir(device));
+		if (hotk->methods->display_set) 
+			remove_proc_entry(PROC_DISP, acpi_device_dir(device));
+	}
+	return 0;
+}
+
 
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
@@ -929,12 +962,29 @@ static int __init asus_hotk_get_info(str
 		return -ENODEV;
 	}
 
-	/* For testing purposes */
+	/* This needs to be called for some laptops to init properly */
 	if (!read_acpi_int(hotk->handle, "BSTS", &bsts_result))
 		printk(KERN_WARNING "  Error calling BSTS\n");
 	else if (bsts_result)
 		printk(KERN_NOTICE "  BSTS called, 0x%02x returned\n", bsts_result);
 
+	/* Samsung P30 has a device with a valid _HID whose INIT does not 
+	 * return anything. Catch this one and any similar here */
+	if (buffer.pointer == NULL) {
+		if (asus_info && /* Samsung P30 */
+		    strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
+			hotk->model = P30;
+			printk(KERN_NOTICE "  Samsung P30 detected, supported\n");
+		} else {
+			hotk->model = M2E;
+			printk(KERN_WARNING "  no string returned by INIT\n");
+			printk(KERN_WARNING "  trying default values, supply "
+			       "the developers with your DSDT\n");
+		}
+		hotk->methods = &model_conf[hotk->model];
+		return AE_OK;
+	}
+	
 	model = (union acpi_object *) buffer.pointer;
 	if (model->type == ACPI_TYPE_STRING) {
 		printk(KERN_NOTICE "  %s model detected, ", model->string.pointer);
@@ -953,12 +1003,14 @@ static int __init asus_hotk_get_info(str
 		hotk->model = L8L;
 	else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
 		 strncmp(model->string.pointer, "M3N", 3) == 0 ||
+		 strncmp(model->string.pointer, "M6N", 3) == 0 ||
 		 strncmp(model->string.pointer, "S1N", 3) == 0 ||
 		 strncmp(model->string.pointer, "S5N", 3) == 0)
 		hotk->model = xxN;
 	else if (strncmp(model->string.pointer, "M1", 2) == 0)
 		hotk->model = M1A;
-	else if (strncmp(model->string.pointer, "M2", 2) == 0)
+	else if (strncmp(model->string.pointer, "M2", 2) == 0 ||
+		 strncmp(model->string.pointer, "L4E", 3) == 0)
 		hotk->model = M2E;
 	else if (strncmp(model->string.pointer, "L2", 2) == 0)
 		hotk->model = L2D;
@@ -994,6 +1046,13 @@ static int __init asus_hotk_get_info(str
 	else if (strncmp(model->string.pointer, "S5N", 3) == 0)
 		hotk->methods->mt_mled = NULL; 
 	/* S5N has no MLED */
+	else if (strncmp(model->string.pointer, "M6N", 3) == 0) {
+		hotk->methods->display_get = NULL; //TODO
+		hotk->methods->lcd_status = "\\_SB.BKLT";
+		hotk->methods->mt_wled = "WLED";
+		hotk->methods->wled_status = "\\_SB.PCI0.SBRG.SG13";
+	/* M6N differs slightly and has a usable WLED */
+	}
 	else if (asus_info) {
 		if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
 			hotk->methods->mled_status = NULL;
@@ -1049,8 +1108,8 @@ static int __init asus_hotk_add(struct a
 	memset(hotk, 0, sizeof(struct asus_hotk));
 
 	hotk->handle = device->handle;
-	sprintf(acpi_device_name(device), "%s", ACPI_HOTK_DEVICE_NAME);
-	sprintf(acpi_device_class(device), "%s", ACPI_HOTK_CLASS);
+	strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
+	strcpy(acpi_device_class(device), ACPI_HOTK_CLASS);
 	acpi_driver_data(device) = hotk;
 	hotk->device = device;
 
@@ -1112,6 +1171,8 @@ static int asus_hotk_remove(struct acpi_
 	if (ACPI_FAILURE(status))
 		printk(KERN_ERR "Asus ACPI: Error removing notify handler\n");
 
+	asus_hotk_remove_fs(device);
+
 	kfree(hotk);
 
 	return(0);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/battery.c linux-2.4.27-rc4/drivers/acpi/battery.c
--- linux-2.4.26/drivers/acpi/battery.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/battery.c	2004-07-30 16:30:28.000000000 +0000
@@ -474,14 +474,18 @@ acpi_battery_read_state (
 	else
 		p += sprintf(p, "capacity state:          critical\n");
 
-	if ((bst->state & 0x01) && (bst->state & 0x02))
+	if ((bst->state & 0x01) && (bst->state & 0x02)){
 		p += sprintf(p, "charging state:          charging/discharging\n");
+		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+					"Battery Charging and Discharging?\n"));
+	}
 	else if (bst->state & 0x01)
 		p += sprintf(p, "charging state:          discharging\n");
 	else if (bst->state & 0x02)
 		p += sprintf(p, "charging state:          charging\n");
-	else
-		p += sprintf(p, "charging state:          unknown\n");
+	else {
+		p += sprintf(p, "charging state:          charged\n");
+	}
 
 	if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
 		p += sprintf(p, "present rate:            unknown\n");
@@ -609,6 +613,7 @@ acpi_battery_add_fs (
 			acpi_battery_dir);
 		if (!acpi_device_dir(device))
 			return_VALUE(-ENODEV);
+		acpi_device_dir(device)->owner = THIS_MODULE;
 	}
 
 	/* 'info' [R] */
@@ -621,6 +626,7 @@ acpi_battery_add_fs (
 	else {
 		entry->read_proc = acpi_battery_read_info;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'status' [R] */
@@ -633,6 +639,7 @@ acpi_battery_add_fs (
 	else {
 		entry->read_proc = acpi_battery_read_state;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'alarm' [R/W] */
@@ -646,6 +653,7 @@ acpi_battery_add_fs (
 		entry->read_proc = acpi_battery_read_alarm;
 		entry->write_proc = acpi_battery_write_alarm;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	return_VALUE(0);
@@ -659,6 +667,12 @@ acpi_battery_remove_fs (
 	ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_BATTERY_FILE_INFO,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
 		acpi_device_dir(device) = NULL;
 	}
@@ -797,6 +811,7 @@ acpi_battery_init (void)
 	acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
 	if (!acpi_battery_dir)
 		return_VALUE(-ENODEV);
+	acpi_battery_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&acpi_battery_driver);
 	if (result < 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/bus.c linux-2.4.27-rc4/drivers/acpi/bus.c
--- linux-2.4.26/drivers/acpi/bus.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/bus.c	2004-07-30 16:29:10.000000000 +0000
@@ -1964,8 +1964,10 @@ acpi_bus_init (void)
 	acpi_ec_init();		/* ACPI Embedded Controller */
 #endif
 #ifdef CONFIG_ACPI_PCI
-	acpi_pci_link_init();	/* ACPI PCI Interrupt Link */
-	acpi_pci_root_init();	/* ACPI PCI Root Bridge */
+	if (!acpi_pci_disabled) {
+		acpi_pci_link_init();	/* ACPI PCI Interrupt Link */
+		acpi_pci_root_init();	/* ACPI PCI Root Bridge */
+	}
 #endif
 	/*
 	 * Enumerate devices in the ACPI namespace.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/button.c linux-2.4.27-rc4/drivers/acpi/button.c
--- linux-2.4.26/drivers/acpi/button.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/button.c	2004-07-30 16:30:28.000000000 +0000
@@ -171,10 +171,15 @@ acpi_button_add_fs (
 				acpi_button_dir);
 		break;
 	}
+	
+	if (!entry)
+		return_VALUE(-ENODEV);
+	entry->owner = THIS_MODULE;
 
 	acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
 	if (!acpi_device_dir(device))
 		return_VALUE(-ENODEV);
+	acpi_device_dir(device)->owner = THIS_MODULE;
 
 	/* 'info' [R] */
 	entry = create_proc_entry(ACPI_BUTTON_FILE_INFO,
@@ -186,6 +191,7 @@ acpi_button_add_fs (
 	else {
 		entry->read_proc = acpi_button_read_info;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 	
 	if (button->type==ACPI_BUTTON_TYPE_LID){
@@ -199,6 +205,7 @@ acpi_button_add_fs (
 	    else {
 		entry->read_proc = acpi_button_lid_read_state;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	    }
 	}
 
@@ -210,10 +217,37 @@ static int
 acpi_button_remove_fs (
 	struct acpi_device	*device)
 {
+	struct acpi_button	*button = NULL;
+
 	ACPI_FUNCTION_TRACE("acpi_button_remove_fs");
 
+	button = acpi_driver_data(device);
 	if (acpi_device_dir(device)) {
-		remove_proc_entry(acpi_device_bid(device), acpi_button_dir);
+ 		if (button->type == ACPI_BUTTON_TYPE_LID)
+ 			remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+ 					     acpi_device_dir(device));
+ 		remove_proc_entry(ACPI_BUTTON_FILE_INFO,
+ 				     acpi_device_dir(device));
+ 
+ 		remove_proc_entry(acpi_device_bid(device),
+ 				     acpi_device_dir(device)->parent);
+
+		switch (button->type) {
+			case ACPI_BUTTON_TYPE_POWER:
+			case ACPI_BUTTON_TYPE_POWERF:
+				remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, 
+					acpi_button_dir);
+				break;
+			case ACPI_BUTTON_TYPE_SLEEP:
+			case ACPI_BUTTON_TYPE_SLEEPF:
+				remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, 
+					acpi_button_dir);
+				break;
+			case ACPI_BUTTON_TYPE_LID:
+				remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, 
+					acpi_button_dir);
+				break;
+		}
 		acpi_device_dir(device) = NULL;
 	}
 
@@ -470,6 +504,7 @@ acpi_button_init (void)
 	acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
 	if (!acpi_button_dir)
 		return_VALUE(-ENODEV);
+	acpi_button_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&acpi_button_driver);
 	if (result < 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/ec.c linux-2.4.27-rc4/drivers/acpi/ec.c
--- linux-2.4.26/drivers/acpi/ec.c	2004-04-14 13:05:28.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/ec.c	2004-07-30 16:26:43.000000000 +0000
@@ -544,6 +544,12 @@ acpi_ec_remove_fs (
 {
 	ACPI_FUNCTION_TRACE("acpi_ec_remove_fs");
 
+	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
+		remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
+		acpi_device_dir(device) = NULL;
+	}
+
 	return_VALUE(0);
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/fan.c linux-2.4.27-rc4/drivers/acpi/fan.c
--- linux-2.4.26/drivers/acpi/fan.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/fan.c	2004-07-30 16:26:03.000000000 +0000
@@ -151,6 +151,7 @@ acpi_fan_add_fs (
 			acpi_fan_dir);
 		if (!acpi_device_dir(device))
 			return_VALUE(-ENODEV);
+		acpi_device_dir(device)->owner = THIS_MODULE;
 	}
 
 	/* 'status' [R/W] */
@@ -164,6 +165,7 @@ acpi_fan_add_fs (
 		entry->read_proc = acpi_fan_read_state;
 		entry->write_proc = acpi_fan_write_state;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	return_VALUE(0);
@@ -177,6 +179,8 @@ acpi_fan_remove_fs (
 	ACPI_FUNCTION_TRACE("acpi_fan_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_FAN_FILE_STATE,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
 		acpi_device_dir(device) = NULL;
 	}
@@ -267,6 +271,7 @@ acpi_fan_init (void)
 	acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
 	if (!acpi_fan_dir)
 		return_VALUE(-ENODEV);
+	acpi_fan_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&acpi_fan_driver);
 	if (result < 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/pci_irq.c linux-2.4.27-rc4/drivers/acpi/pci_irq.c
--- linux-2.4.26/drivers/acpi/pci_irq.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/pci_irq.c	2004-07-30 16:31:54.000000000 +0000
@@ -373,7 +373,7 @@ acpi_pci_irq_enable (
 	if (!irq) {
 		printk(KERN_WARNING PREFIX "No IRQ known for interrupt pin %c of device %s", ('A' + pin), dev->slot_name);
 		/* Interrupt Line values above 0xF are forbidden */
-		if (dev->irq && dev->irq >= 0xF) {
+		if (dev->irq && (dev->irq <= 0xF)) {
 			printk(" - using IRQ %d\n", dev->irq);
 			return_VALUE(dev->irq);
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/pci_link.c linux-2.4.27-rc4/drivers/acpi/pci_link.c
--- linux-2.4.26/drivers/acpi/pci_link.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/pci_link.c	2004-07-30 16:32:19.000000000 +0000
@@ -90,6 +90,9 @@ static struct {
                             PCI Link Device Management
    -------------------------------------------------------------------------- */
 
+/*
+ * set context (link) possible list from resource list
+ */
 static acpi_status
 acpi_pci_link_check_possible (
 	struct acpi_resource	*resource,
@@ -128,7 +131,7 @@ acpi_pci_link_check_possible (
 		struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
 		if (!p || !p->number_of_interrupts) {
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN, 
-				"Blank IRQ resource\n"));
+				"Blank EXT IRQ resource\n"));
 			return AE_OK;
 		}
 		for (i = 0; (i<p->number_of_interrupts && i<ACPI_PCI_LINK_MAX_POSSIBLE); i++) {
@@ -193,8 +196,12 @@ acpi_pci_link_check_current (
 	{
 		struct acpi_resource_irq *p = &resource->data.irq;
 		if (!p || !p->number_of_interrupts) {
-			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				"Blank IRQ resource\n"));
+			/*
+			 * IRQ descriptors may have no IRQ# bits set,
+			 * particularly those those w/ _STA disabled
+			 */
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				"Blank IRQ resource\n")); 
 			return AE_OK;
 		}
 		*irq = p->interrupts[0];
@@ -204,8 +211,12 @@ acpi_pci_link_check_current (
 	{
 		struct acpi_resource_ext_irq *p = &resource->data.extended_irq;
 		if (!p || !p->number_of_interrupts) {
+			/*
+			 * extended IRQ descriptors must
+			 * return at least 1 IRQ
+			 */
 			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
-				"Blank IRQ resource\n"));
+				"Blank EXT IRQ resource\n"));
 			return AE_OK;
 		}
 		*irq = p->interrupts[0];
@@ -219,6 +230,13 @@ acpi_pci_link_check_current (
 	return AE_CTRL_TERMINATE;
 }
 
+/*
+ * Run _CRS and set link->irq.active
+ *
+ * return value:
+ * 0 - success
+ * !0 - failure
+ */
 static int
 acpi_pci_link_get_current (
 	struct acpi_pci_link	*link)
@@ -234,15 +252,19 @@ acpi_pci_link_get_current (
 
 	link->irq.active = 0;
 
-	/* Make sure the link is enabled (no use querying if it isn't). */
-	result = acpi_bus_get_status(link->device);
-	if (result) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
-		goto end;
-	}
-	if (!link->device->status.enabled) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
-		return_VALUE(0);
+	/* in practice, status disabled is meaningless, ignore it */
+	if (acpi_strict) {
+		/* Query _STA, set link->device->status */
+		result = acpi_bus_get_status(link->device);
+		if (result) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
+			goto end;
+		}
+
+		if (!link->device->status.enabled) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link disabled\n"));
+			return_VALUE(0);
+		}
 	}
 
 	/* 
@@ -257,18 +279,11 @@ acpi_pci_link_get_current (
 		goto end;
 	}
 
-	if (!irq) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No IRQ resource found\n"));
+	if (acpi_strict && !irq) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "_CRS returned 0\n"));
 		result = -ENODEV;
-		goto end;
 	}
 
-	/*
-	 * Note that we don't validate that the current IRQ (_CRS) exists
-	 * within the possible IRQs (_PRS): we blindly assume that whatever
-	 * IRQ a boot-enabled Link device is set to is the correct one.
-	 * (Required to support systems such as the Toshiba 5005-S504.)
-	 */
 	link->irq.active = irq;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Link at IRQ %d \n", link->irq.active));
@@ -278,32 +293,6 @@ end:
 }
 
 static int
-acpi_pci_link_try_get_current (
-	struct acpi_pci_link *link,
-	int irq)
-{
-	int result;
-
-	ACPI_FUNCTION_TRACE("acpi_pci_link_try_get_current");
-
-	result = acpi_pci_link_get_current(link);
-	if (result && link->irq.active) {
- 		return_VALUE(result);
- 	}
-
-	if (!link->irq.active) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n"));
-		printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for"
-			"device (%s [%s]).\n", irq,
-			acpi_device_name(link->device),
-			acpi_device_bid(link->device));
-		link->irq.active = irq;
-	}
-	
-	return 0;
-}
-
-static int
 acpi_pci_link_set (
 	struct acpi_pci_link	*link,
 	int			irq)
@@ -315,59 +304,24 @@ acpi_pci_link_set (
 		struct acpi_resource	end;
 	}                       resource;
 	struct acpi_buffer	buffer = {sizeof(resource)+1, &resource};
-	int			i = 0;
-	int			valid = 0;
-	int			resource_type = 0;
-   
+
 	ACPI_FUNCTION_TRACE("acpi_pci_link_set");
 
 	if (!link || !irq)
 		return_VALUE(-EINVAL);
 
-	/* We don't check irqs the first time around */
-	if (link->irq.setonboot) {
-		/* See if we're already at the target IRQ. */
-		if (irq == link->irq.active)
-			return_VALUE(0);
-
-		/* Make sure the target IRQ in the list of possible IRQs. */
-		for (i=0; i<link->irq.possible_count; i++) {
-			if (irq == link->irq.possible[i])
-				valid = 1;
-		}
-		if (!valid) {
-			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Target IRQ %d invalid\n", irq));
-			return_VALUE(-EINVAL);
-		}
-	}
-
-	resource_type = link->irq.resource_type;
-
-	if (resource_type != ACPI_RSTYPE_IRQ &&
-			resource_type != ACPI_RSTYPE_EXT_IRQ){
-	/* If IRQ<=15, first try with a "normal" IRQ descriptor. If that fails, try with
-	 * an extended one */
-		if (irq <= 15) {
-			resource_type = ACPI_RSTYPE_IRQ;
-		} else {
-			resource_type = ACPI_RSTYPE_EXT_IRQ;
-		}
-	} 
-
-retry_programming:
-   
 	memset(&resource, 0, sizeof(resource));
 
-	/* NOTE: PCI interrupts are always level / active_low / shared. But not all
-	   interrupts > 15 are PCI interrupts. Rely on the ACPI IRQ definition for 
-	   parameters */
-	switch(resource_type) {
+	switch(link->irq.resource_type) {
 	case ACPI_RSTYPE_IRQ:
 		resource.res.id = ACPI_RSTYPE_IRQ;
 		resource.res.length = sizeof(struct acpi_resource);
 		resource.res.data.irq.edge_level = link->irq.edge_level;
 		resource.res.data.irq.active_high_low = link->irq.active_high_low;
-		resource.res.data.irq.shared_exclusive = ACPI_SHARED;
+		if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
+			resource.res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+		else
+			resource.res.data.irq.shared_exclusive = ACPI_SHARED;
 		resource.res.data.irq.number_of_interrupts = 1;
 		resource.res.data.irq.interrupts[0] = irq;
 		break;
@@ -378,55 +332,63 @@ retry_programming:
 		resource.res.data.extended_irq.producer_consumer = ACPI_CONSUMER;
 		resource.res.data.extended_irq.edge_level = link->irq.edge_level;
 		resource.res.data.extended_irq.active_high_low = link->irq.active_high_low;
-		resource.res.data.extended_irq.shared_exclusive = ACPI_SHARED;
+		if (link->irq.edge_level == ACPI_EDGE_SENSITIVE)
+			resource.res.data.irq.shared_exclusive = ACPI_EXCLUSIVE;
+		else
+			resource.res.data.irq.shared_exclusive = ACPI_SHARED;
 		resource.res.data.extended_irq.number_of_interrupts = 1;
 		resource.res.data.extended_irq.interrupts[0] = irq;
 		/* ignore resource_source, it's optional */
 		break;
+	default:
+		printk("ACPI BUG: resource_type %d\n", link->irq.resource_type);
+		return_VALUE(-EINVAL);
 	}
 	resource.end.id = ACPI_RSTYPE_END_TAG;
 
 	/* Attempt to set the resource */
 	status = acpi_set_current_resources(link->handle, &buffer);
-   
 
-	/* if we failed and IRQ <= 15, try again with an extended descriptor */
-	if (ACPI_FAILURE(status) && (resource_type == ACPI_RSTYPE_IRQ)) {
-                resource_type = ACPI_RSTYPE_EXT_IRQ;
-                printk(PREFIX "Retrying with extended IRQ descriptor\n");
-                goto retry_programming;
-	}
-  
 	/* check for total failure */
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _SRS\n"));
 		return_VALUE(-ENODEV);
 	}
 
-	/* Make sure the device is enabled. */
+	/* Query _STA, set device->status */
 	result = acpi_bus_get_status(link->device);
 	if (result) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unable to read status\n"));
 		return_VALUE(result);
 	}
 	if (!link->device->status.enabled) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n"));
-		return_VALUE(-ENODEV);
+		printk(KERN_WARNING PREFIX
+			"%s [%s] disabled and referenced, BIOS bug.\n",
+			acpi_device_name(link->device),
+			acpi_device_bid(link->device));
 	}
 
-	/* Make sure the active IRQ is the one we requested. */
-	result = acpi_pci_link_try_get_current(link, irq);
+	/* Query _CRS, set link->irq.active */
+	result = acpi_pci_link_get_current(link);
 	if (result) {
 		return_VALUE(result);
 	}
-   
+
+	/*
+	 * Is current setting not what we set?
+	 * set link->irq.active
+	 */
 	if (link->irq.active != irq) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
-			"Attempt to enable at IRQ %d resulted in IRQ %d\n", 
-			irq, link->irq.active));
-		link->irq.active = 0;
-		acpi_ut_evaluate_object (link->handle, "_DIS", 0, NULL);	   
-		return_VALUE(-ENODEV);
+		/*
+		 * policy: when _CRS doesn't return what we just _SRS
+		 * assume _SRS worked and override _CRS value.
+		 */
+		printk(KERN_WARNING PREFIX
+			"%s [%s] BIOS reported IRQ %d, using IRQ %d\n",
+			acpi_device_name(link->device),
+			acpi_device_bid(link->device),
+			link->irq.active, irq);
+		link->irq.active = irq;
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Set IRQ %d\n", link->irq.active));
@@ -480,7 +442,7 @@ retry_programming:
 #define PIRQ_PENALTY_ISA_USED		(16*16*16*16*16)
 #define PIRQ_PENALTY_ISA_ALWAYS		(16*16*16*16*16*16)
 
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int __initdata acpi_irq_penalty[ACPI_MAX_IRQS] = {
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ0 timer */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ1 keyboard */
 	PIRQ_PENALTY_ISA_ALWAYS,	/* IRQ2 cascade */
@@ -493,7 +455,7 @@ static int acpi_irq_penalty[ACPI_MAX_IRQ
 	PIRQ_PENALTY_PCI_AVAILABLE,	/* IRQ9  PCI, often acpi */
 	PIRQ_PENALTY_PCI_AVAILABLE,	/* IRQ10 PCI */
 	PIRQ_PENALTY_PCI_AVAILABLE,	/* IRQ11 PCI */
-	PIRQ_PENALTY_ISA_TYPICAL,	/* IRQ12 mouse */
+	PIRQ_PENALTY_ISA_USED,	/* IRQ12 mouse */
 	PIRQ_PENALTY_ISA_USED,	/* IRQ13 fpe, sometimes */
 	PIRQ_PENALTY_ISA_USED,	/* IRQ14 ide0 */
 	PIRQ_PENALTY_ISA_USED,	/* IRQ15 ide1 */
@@ -553,10 +515,30 @@ static int acpi_pci_link_allocate(struct
 	if (link->irq.setonboot)
 		return_VALUE(0);
 
+	/*
+	 * search for active IRQ in list of possible IRQs.
+	 */
+	for (i = 0; i < link->irq.possible_count; ++i) {
+		if (link->irq.active == link->irq.possible[i])
+			break;
+	}
+	/*
+	 * forget active IRQ that is not in possible list
+	 */
+	if (i == link->irq.possible_count) {
+		if (acpi_strict)
+			printk(KERN_WARNING PREFIX "_CRS %d not found"
+				" in _PRS\n", link->irq.active);
+		link->irq.active = 0;
+	}
+
+	/*
+	 * if active found, use it; else pick entry from end of possible list.
+	 */
 	if (link->irq.active) {
 		irq = link->irq.active;
 	} else {
-		irq = link->irq.possible[0];
+		irq = link->irq.possible[link->irq.possible_count - 1];
 	}
 
 	if (acpi_irq_balance || !link->irq.active) {
@@ -572,7 +554,8 @@ static int acpi_pci_link_allocate(struct
 
 	/* Attempt to enable the link device at this IRQ. */
 	if (acpi_pci_link_set(link, irq)) {
-		printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS). Aborting ACPI-based IRQ routing. Try pci=noacpi or acpi=off\n",
+		printk(PREFIX "Unable to set IRQ for %s [%s] (likely buggy ACPI BIOS).\n"
+				"Try pci=noacpi or acpi=off\n",
 			acpi_device_name(link->device),
 			acpi_device_bid(link->device));
 		return_VALUE(-ENODEV);
@@ -624,7 +607,7 @@ acpi_pci_link_get_irq (
 		return_VALUE(0);
 
 	if (!link->irq.active) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link disabled\n"));
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
 		return_VALUE(0);
 	}
 
@@ -670,7 +653,6 @@ acpi_pci_link_add (
 	/* query and set link->irq.active */
 	acpi_pci_link_get_current(link);
 
-//#ifdef CONFIG_ACPI_DEBUG
 	printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device),
 		acpi_device_bid(device));
 	for (i = 0; i < link->irq.possible_count; i++) {
@@ -681,14 +663,25 @@ acpi_pci_link_add (
 		else
 			printk(" %d", link->irq.possible[i]);
 	}
-	printk(")\n");
-//#endif /* CONFIG_ACPI_DEBUG */
+
+	printk(")");
+
+	if (!found)
+		printk(" *%d", link->irq.active);
+
+	if(!link->device->status.enabled)
+		printk(", disabled.");
+
+	printk("\n");
 
 	/* TBD: Acquire/release lock */
 	list_add_tail(&link->node, &acpi_link.entries);
 	acpi_link.count++;
 
 end:
+	/* disable all links -- to be activated on use */
+	acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
+
 	if (result)
 		kfree(link);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/pci_root.c linux-2.4.27-rc4/drivers/acpi/pci_root.c
--- linux-2.4.26/drivers/acpi/pci_root.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/pci_root.c	2004-07-30 16:25:01.000000000 +0000
@@ -112,12 +112,47 @@ void acpi_pci_unregister_driver(struct a
 	}
 }
 
+static acpi_status
+get_root_bridge_busnr_callback (struct acpi_resource *resource, void *data)
+{
+	int *busnr = (int *)data;
+	struct acpi_resource_address64 address;
+
+	if (resource->id != ACPI_RSTYPE_ADDRESS16 &&
+	    resource->id != ACPI_RSTYPE_ADDRESS32 &&
+	    resource->id != ACPI_RSTYPE_ADDRESS64)
+		return AE_OK;
+
+	acpi_resource_to_address64(resource, &address);
+	if ((address.address_length > 0) && 
+	   (address.resource_type == ACPI_BUS_NUMBER_RANGE))
+		*busnr = address.min_address_range;
+
+	return AE_OK;
+}
+
+static acpi_status 
+try_get_root_bridge_busnr(acpi_handle handle, int *busnum)
+{
+	acpi_status status;
+
+	*busnum = -1;
+	status = acpi_walk_resources(handle, METHOD_NAME__CRS, get_root_bridge_busnr_callback, busnum);
+	if (ACPI_FAILURE(status))
+		return status;
+	/* Check if we really get a bus number from _CRS */
+	if (*busnum == -1)
+		return AE_ERROR;
+	return AE_OK;
+}
+
 static int
 acpi_pci_root_add (
 	struct acpi_device	*device)
 {
 	int			result = 0;
 	struct acpi_pci_root	*root = NULL;
+	struct acpi_pci_root	*tmp;
 	acpi_status		status = AE_OK;
 	unsigned long		value = 0;
 	acpi_handle		handle = NULL;
@@ -152,8 +187,6 @@ acpi_pci_root_add (
 	switch (status) {
 	case AE_OK:
 		root->id.segment = (u16) value;
-		printk("_SEG exists! Unsupported. Abort.\n");
-		BUG();
 		break;
 	case AE_NOT_FOUND:
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
@@ -187,6 +220,27 @@ acpi_pci_root_add (
 		goto end;
 	}
 
+	/* Some systems have wrong _BBN */
+	list_for_each_entry(tmp, &acpi_pci_roots, node) {
+		if ((tmp->id.segment == root->id.segment)
+				&& (tmp->id.bus == root->id.bus)) {
+			int bus = 0;
+			acpi_status status;
+
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
+				"Wrong _BBN value, please reboot and using option 'pci=noacpi'\n"));
+
+			status = try_get_root_bridge_busnr(root->handle, &bus);
+			if (ACPI_FAILURE(status))
+				break;
+			if (bus != root->id.bus) {
+				printk(KERN_INFO PREFIX "PCI _CRS %d overrides _BBN 0\n", bus);
+				root->id.bus = bus;
+			}
+			break;
+		}
+	}
+
 	/*
 	 * Device & Function
 	 * -----------------
@@ -213,7 +267,12 @@ acpi_pci_root_add (
 	 * PCI namespace does not get created until this call is made (and 
 	 * thus the root bridge's pci_dev does not exist).
 	 */
+#ifdef CONFIG_X86
 	root->bus = pcibios_scan_root(root->id.bus);
+#else
+	root->bus = pcibios_scan_root(root->handle,
+				      root->id.segment, root->id.bus);
+#endif
 	if (!root->bus) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 
 			"Bus %02x:%02x not present in PCI namespace\n", 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/power.c linux-2.4.27-rc4/drivers/acpi/power.c
--- linux-2.4.26/drivers/acpi/power.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/power.c	2004-07-30 16:25:20.000000000 +0000
@@ -469,6 +469,8 @@ acpi_power_remove_fs (
 	ACPI_FUNCTION_TRACE("acpi_power_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_POWER_FILE_STATUS,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_power_dir);
 		acpi_device_dir(device) = NULL;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/processor.c linux-2.4.27-rc4/drivers/acpi/processor.c
--- linux-2.4.26/drivers/acpi/processor.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/processor.c	2004-07-30 16:28:42.000000000 +0000
@@ -2011,6 +2011,7 @@ acpi_processor_add_fs (
 		if (!acpi_device_dir(device))
 			return_VALUE(-ENODEV);
 	}
+	acpi_device_dir(device)->owner = THIS_MODULE;
 
 	/* 'info' [R] */
 	entry = create_proc_entry(ACPI_PROCESSOR_FILE_INFO,
@@ -2022,6 +2023,7 @@ acpi_processor_add_fs (
 	else {
 		entry->read_proc = acpi_processor_read_info;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'power' [R] */
@@ -2034,6 +2036,7 @@ acpi_processor_add_fs (
 	else {
 		entry->read_proc = acpi_processor_read_power;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'performance' [R/W] */
@@ -2047,6 +2050,7 @@ acpi_processor_add_fs (
 		entry->read_proc = acpi_processor_read_performance;
 		entry->write_proc = acpi_processor_write_performance;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'throttling' [R/W] */
@@ -2060,6 +2064,7 @@ acpi_processor_add_fs (
 		entry->read_proc = acpi_processor_read_throttling;
 		entry->write_proc = acpi_processor_write_throttling;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'limit' [R/W] */
@@ -2073,6 +2078,7 @@ acpi_processor_add_fs (
 		entry->read_proc = acpi_processor_read_limit;
 		entry->write_proc = acpi_processor_write_limit;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	return_VALUE(0);
@@ -2349,6 +2355,7 @@ acpi_processor_init (void)
 	acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
 	if (!acpi_processor_dir)
 		return_VALUE(-ENODEV);
+	acpi_processor_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&acpi_processor_driver);
 	if (result < 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/tables.c linux-2.4.27-rc4/drivers/acpi/tables.c
--- linux-2.4.26/drivers/acpi/tables.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/tables.c	2004-07-30 16:26:08.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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/thermal.c linux-2.4.27-rc4/drivers/acpi/thermal.c
--- linux-2.4.26/drivers/acpi/thermal.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/thermal.c	2004-07-30 16:29:20.000000000 +0000
@@ -227,6 +227,13 @@ acpi_thermal_set_cooling_mode (
 	status = acpi_get_handle(tz->handle, "_SCP", &handle);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n"));
+		status = acpi_get_handle(tz->handle, "_PSV", &handle);
+		if(!ACPI_FAILURE(status)) {
+			tz->cooling_mode = 1;
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", 
+				mode?"passive":"active"));
+			return_VALUE(0);
+		}
 		return_VALUE(-ENODEV);
 	}
 
@@ -1051,6 +1058,7 @@ acpi_thermal_add_fs (
 			acpi_thermal_dir);
 		if (!acpi_device_dir(device))
 			return_VALUE(-ENODEV);
+		acpi_device_dir(device)->owner = THIS_MODULE;
 	}
 
 	/* 'state' [R] */
@@ -1063,6 +1071,7 @@ acpi_thermal_add_fs (
 	else {
 		entry->read_proc = acpi_thermal_read_state;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'temperature' [R] */
@@ -1075,6 +1084,7 @@ acpi_thermal_add_fs (
 	else {
 		entry->read_proc = acpi_thermal_read_temperature;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'trip_points' [R/W] */
@@ -1088,6 +1098,7 @@ acpi_thermal_add_fs (
 		entry->read_proc = acpi_thermal_read_trip_points;
 		entry->write_proc = acpi_thermal_write_trip_points;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'cooling_mode' [R/W] */
@@ -1101,6 +1112,7 @@ acpi_thermal_add_fs (
 		entry->read_proc = acpi_thermal_read_cooling_mode;
 		entry->write_proc = acpi_thermal_write_cooling_mode;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	/* 'polling_frequency' [R/W] */
@@ -1114,6 +1126,7 @@ acpi_thermal_add_fs (
 		entry->read_proc = acpi_thermal_read_polling;
 		entry->write_proc = acpi_thermal_write_polling;
 		entry->data = acpi_driver_data(device);
+		entry->owner = THIS_MODULE;
 	}
 
 	return_VALUE(0);
@@ -1127,6 +1140,16 @@ acpi_thermal_remove_fs (
 	ACPI_FUNCTION_TRACE("acpi_thermal_remove_fs");
 
 	if (acpi_device_dir(device)) {
+		remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
+				  acpi_device_dir(device));
+		remove_proc_entry(ACPI_THERMAL_FILE_STATE,
+				  acpi_device_dir(device));
 		remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
 		acpi_device_dir(device) = NULL;
 	}
@@ -1332,6 +1355,7 @@ acpi_thermal_init (void)
 	acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
 	if (!acpi_thermal_dir)
 		return_VALUE(-ENODEV);
+	acpi_thermal_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&acpi_thermal_driver);
 	if (result < 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/acpi/toshiba_acpi.c linux-2.4.27-rc4/drivers/acpi/toshiba_acpi.c
--- linux-2.4.26/drivers/acpi/toshiba_acpi.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/acpi/toshiba_acpi.c	2004-07-30 16:25:38.000000000 +0000
@@ -503,6 +503,8 @@ add_device(void)
 		proc = create_proc_read_entry(item->name,
 			S_IFREG | S_IRUGO | S_IWUSR,
 			toshiba_proc_dir, (read_proc_t*)dispatch_read, item);
+		if (proc)
+			proc->owner = THIS_MODULE;
 		if (proc && item->write_func)
 			proc->write_proc = (write_proc_t*)dispatch_write;
 	}
@@ -526,6 +528,8 @@ toshiba_acpi_init(void)
 	acpi_status status = AE_OK;
 	u32 hci_result;
 
+	if (acpi_disabled)
+		return -ENODEV;
 	/* simple device detection: look for HCI method */
 	if (is_valid_acpi_path(METHOD_HCI_1))
 		method_hci = METHOD_HCI_1;
@@ -548,6 +552,7 @@ toshiba_acpi_init(void)
 	if (!toshiba_proc_dir) {
 		status = AE_ERROR;
 	} else {
+		toshiba_proc_dir->owner = THIS_MODULE;
 		status = add_device();
 		if (ACPI_FAILURE(status))
 			remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/atm/Config.in linux-2.4.27-rc4/drivers/atm/Config.in
--- linux-2.4.26/drivers/atm/Config.in	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.27-rc4/drivers/atm/Config.in	2004-07-30 16:30:52.000000000 +0000
@@ -83,6 +83,7 @@ if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBU
   fi
   if [ "$CONFIG_ATM_FORE200E_PCA" = "y" -o "$CONFIG_ATM_FORE200E_SBA" = "y" ]; \
     then
+    bool '  Defer interrupt work to a tasklet' CONFIG_ATM_FORE200E_USE_TASKLET
     int  '  Maximum number of tx retries' CONFIG_ATM_FORE200E_TX_RETRY 16
     int  '  Debugging level (0-3)' CONFIG_ATM_FORE200E_DEBUG 0
     if [ "$CONFIG_ATM_FORE200E_MAYBE" = "y" ]; then
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/atm/fore200e.c linux-2.4.27-rc4/drivers/atm/fore200e.c
--- linux-2.4.26/drivers/atm/fore200e.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/drivers/atm/fore200e.c	2004-07-30 16:31:57.000000000 +0000
@@ -2,7 +2,7 @@
   $Id: fore200e.c,v 1.5 2000/04/14 10:10:34 davem Exp $
 
   A FORE Systems 200E-series driver for ATM on Linux.
-  Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2000.
+  Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2003.
 
   Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de).
 
@@ -34,6 +34,8 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/module.h>
 #include <linux/atmdev.h>
 #include <linux/sonet.h>
 #include <linux/atm_suni.h>
@@ -46,7 +48,6 @@
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
-#include <linux/pci.h>
 
 #ifdef CONFIG_ATM_FORE200E_SBA
 #include <asm/idprom.h>
@@ -56,25 +57,33 @@
 #include <asm/pgtable.h>
 #endif
 
-#include <linux/module.h>
+#if defined(CONFIG_ATM_FORE200E_USE_TASKLET) /* defer interrupt work to a tasklet */
+#define FORE200E_USE_TASKLET
+#endif
 
-#include "fore200e.h"
-#include "suni.h"
+#if 0 /* enable the debugging code of the buffer supply queues */
+#define FORE200E_BSQ_DEBUG
+#endif
 
-#if 1   /* ensure correct handling of 52-byte AAL0 SDUs used by atmdump-like apps */
+#if 1 /* ensure correct handling of 52-byte AAL0 SDUs expected by atmdump-like apps */
 #define FORE200E_52BYTE_AAL0_SDU
 #endif
 
-#define FORE200E_VERSION "0.2d"
+#include "fore200e.h"
+#include "suni.h"
 
+#define FORE200E_VERSION "0.3e"
 
 #define FORE200E         "fore200e: "
 
+#if 0 /* override .config */
+#define CONFIG_ATM_FORE200E_DEBUG 1
+#endif
 #if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG > 0)
 #define DPRINTK(level, format, args...)  do { if (CONFIG_ATM_FORE200E_DEBUG >= (level)) \
-                                                  printk(FORE200E format, ##args); } while(0)
+                                                  printk(FORE200E format, ##args); } while (0)
 #else
-#define DPRINTK(level, format, args...)  while(0)
+#define DPRINTK(level, format, args...)  do {} while (0)
 #endif
 
 
@@ -85,18 +94,28 @@
 
 #define FORE200E_INDEX(virt_addr, type, index)     (&((type *)(virt_addr))[ index ])
 
-#define FORE200E_NEXT_ENTRY(index, modulo)    (index = ++(index) % (modulo))
+#define FORE200E_NEXT_ENTRY(index, modulo)         (index = ++(index) % (modulo))
 
 
 #define MSECS(ms)  (((ms)*HZ/1000)+1)
 
 
+#if 1
+#define ASSERT(expr)     if (!(expr)) { \
+                             printk(FORE200E "assertion failed! %s[%d]: %s\n", \
+			            __FUNCTION__, __LINE__, #expr); \
+                             panic(FORE200E "%s", __FUNCTION__); \
+                         }
+#else
+#define ASSERT(expr)     do {} while (0)
+#endif
+
+
 extern const struct atmdev_ops   fore200e_ops;
 extern const struct fore200e_bus fore200e_bus[];
 
 static struct fore200e* fore200e_boards = NULL;
 
-
 #ifdef MODULE
 MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");
 MODULE_DESCRIPTION("FORE Systems 200E-series ATM driver - version " FORE200E_VERSION);
@@ -225,29 +244,6 @@ fore200e_chunk_free(struct fore200e* for
 }
 
 
-
-#if 0 /* currently unused */
-static int
-fore200e_checkup(struct fore200e* fore200e)
-{
-    u32 hb1, hb2;
-
-    hb1 = fore200e->bus->read(&fore200e->cp_queues->heartbeat);
-    fore200e_spin(10);
-    hb2 = fore200e->bus->read(&fore200e->cp_queues->heartbeat);
-    
-    if (hb2 <= hb1) {
-	printk(FORE200E "device %s heartbeat is not counting upwards, hb1 = %x; hb2 = %x\n",
-	       fore200e->name, hb1, hb2);
-	return -EIO;
-    }
-    printk(FORE200E "device %s heartbeat is ok\n", fore200e->name);
-    
-    return 0;
-}
-#endif 
-
-
 static void
 fore200e_spin(int msecs)
 {
@@ -444,7 +440,6 @@ fore200e_shutdown(struct fore200e* fore2
 }
 
 
-
 #ifdef CONFIG_ATM_FORE200E_PCA
 
 static u32 fore200e_pca_read(volatile u32* addr)
@@ -501,20 +496,16 @@ static int
 fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
 			     int size, int nbr, int alignment)
 {
-#if defined(__sparc_v9__)
     /* returned chunks are page-aligned */
+    chunk->alloc_size = size * nbr;
     chunk->alloc_addr = pci_alloc_consistent((struct pci_dev*)fore200e->bus_dev,
 					     chunk->alloc_size,
 					     &chunk->dma_addr);
     
-    if (chunk->alloc_addr == NULL || chunk->dma_addr == 0)
+    if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0))
 	return -ENOMEM;
 
     chunk->align_addr = chunk->alloc_addr;
-#else
-    if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment, FORE200E_DMA_BIDIRECTIONAL) < 0)
-	return -ENOMEM;
-#endif
     
     return 0;
 }
@@ -525,14 +516,10 @@ fore200e_pca_dma_chunk_alloc(struct fore
 static void
 fore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
 {
-#if defined(__sparc_v9__)
     pci_free_consistent((struct pci_dev*)fore200e->bus_dev,
 			chunk->alloc_size,
 			chunk->alloc_addr,
 			chunk->dma_addr);
-#else
-    fore200e_chunk_free(fore200e, chunk);
-#endif
 }
 
 
@@ -540,7 +527,15 @@ static int
 fore200e_pca_irq_check(struct fore200e* fore200e)
 {
     /* this is a 1 bit register */
-    return readl(fore200e->regs.pca.psr);
+    int irq_posted = readl(fore200e->regs.pca.psr);
+
+#if defined(CONFIG_ATM_FORE200E_DEBUG) && (CONFIG_ATM_FORE200E_DEBUG == 2)
+    if (irq_posted && (readl(fore200e->regs.pca.hcr) & PCA200E_HCR_OUTFULL)) {
+	DPRINTK(2,"FIFO OUT full, device %d\n", fore200e->atm_dev->number);
+    }
+#endif
+
+    return irq_posted;
 }
 
 
@@ -574,7 +569,7 @@ fore200e_pca_map(struct fore200e* fore20
 
     DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
 
-    /* gain access to the PCA-200E specific registers  */
+    /* gain access to the PCA specific registers  */
     fore200e->regs.pca.hcr = (u32*)(fore200e->virt_base + PCA200E_HCR_OFFSET);
     fore200e->regs.pca.imr = (u32*)(fore200e->virt_base + PCA200E_IMR_OFFSET);
     fore200e->regs.pca.psr = (u32*)(fore200e->virt_base + PCA200E_PSR_OFFSET);
@@ -589,8 +584,6 @@ fore200e_pca_unmap(struct fore200e* fore
 {
     DPRINTK(2, "device %s being unmapped from memory\n", fore200e->name);
 
-    /* XXX iounmap() does nothing on PowerPC (at least in 2.2.12 and 2.3.41),
-       this leads to a kernel panic if the module is loaded and unloaded several times */
     if (fore200e->virt_base != NULL)
 	iounmap(fore200e->virt_base);
 }
@@ -600,7 +593,7 @@ static int __init
 fore200e_pca_configure(struct fore200e* fore200e)
 {
     struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;
-    u8              master_ctrl;
+    u8              master_ctrl, latency;
 
     DPRINTK(2, "device %s being configured\n", fore200e->name);
 
@@ -609,21 +602,29 @@ fore200e_pca_configure(struct fore200e* 
 	return -EIO;
     }
 
-	pci_read_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, &master_ctrl);
+    pci_read_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, &master_ctrl);
 
     master_ctrl = master_ctrl
-#if 0
-	| PCA200E_CTRL_DIS_CACHE_RD
-        | PCA200E_CTRL_DIS_WRT_INVAL
-#endif
 #if defined(__BIG_ENDIAN)
 	/* request the PCA board to convert the endianess of slave RAM accesses */
 	| PCA200E_CTRL_CONVERT_ENDIAN
 #endif
+#if 0
+        | PCA200E_CTRL_DIS_CACHE_RD
+        | PCA200E_CTRL_DIS_WRT_INVAL
+        | PCA200E_CTRL_ENA_CONT_REQ_MODE
+        | PCA200E_CTRL_2_CACHE_WRT_INVAL
+#endif
 	| PCA200E_CTRL_LARGE_PCI_BURSTS;
     
     pci_write_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, master_ctrl);
 
+    /* raise latency from 32 (default) to 192, as this seems to prevent NIC
+       lockups (under heavy rx loads) due to continuous 'FIFO OUT full' condition.
+       this may impact the performances of other PCI devices on the same bus, though */
+    latency = 192;
+    pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
+
     fore200e->state = FORE200E_STATE_CONFIGURE;
     return 0;
 }
@@ -657,11 +658,7 @@ fore200e_pca_detect(const struct fore200
     fore200e->bus       = bus;
     fore200e->bus_dev   = pci_dev;    
     fore200e->irq       = pci_dev->irq;
-    fore200e->phys_base = pci_resource_start (pci_dev, 0);
-
-#if defined(__powerpc__)
-    fore200e->phys_base += KERNELBASE;
-#endif
+    fore200e->phys_base = pci_resource_start(pci_dev, 0);
 
     sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
 
@@ -729,8 +726,6 @@ fore200e_pca_proc_read(struct fore200e* 
 #endif /* CONFIG_ATM_FORE200E_PCA */
 
 
-
-
 #ifdef CONFIG_ATM_FORE200E_SBA
 
 static u32
@@ -792,7 +787,7 @@ fore200e_sba_dma_chunk_alloc(struct fore
 					      chunk->alloc_size,
 					      &chunk->dma_addr);
 
-    if (chunk->alloc_addr == NULL || chunk->dma_addr == 0)
+    if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0))
 	return -ENOMEM;
 
     chunk->align_addr = chunk->alloc_addr;
@@ -851,8 +846,7 @@ fore200e_sba_map(struct fore200e* fore20
     struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;
     unsigned int bursts;
 
-    /* gain access to the SBA-200E specific registers  */
-    
+    /* gain access to the SBA specific registers  */
     fore200e->regs.sba.hcr = (u32*)sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
     fore200e->regs.sba.bsr = (u32*)sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
     fore200e->regs.sba.isr = (u32*)sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
@@ -873,17 +867,6 @@ fore200e_sba_map(struct fore200e* fore20
     if (sbus_can_dma_64bit(sbus_dev))
 	sbus_set_sbus64(sbus_dev, bursts);
 
-#if 0
-    if (bursts & DMA_BURST16)
-	fore200e->bus->write(SBA200E_BSR_BURST16, fore200e->regs.sba.bsr);
-    else
-    if (bursts & DMA_BURST8)
-       fore200e->bus->write(SBA200E_BSR_BURST8, fore200e->regs.sba.bsr);
-    else
-    if (bursts & DMA_BURST4)
-        fore200e->bus->write(SBA200E_BSR_BURST4, fore200e->regs.sba.bsr);
-#endif
-
     fore200e->state = FORE200E_STATE_MAP;
     return 0;
 }
@@ -928,13 +911,11 @@ fore200e_sba_detect(const struct fore200
     return NULL;
     
   found:
-#if 1
     if (sbus_dev->num_registers != 4) {
 	printk(FORE200E "this %s device has %d instead of 4 registers\n",
 	       bus->model_name, sbus_dev->num_registers);
 	return NULL;
     }
-#endif
 
     fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
     if (fore200e == NULL)
@@ -987,46 +968,143 @@ fore200e_sba_proc_read(struct fore200e* 
 
 
 static void
-fore200e_irq_tx(struct fore200e* fore200e)
+fore200e_tx_irq(struct fore200e* fore200e)
 {
-    struct host_txq_entry* entry;
-    int i;
-    
-    entry = fore200e->host_txq.host_entry;
+    struct host_txq*        txq = &fore200e->host_txq;
+    struct host_txq_entry*  entry;
+    struct atm_vcc*         vcc;
+    struct fore200e_vc_map* vc_map;
 
-    for (i = 0; i < QUEUE_SIZE_TX; i++) {
+    if (fore200e->host_txq.txing == 0)
+	return;
+
+    for (;;) {
+	
+	entry = &txq->host_entry[ txq->tail ];
 
-	if (*entry->status & STATUS_COMPLETE) {
+        if ((*entry->status & STATUS_COMPLETE) == 0) {
+	    break;
+	}
 
-	    DPRINTK(3, "TX COMPLETED: entry = %p, vcc = %p, skb = %p\n", entry, entry->vcc, entry->skb);
+	DPRINTK(3, "TX COMPLETED: entry = %p [tail = %d], vc_map = %p, skb = %p\n", 
+		entry, txq->tail, entry->vc_map, entry->skb);
 
-	    /* free copy of misaligned data */
-	    if (entry->data)
-		kfree(entry->data);
+	/* free copy of misaligned data */
+	if (entry->data)
+	    kfree(entry->data);
+	
+	/* remove DMA mapping */
+	fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
+				 FORE200E_DMA_TODEVICE);
 
-	    /* remove DMA mapping */
-	    fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
-				     FORE200E_DMA_TODEVICE);
+	vc_map = entry->vc_map;
 
-	    /* notify tx completion */
-	    if (entry->vcc->pop)
-		entry->vcc->pop(entry->vcc, entry->skb);
-	    else
-		dev_kfree_skb_irq(entry->skb);
+	/* vcc closed since the time the entry was submitted for tx? */
+	if ((vc_map->vcc == NULL) ||
+	    (test_bit(ATM_VF_READY, &vc_map->vcc->flags) == 0)) {
 
-	    /* check error condition */
-	    if (*entry->status & STATUS_ERROR)
-		atomic_inc(&entry->vcc->stats->tx_err);
-	    else
-		atomic_inc(&entry->vcc->stats->tx);
+	    DPRINTK(1, "no ready vcc found for PDU sent on device %d\n",
+		    fore200e->atm_dev->number);
 
-	    *entry->status = STATUS_FREE;
-	    
-	    fore200e->host_txq.txing--;
+	    dev_kfree_skb_any(entry->skb);
+	}
+	else {
+	    ASSERT(vc_map->vcc);
+
+	    /* vcc closed then immediately re-opened? */
+	    if (vc_map->incarn != entry->incarn) {
+
+		/* when a vcc is closed, some PDUs may be still pending in the tx queue.
+		   if the same vcc is immediately re-opened, those pending PDUs must
+		   not be popped after the completion of their emission, as they refer
+		   to the prior incarnation of that vcc. otherwise, vcc->sk->wmem_alloc
+		   would be decremented by the size of the (unrelated) skb, possibly
+		   leading to a negative sk->wmem_alloc count, ultimately freezing the vcc.
+		   we thus bind the tx entry to the current incarnation of the vcc
+		   when the entry is submitted for tx. When the tx later completes,
+		   if the incarnation number of the tx entry does not match the one
+		   of the vcc, then this implies that the vcc has been closed then re-opened.
+		   we thus just drop the skb here. */
+
+		DPRINTK(1, "vcc closed-then-re-opened; dropping PDU sent on device %d\n",
+			fore200e->atm_dev->number);
+
+		dev_kfree_skb_any(entry->skb);
+	    }
+	    else {
+		vcc = vc_map->vcc;
+		ASSERT(vcc);
+
+		/* notify tx completion */
+		if (vcc->pop) {
+		    vcc->pop(vcc, entry->skb);
+		}
+		else {
+		    dev_kfree_skb_any(entry->skb);
+		}
+#if 1
+		/* race fixed by the above incarnation mechanism, but... */
+		if (atomic_read(&vcc->sk->wmem_alloc) < 0) {
+		    atomic_set(&vcc->sk->wmem_alloc, 0);
+		}
+#endif
+		/* check error condition */
+		if (*entry->status & STATUS_ERROR)
+		    atomic_inc(&vcc->stats->tx_err);
+		else
+		    atomic_inc(&vcc->stats->tx);
+	    }
+	}
+
+	*entry->status = STATUS_FREE;
+
+	fore200e->host_txq.txing--;
+
+	FORE200E_NEXT_ENTRY(txq->tail, QUEUE_SIZE_TX);
+    }
+}
+
+
+#ifdef FORE200E_BSQ_DEBUG
+int bsq_audit(int where, struct host_bsq* bsq, int scheme, int magn)
+{
+    struct buffer* buffer;
+    int count = 0;
+
+    buffer = bsq->freebuf;
+    while (buffer) {
+
+	if (buffer->supplied) {
+	    printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld supplied but in free list!\n",
+		   where, scheme, magn, buffer->index);
+	}
+
+	if (buffer->magn != magn) {
+	    printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected magn = %d\n",
+		   where, scheme, magn, buffer->index, buffer->magn);
+	}
+
+	if (buffer->scheme != scheme) {
+	    printk(FORE200E "bsq_audit(%d): queue %d.%d, buffer %ld, unexpected scheme = %d\n",
+		   where, scheme, magn, buffer->index, buffer->scheme);
+	}
+
+	if ((buffer->index < 0) || (buffer->index >= fore200e_rx_buf_nbr[ scheme ][ magn ])) {
+	    printk(FORE200E "bsq_audit(%d): queue %d.%d, out of range buffer index = %ld !\n",
+		   where, scheme, magn, buffer->index);
 	}
-	entry++;
+
+	count++;
+	buffer = buffer->next;
+    }
+
+    if (count != bsq->freebuf_count) {
+	printk(FORE200E "bsq_audit(%d): queue %d.%d, %d bufs in free list, but freebuf_count = %d\n",
+	       where, scheme, magn, count, bsq->freebuf_count);
     }
+    return 0;
 }
+#endif
 
 
 static void
@@ -1043,28 +1121,42 @@ fore200e_supply(struct fore200e* fore200
 
 	    bsq = &fore200e->host_bsq[ scheme ][ magn ];
 
-	    if (fore200e_rx_buf_nbr[ scheme ][ magn ] - bsq->count > RBD_BLK_SIZE) {
+#ifdef FORE200E_BSQ_DEBUG
+	    bsq_audit(1, bsq, scheme, magn);
+#endif
+	    while (bsq->freebuf_count >= RBD_BLK_SIZE) {
 
-		DPRINTK(2, "supplying rx buffers to queue %d / %d, count = %d\n",
-			scheme, magn, bsq->count);
+		DPRINTK(2, "supplying %d rx buffers to queue %d / %d, freebuf_count = %d\n",
+			RBD_BLK_SIZE, scheme, magn, bsq->freebuf_count);
 
 		entry = &bsq->host_entry[ bsq->head ];
-		
-		FORE200E_NEXT_ENTRY(bsq->head, QUEUE_SIZE_BS);
 
 		for (i = 0; i < RBD_BLK_SIZE; i++) {
 
-		    buffer = &bsq->buffer[ bsq->free ];
-		    
-		    FORE200E_NEXT_ENTRY(bsq->free, fore200e_rx_buf_nbr[ scheme ][ magn ]);
+		    /* take the first buffer in the free buffer list */
+		    buffer = bsq->freebuf;
+		    if (!buffer) {
+			printk(FORE200E "no more free bufs in queue %d.%d, but freebuf_count = %d\n",
+			       scheme, magn, bsq->freebuf_count);
+			return;
+		    }
+		    bsq->freebuf = buffer->next;
 		    
+#ifdef FORE200E_BSQ_DEBUG
+		    if (buffer->supplied)
+			printk(FORE200E "queue %d.%d, buffer %lu already supplied\n",
+			       scheme, magn, buffer->index);
+		    buffer->supplied = 1;
+#endif
 		    entry->rbd_block->rbd[ i ].buffer_haddr = buffer->data.dma_addr;
 		    entry->rbd_block->rbd[ i ].handle       = FORE200E_BUF2HDL(buffer);
 		}
 
-		/* increase the number of supplied rx buffers */
-		bsq->count += RBD_BLK_SIZE;
-		
+		FORE200E_NEXT_ENTRY(bsq->head, QUEUE_SIZE_BS);
+
+ 		/* decrease accordingly the number of free rx buffers */
+		bsq->freebuf_count -= RBD_BLK_SIZE;
+
 		*entry->status = STATUS_PENDING;
 		fore200e->bus->write(entry->rbd_block_dma, &entry->cp_entry->rbd_block_haddr);
 	    }
@@ -1073,33 +1165,9 @@ fore200e_supply(struct fore200e* fore200
 }
 
 
-
-static struct atm_vcc* 
-fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd)
-{
-    struct sock *s;
-    struct atm_vcc* vcc;
-
-    read_lock(&vcc_sklist_lock);
-    for(s = vcc_sklist; s; s = s->next) {
-	vcc = s->protinfo.af_atm;
-	if (vcc->dev != fore200e->atm_dev)
-		continue;
-	if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci) {
-            read_unlock(&vcc_sklist_lock);
-	    return vcc;
-	}
-    }
-    read_unlock(&vcc_sklist_lock);
-
-    return NULL;
-}
-
-
-static void
-fore200e_push_rpd(struct fore200e* fore200e, struct rpd* rpd)
+static int
+fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rpd)
 {
-    struct atm_vcc*      vcc;
     struct sk_buff*      skb;
     struct buffer*       buffer;
     struct fore200e_vcc* fore200e_vcc;
@@ -1108,15 +1176,10 @@ fore200e_push_rpd(struct fore200e* fore2
     u32                  cell_header = 0;
 #endif
 
-    vcc = fore200e_find_vcc(fore200e, rpd);
-    if (vcc == NULL) {
-	
-	printk(FORE200E "no vcc found for PDU received on %d.%d.%d\n",
-	       fore200e->atm_dev->number, rpd->atm_header.vpi, rpd->atm_header.vci);
-	return;
-    }
-
+    ASSERT(vcc);
+    
     fore200e_vcc = FORE200E_VCC(vcc);
+    ASSERT(fore200e_vcc);
 
 #ifdef FORE200E_52BYTE_AAL0_SDU
     if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.rxtp.max_sdu == ATM_AAL0_SDU)) {
@@ -1136,10 +1199,10 @@ fore200e_push_rpd(struct fore200e* fore2
     
     skb = alloc_skb(pdu_len, GFP_ATOMIC);
     if (skb == NULL) {
-	
-	printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
+	DPRINTK(2, "unable to alloc new skb, rx PDU length = %d\n", pdu_len);
+
 	atomic_inc(&vcc->stats->rx_drop);
-	return;
+	return -ENOMEM;
     } 
 
     skb->stamp = xtime;
@@ -1161,13 +1224,14 @@ fore200e_push_rpd(struct fore200e* fore2
 	
 	memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length);
     }
-    
+
     DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize);
     
     if (pdu_len < fore200e_vcc->rx_min_pdu)
 	fore200e_vcc->rx_min_pdu = pdu_len;
     if (pdu_len > fore200e_vcc->rx_max_pdu)
 	fore200e_vcc->rx_max_pdu = pdu_len;
+    fore200e_vcc->rx_pdu++;
 
     /* push PDU */
     if (atm_charge(vcc, skb->truesize) == 0) {
@@ -1175,37 +1239,63 @@ fore200e_push_rpd(struct fore200e* fore2
 	DPRINTK(2, "receive buffers saturated for %d.%d.%d - PDU dropped\n",
 		vcc->itf, vcc->vpi, vcc->vci);
 
-	dev_kfree_skb_irq(skb);
-	return;
+	dev_kfree_skb_any(skb);
+
+	atomic_inc(&vcc->stats->rx_drop);
+	return -ENOMEM;
     }
 
+    ASSERT(atomic_read(&vcc->sk->wmem_alloc) >= 0);
+
     vcc->push(vcc, skb);
     atomic_inc(&vcc->stats->rx);
+
+    ASSERT(atomic_read(&vcc->sk->wmem_alloc) >= 0);
+
+    return 0;
 }
 
 
 static void
 fore200e_collect_rpd(struct fore200e* fore200e, struct rpd* rpd)
 {
-    struct buffer* buffer;
-    int            i;
+    struct host_bsq* bsq;
+    struct buffer*   buffer;
+    int              i;
     
     for (i = 0; i < rpd->nseg; i++) {
 
 	/* rebuild rx buffer address from rsd handle */
 	buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);
 
-	/* decrease the number of supplied rx buffers */
-	fore200e->host_bsq[ buffer->scheme ][ buffer->magn ].count--;
+	bsq = &fore200e->host_bsq[ buffer->scheme ][ buffer->magn ];
+
+#ifdef FORE200E_BSQ_DEBUG
+	bsq_audit(2, bsq, buffer->scheme, buffer->magn);
+
+	if (buffer->supplied == 0)
+	    printk(FORE200E "queue %d.%d, buffer %ld was not supplied\n",
+		   buffer->scheme, buffer->magn, buffer->index);
+	buffer->supplied = 0;
+#endif
+
+	/* re-insert the buffer into the free buffer list */
+	buffer->next = bsq->freebuf;
+	bsq->freebuf = buffer;
+
+	/* then increment the number of free rx buffers */
+	bsq->freebuf_count++;
     }
 }
 
 
 static void
-fore200e_irq_rx(struct fore200e* fore200e)
+fore200e_rx_irq(struct fore200e* fore200e)
 {
-    struct host_rxq*       rxq = &fore200e->host_rxq;
-    struct host_rxq_entry* entry;
+    struct host_rxq*        rxq = &fore200e->host_rxq;
+    struct host_rxq_entry*  entry;
+    struct atm_vcc*         vcc;
+    struct fore200e_vc_map* vc_map;
 
     for (;;) {
 	
@@ -1215,28 +1305,61 @@ fore200e_irq_rx(struct fore200e* fore200
 	if ((*entry->status & STATUS_COMPLETE) == 0)
 	    break;
 
-	FORE200E_NEXT_ENTRY(rxq->head, QUEUE_SIZE_RX);
+	vc_map = FORE200E_VC_MAP(fore200e, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
 
-	if ((*entry->status & STATUS_ERROR) == 0) {
+	if ((vc_map->vcc == NULL) || 
+	    (test_bit(ATM_VF_READY, &vc_map->vcc->flags) == 0)) {
 
-	    fore200e_push_rpd(fore200e, entry->rpd);
+	    DPRINTK(1, "no ready VC found for PDU received on %d.%d.%d\n",
+		    fore200e->atm_dev->number,
+		    entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
 	}
 	else {
-	    printk(FORE200E "damaged PDU on %d.%d.%d\n", 
-		   fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
+	    vcc = vc_map->vcc;
+	    ASSERT(vcc);
+
+	    if ((*entry->status & STATUS_ERROR) == 0) {
+
+		fore200e_push_rpd(fore200e, vcc, entry->rpd);
+	    }
+	    else {
+		DPRINTK(2, "damaged PDU on %d.%d.%d\n", 
+			fore200e->atm_dev->number,
+			entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);
+		atomic_inc(&vcc->stats->rx_err);
+	    }
 	}
 
-	fore200e_collect_rpd(fore200e, entry->rpd);
+	FORE200E_NEXT_ENTRY(rxq->head, QUEUE_SIZE_RX);
 
-	fore200e_supply(fore200e);
+	fore200e_collect_rpd(fore200e, entry->rpd);
 
 	/* rewrite the rpd address to ack the received PDU */
 	fore200e->bus->write(entry->rpd_dma, &entry->cp_entry->rpd_haddr);
 	*entry->status = STATUS_FREE;
+
+	fore200e_supply(fore200e);
     }
 }
 
 
+#ifndef FORE200E_USE_TASKLET
+static void 
+fore200e_irq(struct fore200e* fore200e)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&fore200e->q_lock, flags);
+    fore200e_rx_irq(fore200e);
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+    
+    spin_lock_irqsave(&fore200e->q_lock, flags);
+    fore200e_tx_irq(fore200e);
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+}
+#endif
+
+
 static void
 fore200e_interrupt(int irq, void* dev, struct pt_regs* regs)
 {
@@ -1244,57 +1367,65 @@ fore200e_interrupt(int irq, void* dev, s
 
     if (fore200e->bus->irq_check(fore200e) == 0) {
 	
-	DPRINTK(3, "unexpected interrupt on device %c\n", fore200e->name[9]);
+	DPRINTK(3, "interrupt NOT triggered by device %d\n", fore200e->atm_dev->number);
 	return;
     }
-    DPRINTK(3, "valid interrupt on device %c\n", fore200e->name[9]);
+    DPRINTK(3, "interrupt triggered by device %d\n", fore200e->atm_dev->number);
 
-    tasklet_schedule(&fore200e->tasklet);
+#ifdef FORE200E_USE_TASKLET
+    tasklet_schedule(&fore200e->tx_tasklet);
+    tasklet_schedule(&fore200e->rx_tasklet);
+#else
+    fore200e_irq(fore200e);
+#endif
     
     fore200e->bus->irq_ack(fore200e);
 }
 
 
+#ifdef FORE200E_USE_TASKLET
 static void
-fore200e_tasklet(unsigned long data)
+fore200e_tx_tasklet(unsigned long data)
 {
     struct fore200e* fore200e = (struct fore200e*) data;
+    unsigned long    flags;
 
-    fore200e_irq_rx(fore200e);
-    
-    if (fore200e->host_txq.txing)
-	fore200e_irq_tx(fore200e);
+    DPRINTK(3, "tx tasklet scheduled for device %d\n", fore200e->atm_dev->number);
+
+    spin_lock_irqsave(&fore200e->q_lock, flags);
+    fore200e_tx_irq(fore200e);
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
 }
 
 
+static void
+fore200e_rx_tasklet(unsigned long data)
+{
+    struct fore200e* fore200e = (struct fore200e*) data;
+    unsigned long    flags;
+
+    DPRINTK(3, "rx tasklet scheduled for device %d\n", fore200e->atm_dev->number);
+
+    spin_lock_irqsave(&fore200e->q_lock, flags);
+    fore200e_rx_irq((struct fore200e*) data);
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+}
+#endif
+
 
 static int
 fore200e_select_scheme(struct atm_vcc* vcc)
 {
-    int scheme;
-
-#if 1
-    /* fairly balance VCs over (identical) buffer schemes */
-    scheme =  vcc->vci % 2 ? BUFFER_SCHEME_ONE : BUFFER_SCHEME_TWO;
-#else
-    /* bit 7 of VPI magically selects the second buffer scheme */
-    if (vcc->vpi & (1<<7)) {
-	vcc->vpi &= ((1<<7) - 1);    /* reset the magic bit */
-	scheme = BUFFER_SCHEME_TWO;
-    }
-    else {
-	scheme = BUFFER_SCHEME_ONE;
-    }
-#endif
+    /* fairly balance the VCs over (identical) buffer schemes */
+    int scheme = vcc->vci % 2 ? BUFFER_SCHEME_ONE : BUFFER_SCHEME_TWO;
     
-    DPRINTK(1, "vpvc %d.%d.%d uses the %s buffer scheme\n",
-	    vcc->itf, vcc->vpi, vcc->vci, scheme == BUFFER_SCHEME_ONE ? "first" : "second");
+    DPRINTK(1, "VC %d.%d.%d uses buffer scheme %d\n",
+	    vcc->itf, vcc->vpi, vcc->vci, scheme);
 
     return scheme;
 }
 
 
-
 static int 
 fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc* vcc, int mtu)
 {
@@ -1331,7 +1462,7 @@ fore200e_activate_vcin(struct fore200e* 
 #ifdef FORE200E_52BYTE_AAL0_SDU
 	mtu = 48;
 #endif
-	/* the MTU is unused by the cp, except in the case of AAL0 */
+	/* the MTU is not used by the cp, except in the case of AAL0 */
 	fore200e->bus->write(mtu,                        &entry->cp_entry->cmd.activate_block.mtu);
 	fore200e->bus->write(*(u32*)&vpvc,         (u32*)&entry->cp_entry->cmd.activate_block.vpvc);
 	fore200e->bus->write(*(u32*)&activ_opcode, (u32*)&entry->cp_entry->cmd.activate_block.opcode);
@@ -1346,13 +1477,13 @@ fore200e_activate_vcin(struct fore200e* 
     *entry->status = STATUS_FREE;
 
     if (ok == 0) {
-	printk(FORE200E "unable to %s vpvc %d.%d on device %s\n",
-	       activate ? "open" : "close", vcc->vpi, vcc->vci, fore200e->name);
+	printk(FORE200E "unable to %s VC %d.%d.%d\n",
+	       activate ? "open" : "close", vcc->itf, vcc->vpi, vcc->vci);
 	return -EIO;
     }
 
-    DPRINTK(1, "vpvc %d.%d %sed on device %s\n", vcc->vpi, vcc->vci, 
-	    activate ? "open" : "clos", fore200e->name);
+    DPRINTK(1, "VC %d.%d.%d %sed\n", vcc->itf, vcc->vpi, vcc->vci, 
+	    activate ? "open" : "clos");
 
     return 0;
 }
@@ -1410,7 +1541,7 @@ fore200e_rate_ctrl(struct atm_qos* qos, 
 {
     if (qos->txtp.max_pcr < ATM_OC3_PCR) {
     
-	/* compute the data cells to idle cells ratio from the PCR */
+	/* compute the data cells to idle cells ratio from the tx PCR */
 	rate->data_cells = qos->txtp.max_pcr * FORE200E_MAX_BACK2BACK_CELLS / ATM_OC3_PCR;
 	rate->idle_cells = FORE200E_MAX_BACK2BACK_CELLS - rate->data_cells;
     }
@@ -1424,21 +1555,38 @@ fore200e_rate_ctrl(struct atm_qos* qos, 
 static int
 fore200e_open(struct atm_vcc *vcc, short vpi, int vci)
 {
-    struct fore200e*     fore200e = FORE200E_DEV(vcc->dev);
-    struct fore200e_vcc* fore200e_vcc;
-    
-    /* find a free VPI/VCI */
+    struct fore200e*        fore200e = FORE200E_DEV(vcc->dev);
+    struct fore200e_vcc*    fore200e_vcc;
+    struct fore200e_vc_map* vc_map;
+    unsigned long           flags;
+
     fore200e_walk_vccs(vcc, &vpi, &vci);
+	
+    ASSERT((vpi >= 0) && (vpi < 1<<FORE200E_VPI_BITS));
+    ASSERT((vci >= 0) && (vci < 1<<FORE200E_VCI_BITS));
 
-    vcc->vpi = vpi;
-    vcc->vci = vci;
+    spin_lock_irqsave(&fore200e->q_lock, flags);
 
-    /* ressource checking only? */
-    if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
-	return 0;
+    vc_map = FORE200E_VC_MAP(fore200e, vpi, vci);
+    if (vc_map->vcc) {
 
-    set_bit(ATM_VF_ADDR, &vcc->flags);
-    vcc->itf    = vcc->dev->number;
+	spin_unlock_irqrestore(&fore200e->q_lock, flags);
+
+	printk(FORE200E "VC %d.%d.%d already in use\n",
+	       fore200e->atm_dev->number, vpi, vci);
+
+	return -EINVAL;
+    }
+
+    vc_map->vcc = vcc;
+
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+
+    fore200e_vcc = fore200e_kmalloc(sizeof(struct fore200e_vcc), GFP_ATOMIC);
+    if (fore200e_vcc == NULL) {
+	vc_map->vcc = NULL;
+	return -ENOMEM;
+    }
 
     DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
 	    "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d)\n",
@@ -1448,44 +1596,52 @@ fore200e_open(struct atm_vcc *vcc, short
 	    fore200e_traffic_class[ vcc->qos.rxtp.traffic_class ],
 	    vcc->qos.rxtp.min_pcr, vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_cdv, vcc->qos.rxtp.max_sdu);
     
+    /* pseudo-CBR bandwidth requested? */
     if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
 	
 	down(&fore200e->rate_sf);
 	if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {
 	    up(&fore200e->rate_sf);
+
+	    fore200e_kfree(fore200e_vcc);
+	    vc_map->vcc = NULL;
 	    return -EAGAIN;
 	}
-	/* reserving the pseudo-CBR bandwidth at this point grants us
-	   to reduce the length of the critical section protected
-	   by 'rate_sf'. in counterpart, we have to reset the available
-	   bandwidth if we later encounter an error */
 
+	/* reserve bandwidth */
 	fore200e->available_cell_rate -= vcc->qos.txtp.max_pcr;
 	up(&fore200e->rate_sf);
     }
-    
-    fore200e_vcc = fore200e_kmalloc(sizeof(struct fore200e_vcc), GFP_KERNEL);
-    if (fore200e_vcc == NULL) {
-	down(&fore200e->rate_sf);
-	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
-	up(&fore200e->rate_sf);
-	return -ENOMEM;
-    }
+
+    vcc->itf = vcc->dev->number;
+    vcc->vpi = vpi;
+    vcc->vci = vci;
+
+    set_bit(ATM_VF_PARTIAL,&vcc->flags);
+    set_bit(ATM_VF_ADDR, &vcc->flags);
 
     FORE200E_VCC(vcc) = fore200e_vcc;
-    
+
     if (fore200e_activate_vcin(fore200e, 1, vcc, vcc->qos.rxtp.max_sdu) < 0) {
-	kfree(fore200e_vcc);
-	down(&fore200e->rate_sf);
+
+	vc_map->vcc = NULL;
+
+	clear_bit(ATM_VF_ADDR, &vcc->flags);
+	clear_bit(ATM_VF_PARTIAL,&vcc->flags);
+
+	FORE200E_VCC(vcc) = NULL;
+
 	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
-	up(&fore200e->rate_sf);
-	return -EBUSY;
+
+	fore200e_kfree(fore200e_vcc);
+	return -EINVAL;
     }
     
     /* compute rate control parameters */
     if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
 	
 	fore200e_rate_ctrl(&vcc->qos, &fore200e_vcc->rate);
+	set_bit(ATM_VF_HASQOS, &vcc->flags);
 
 	DPRINTK(3, "tx on %d.%d.%d:%d, tx PCR = %d, rx PCR = %d, data_cells = %u, idle_cells = %u\n",
 		vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
@@ -1493,57 +1649,99 @@ fore200e_open(struct atm_vcc *vcc, short
 		fore200e_vcc->rate.data_cells, fore200e_vcc->rate.idle_cells);
     }
     
-    fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = 65536;
+    fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = MAX_PDU_SIZE + 1;
     fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0;
-    
+    fore200e_vcc->tx_pdu     = fore200e_vcc->rx_pdu     = 0;
+
+    /* new incarnation of the vcc */
+    vc_map->incarn = ++fore200e->incarn_count;
+
+    /* VC unusable before this flag is set */
     set_bit(ATM_VF_READY, &vcc->flags);
+
     return 0;
 }
 
 
-
 static void
 fore200e_close(struct atm_vcc* vcc)
 {
-    struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
-    
+    struct fore200e*        fore200e = FORE200E_DEV(vcc->dev);
+    struct fore200e_vcc*    fore200e_vcc;
+    struct fore200e_vc_map* vc_map;
+    unsigned long           flags;
+
+    ASSERT(vcc);
+    ASSERT((vcc->vpi >= 0) && (vcc->vpi < 1<<FORE200E_VPI_BITS));
+    ASSERT((vcc->vci >= 0) && (vcc->vci < 1<<FORE200E_VCI_BITS));
+
     DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));
-    
+
+    clear_bit(ATM_VF_READY, &vcc->flags);
+
     fore200e_activate_vcin(fore200e, 0, vcc, 0);
-    
-    kfree(FORE200E_VCC(vcc));
-	
+
+    spin_lock_irqsave(&fore200e->q_lock, flags);
+
+    vc_map = FORE200E_VC_MAP(fore200e, vcc->vpi, vcc->vci);
+
+    /* the vc is no longer considered as "in use" by fore200e_open() */
+    vc_map->vcc = NULL;
+
+    vcc->itf = vcc->vci = vcc->vpi = 0;
+
+    fore200e_vcc = FORE200E_VCC(vcc);
+    FORE200E_VCC(vcc) = NULL;
+
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+
+    /* release reserved bandwidth, if any */
     if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {
+
 	down(&fore200e->rate_sf);
 	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
 	up(&fore200e->rate_sf);
-    }
 
-    clear_bit(ATM_VF_READY, &vcc->flags);
-}
+	clear_bit(ATM_VF_HASQOS, &vcc->flags);
+    }
 
+    clear_bit(ATM_VF_ADDR, &vcc->flags);
+    clear_bit(ATM_VF_PARTIAL,&vcc->flags);
 
-#if 0
-#define FORE200E_SYNC_SEND    /* wait tx completion before returning */
-#endif
+    ASSERT(fore200e_vcc);
+    fore200e_kfree(fore200e_vcc);
+}
 
 
 static int
 fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
 {
-    struct fore200e*       fore200e     = FORE200E_DEV(vcc->dev);
-    struct fore200e_vcc*   fore200e_vcc = FORE200E_VCC(vcc);
-    struct host_txq*       txq          = &fore200e->host_txq;
-    struct host_txq_entry* entry;
-    struct tpd*            tpd;
-    struct tpd_haddr       tpd_haddr;
-    //unsigned long          flags;
-    int                    retry        = CONFIG_ATM_FORE200E_TX_RETRY;
-    int                    tx_copy      = 0;
-    int                    tx_len       = skb->len;
-    u32*                   cell_header  = NULL;
-    unsigned char*         skb_data;
-    int                    skb_len;
+    struct fore200e*        fore200e     = FORE200E_DEV(vcc->dev);
+    struct fore200e_vcc*    fore200e_vcc = FORE200E_VCC(vcc);
+    struct fore200e_vc_map* vc_map;
+    struct host_txq*        txq          = &fore200e->host_txq;
+    struct host_txq_entry*  entry;
+    struct tpd*             tpd;
+    struct tpd_haddr        tpd_haddr;
+    int                     retry        = CONFIG_ATM_FORE200E_TX_RETRY;
+    int                     tx_copy      = 0;
+    int                     tx_len       = skb->len;
+    u32*                    cell_header  = NULL;
+    unsigned char*          skb_data;
+    int                     skb_len;
+    unsigned char*          data;
+    unsigned long           flags;
+
+    ASSERT(vcc);
+    ASSERT(atomic_read(&vcc->sk->wmem_alloc) >= 0);
+    ASSERT(fore200e);
+    ASSERT(fore200e_vcc);
+
+    if (!test_bit(ATM_VF_READY, &vcc->flags)) {
+	DPRINTK(1, "VC %d.%d.%d not ready for tx\n", vcc->itf, vcc->vpi, vcc->vpi);
+	dev_kfree_skb_any(skb);
+	return -EINVAL;
+    }
 
 #ifdef FORE200E_52BYTE_AAL0_SDU
     if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.txtp.max_sdu == ATM_AAL0_SDU)) {
@@ -1551,7 +1749,7 @@ fore200e_send(struct atm_vcc *vcc, struc
 	skb_data    = skb->data + 4;    /* skip 4-byte cell header */
 	skb_len     = tx_len = skb->len  - 4;
 
-	DPRINTK(3, "skipping user-supplied cell header 0x%08x", *cell_header);
+	DPRINTK(3, "user-supplied cell header = 0x%08x\n", *cell_header);
     }
     else 
 #endif
@@ -1560,39 +1758,6 @@ fore200e_send(struct atm_vcc *vcc, struc
 	skb_len  = skb->len;
     }
     
-  retry_here:
-    
-    tasklet_disable(&fore200e->tasklet);
-
-    entry = &txq->host_entry[ txq->head ];
-    
-    if (*entry->status != STATUS_FREE) {
-	
-	/* try to free completed tx queue entries */
-	fore200e_irq_tx(fore200e);
-	
-	if (*entry->status != STATUS_FREE) {
-	    
-	    tasklet_enable(&fore200e->tasklet);
-
-	    /* retry once again? */
-	    if(--retry > 0)
-		goto retry_here;
-	    
-	    atomic_inc(&vcc->stats->tx_err);
-	    
-	    printk(FORE200E "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",
-		   fore200e->name, fore200e->cp_queues->heartbeat);
-	    if (vcc->pop)
-		vcc->pop(vcc, skb);
-	    else
-		dev_kfree_skb(skb);
-	    return -EIO;
-	}
-    }
-
-    tpd = entry->tpd;
-
     if (((unsigned long)skb_data) & 0x3) {
 
 	DPRINTK(2, "misaligned tx PDU on device %s\n", fore200e->name);
@@ -1602,43 +1767,87 @@ fore200e_send(struct atm_vcc *vcc, struc
 
     if ((vcc->qos.aal == ATM_AAL0) && (skb_len % ATM_CELL_PAYLOAD)) {
 
-	/* this simply NUKES the PCA-200E board */
+	/* this simply NUKES the PCA board */
 	DPRINTK(2, "incomplete tx AAL0 PDU on device %s\n", fore200e->name);
 	tx_copy = 1;
 	tx_len  = ((skb_len / ATM_CELL_PAYLOAD) + 1) * ATM_CELL_PAYLOAD;
     }
     
     if (tx_copy) {
-	
-	entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
-	if (entry->data == NULL) {
-	    
-	    tasklet_enable(&fore200e->tasklet);
-	    if (vcc->pop)
+	data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
+	if (data == NULL) {
+	    if (vcc->pop) {
 		vcc->pop(vcc, skb);
-	    else
-		dev_kfree_skb(skb);
+	    }
+	    else {
+		dev_kfree_skb_any(skb);
+	    }
 	    return -ENOMEM;
 	}
 
-	memcpy(entry->data, skb_data, skb_len);
+	memcpy(data, skb_data, skb_len);
 	if (skb_len < tx_len)
-	    memset(entry->data + skb_len, 0x00, tx_len - skb_len);
-	
-	tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len, FORE200E_DMA_TODEVICE);
+	    memset(data + skb_len, 0x00, tx_len - skb_len);
     }
     else {
-	entry->data = NULL;
-	tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len, FORE200E_DMA_TODEVICE);
+	data = skb_data;
     }
 
+    vc_map = FORE200E_VC_MAP(fore200e, vcc->vpi, vcc->vci);
+    ASSERT(vc_map->vcc == vcc);
+
+  retry_here:
+    
+    spin_lock_irqsave(&fore200e->q_lock, flags);
+
+    entry = &txq->host_entry[ txq->head ];
+    
+    if ((*entry->status != STATUS_FREE) || (txq->txing >= QUEUE_SIZE_TX - 2)) {
+	
+	/* try to free completed tx queue entries */
+	fore200e_tx_irq(fore200e);
+	
+	if (*entry->status != STATUS_FREE) {
+	    
+	    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+
+	    /* retry once again? */
+	    if(--retry > 0) {
+		schedule();
+		goto retry_here;
+	    }
+	    
+	    atomic_inc(&vcc->stats->tx_err);
+	    
+	    fore200e->tx_sat++;
+	    DPRINTK(2, "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",
+		   fore200e->name, fore200e->cp_queues->heartbeat);
+	    if (vcc->pop) {
+		vcc->pop(vcc, skb);
+	    }
+	    else {
+		dev_kfree_skb_any(skb);
+	    }
+
+	    if (tx_copy)
+		kfree(data);
+
+	    return -ENOBUFS;
+	}
+    }
+
+    entry->incarn = vc_map->incarn;
+    entry->vc_map = vc_map;
+    entry->skb    = skb;
+    entry->data   = tx_copy ? data : NULL;
+
+    tpd = entry->tpd;
+    tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, data, tx_len, FORE200E_DMA_TODEVICE);
     tpd->tsd[ 0 ].length = tx_len;
 
     FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
     txq->txing++;
 
-    tasklet_enable(&fore200e->tasklet);
-
     /* ensure DMA synchronisation */
     fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
     
@@ -1650,9 +1859,7 @@ fore200e_send(struct atm_vcc *vcc, struc
 	fore200e_vcc->tx_min_pdu = skb_len;
     if (skb_len > fore200e_vcc->tx_max_pdu)
 	fore200e_vcc->tx_max_pdu = skb_len;
-    
-    entry->vcc = vcc;
-    entry->skb = skb;
+    fore200e_vcc->tx_pdu++;
 
     /* set tx rate control information */
     tpd->rate.data_cells = fore200e_vcc->rate.data_cells;
@@ -1677,49 +1884,16 @@ fore200e_send(struct atm_vcc *vcc, struc
     tpd->spec.length = tx_len;
     tpd->spec.nseg   = 1;
     tpd->spec.aal    = fore200e_atm2fore_aal(vcc->qos.aal);
-#ifdef FORE200E_SYNC_SEND
-    tpd->spec.intr   = 0;
-#else
     tpd->spec.intr   = 1;
-#endif
 
-    tpd_haddr.size  = sizeof(struct tpd) / 32;    /* size is expressed in 32 byte blocks */
+    tpd_haddr.size  = sizeof(struct tpd) / (1<<TPD_HADDR_SHIFT);  /* size is expressed in 32 byte blocks */
     tpd_haddr.pad   = 0;
-    tpd_haddr.haddr = entry->tpd_dma >> 5;        /* shift the address, as we are in a bitfield */
+    tpd_haddr.haddr = entry->tpd_dma >> TPD_HADDR_SHIFT;          /* shift the address, as we are in a bitfield */
 
     *entry->status = STATUS_PENDING;
     fore200e->bus->write(*(u32*)&tpd_haddr, (u32*)&entry->cp_entry->tpd_haddr);
 
-
-#ifdef FORE200E_SYNC_SEND
-    {
-	int ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 10);
-
-	fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
-				 FORE200E_DMA_TODEVICE);
-	
-	/* free tmp copy of misaligned data */
-	if (entry->data)
-	    kfree(entry->data);
-
-	/* notify tx completion */
-	if (vcc->pop)
-	    vcc->pop(vcc, skb);
-	else
-	    dev_kfree_skb(skb);
-
-	if (ok == 0) {
-	    printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);
-
-	    atomic_inc(&entry->vcc->stats->tx_err);
-	    return -EIO;
-	}
-	atomic_inc(&entry->vcc->stats->tx);
-
-	DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci);
-
-    }
-#endif
+    spin_unlock_irqrestore(&fore200e->q_lock, flags);
 
     return 0;
 }
@@ -1740,7 +1914,8 @@ fore200e_getstats(struct fore200e* fore2
 	    return -ENOMEM;
     }
     
-    stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats), FORE200E_DMA_FROMDEVICE);
+    stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats,
+					    sizeof(struct stats), FORE200E_DMA_FROMDEVICE);
     
     FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 
@@ -1769,9 +1944,9 @@ fore200e_getstats(struct fore200e* fore2
 
 
 static int
-fore200e_getsockopt (struct atm_vcc* vcc, int level, int optname, void* optval, int optlen)
+fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, void* optval, int optlen)
 {
-    // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
+    /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */
 
     DPRINTK(2, "getsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",
 	    vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);
@@ -1783,7 +1958,7 @@ fore200e_getsockopt (struct atm_vcc* vcc
 static int
 fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void* optval, int optlen)
 {
-    // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);
+    /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */
     
     DPRINTK(2, "setsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",
 	    vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);
@@ -1841,6 +2016,8 @@ fore200e_set_oc3(struct fore200e* fore20
     struct oc3_opcode       opcode;
     int                     ok;
 
+    DPRINTK(2, "set OC-3 reg = 0x%02x, value = 0x%02x, mask = 0x%02x\n", reg, value, mask);
+
     FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 
     opcode.opcode = OPCODE_SET_OC3;
@@ -1896,7 +2073,7 @@ fore200e_setloop(struct fore200e* fore20
     }
 
     error = fore200e_set_oc3(fore200e, SUNI_MCT, mct_value, mct_mask);
-    if ( error == 0)
+    if (error == 0)
 	fore200e->loop_mode = loop_mode;
 
     return error;
@@ -1978,6 +2155,11 @@ fore200e_change_qos(struct atm_vcc* vcc,
     struct fore200e_vcc* fore200e_vcc = FORE200E_VCC(vcc);
     struct fore200e*     fore200e     = FORE200E_DEV(vcc->dev);
 
+    if (!test_bit(ATM_VF_READY, &vcc->flags)) {
+	DPRINTK(1, "VC %d.%d.%d not ready for QoS change\n", vcc->itf, vcc->vpi, vcc->vpi);
+	return -EINVAL;
+    }
+
     DPRINTK(2, "change_qos %d.%d.%d, "
 	    "(tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
 	    "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d), flags = 0x%x\n"
@@ -1999,6 +2181,7 @@ fore200e_change_qos(struct atm_vcc* vcc,
 
 	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
 	fore200e->available_cell_rate -= qos->txtp.max_pcr;
+
 	up(&fore200e->rate_sf);
 	
 	memcpy(&vcc->qos, qos, sizeof(struct atm_qos));
@@ -2007,6 +2190,7 @@ fore200e_change_qos(struct atm_vcc* vcc,
 	fore200e_rate_ctrl(qos, &fore200e_vcc->rate);
 
 	set_bit(ATM_VF_HASQOS, &vcc->flags);
+
 	return 0;
     }
     
@@ -2027,7 +2211,10 @@ fore200e_irq_request(struct fore200e* fo
     printk(FORE200E "IRQ %s reserved for device %s\n",
 	   fore200e_irq_itoa(fore200e->irq), fore200e->name);
 
-    tasklet_init(&fore200e->tasklet, fore200e_tasklet, (unsigned long)fore200e);
+#ifdef FORE200E_USE_TASKLET
+    tasklet_init(&fore200e->tx_tasklet, fore200e_tx_tasklet, (unsigned long)fore200e);
+    tasklet_init(&fore200e->rx_tasklet, fore200e_rx_tasklet, (unsigned long)fore200e);
+#endif
 
     fore200e->state = FORE200E_STATE_IRQ;
     return 0;
@@ -2042,6 +2229,7 @@ fore200e_get_esi(struct fore200e* fore20
 
     if (!prom)
 	return -ENOMEM;
+
     ok = fore200e->bus->prom_read(fore200e, prom);
     if (ok < 0) {
 	fore200e_kfree(prom);
@@ -2089,10 +2277,16 @@ fore200e_alloc_rx_buf(struct fore200e* f
 	    if (buffer == NULL)
 		return -ENOMEM;
 
+	    bsq->freebuf = NULL;
+
 	    for (i = 0; i < nbr; i++) {
 
 		buffer[ i ].scheme = scheme;
 		buffer[ i ].magn   = magn;
+#ifdef FORE200E_BSQ_DEBUG
+		buffer[ i ].index  = i;
+		buffer[ i ].supplied = 0;
+#endif
 
 		/* allocate the receive buffer body */
 		if (fore200e_chunk_alloc(fore200e,
@@ -2105,9 +2299,17 @@ fore200e_alloc_rx_buf(struct fore200e* f
 		    
 		    return -ENOMEM;
 		}
+
+		/* insert the buffer into the free buffer list */
+		buffer[ i ].next = bsq->freebuf;
+		bsq->freebuf = &buffer[ i ];
 	    }
-	    /* set next free buffer index */
-	    bsq->free = 0;
+	    /* all the buffers are free, initially */
+	    bsq->freebuf_count = nbr;
+
+#ifdef FORE200E_BSQ_DEBUG
+	    bsq_audit(3, bsq, scheme, magn);
+#endif
 	}
     }
 
@@ -2164,9 +2366,9 @@ fore200e_init_bs_queue(struct fore200e* 
 		                     FORE200E_INDEX(bsq->rbd_block.align_addr, struct rbd_block, i);
 		bsq->host_entry[ i ].rbd_block_dma =
 		                     FORE200E_DMA_INDEX(bsq->rbd_block.dma_addr, struct rbd_block, i);
-		bsq->host_entry[ i ].cp_entry      = &cp_entry[ i ];
+		bsq->host_entry[ i ].cp_entry = &cp_entry[ i ];
 		
-		*bsq->host_entry[ i ].status   = STATUS_FREE;
+		*bsq->host_entry[ i ].status = STATUS_FREE;
 		
 		fore200e->bus->write(FORE200E_DMA_INDEX(bsq->status.dma_addr, enum status, i), 
 				     &cp_entry[ i ].status_haddr);
@@ -2293,10 +2495,11 @@ fore200e_init_tx_queue(struct fore200e* 
 	   we do not write here the DMA (physical) base address of each tpd into
 	   the related cp resident entry, because the cp relies on this write
 	   operation to detect that a new pdu has been submitted for tx */
-}
+    }
 
-    /* set the head entry of the queue */
+    /* set the head and tail entries of the queue */
     txq->head = 0;
+    txq->tail = 0;
 
     fore200e->state = FORE200E_STATE_INIT_TXQ;
     return 0;
@@ -2315,9 +2518,9 @@ fore200e_init_cmd_queue(struct fore200e*
     /* allocate and align the array of status words */
     if (fore200e->bus->dma_chunk_alloc(fore200e,
 				       &cmdq->status,
-				 sizeof(enum status), 
-				 QUEUE_SIZE_CMD,
-				 fore200e->bus->status_alignment) < 0) {
+				       sizeof(enum status), 
+				       QUEUE_SIZE_CMD,
+				       fore200e->bus->status_alignment) < 0) {
 	return -ENOMEM;
     }
     
@@ -2353,12 +2556,6 @@ fore200e_param_bs_queue(struct fore200e*
 {
     struct bs_spec* bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ];
 
-    /* dumb value; the firmware doesn't allow us to activate a VC while
-       selecting a buffer scheme with zero-sized rbd pools */
-
-    if (pool_size == 0)
-	pool_size = 64;
-
     fore200e->bus->write(queue_length,                           &bs_spec->queue_length);
     fore200e->bus->write(fore200e_rx_buf_size[ scheme ][ magn ], &bs_spec->buffer_size);
     fore200e->bus->write(pool_size,                              &bs_spec->pool_size);
@@ -2375,7 +2572,8 @@ fore200e_initialize(struct fore200e* for
     DPRINTK(2, "device %s being initialized\n", fore200e->name);
 
     init_MUTEX(&fore200e->rate_sf);
-    
+    spin_lock_init(&fore200e->q_lock);
+
     cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
 
     /* enable cp to host interrupts */
@@ -2457,7 +2655,7 @@ fore200e_monitor_getc(struct fore200e* f
 static void __init
 fore200e_monitor_puts(struct fore200e* fore200e, char* str)
 {
-    while(*str) {
+    while (*str) {
 
 	/* the i960 monitor doesn't accept any new character if it has something to say */
 	while (fore200e_monitor_getc(fore200e) >= 0);
@@ -2478,6 +2676,11 @@ fore200e_start_fw(struct fore200e* fore2
 
     DPRINTK(2, "device %s firmware being started\n", fore200e->name);
 
+#if defined(__sparc_v9__)
+    /* reported to be required by SBA cards on some sparc64 hosts */
+    fore200e_spin(100);
+#endif
+
     sprintf(cmd, "\rgo %x\r", le32_to_cpu(fw_header->start_offset));
 
     fore200e_monitor_puts(fore200e, cmd);
@@ -2508,12 +2711,10 @@ fore200e_load_fw(struct fore200e* fore20
     DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n", 
 	    fore200e->name, load_addr, fw_size);
 
-#if 1
     if (le32_to_cpu(fw_header->magic) != FW_HEADER_MAGIC) {
 	printk(FORE200E "corrupted %s firmware image\n", fore200e->bus->model_name);
 	return -ENODEV;
     }
-#endif
 
     for (; fw_size--; fw_data++, load_addr++)
 	fore200e->bus->write(le32_to_cpu(*fw_data), load_addr);
@@ -2540,8 +2741,8 @@ fore200e_register(struct fore200e* fore2
     FORE200E_DEV(atm_dev) = fore200e;
     fore200e->atm_dev = atm_dev;
 
-    atm_dev->ci_range.vpi_bits = 8;
-    atm_dev->ci_range.vci_bits = 10;
+    atm_dev->ci_range.vpi_bits = FORE200E_VPI_BITS;
+    atm_dev->ci_range.vci_bits = FORE200E_VCI_BITS;
 
     fore200e->available_cell_rate = ATM_OC3_PCR;
 
@@ -2610,7 +2811,7 @@ fore200e_detect(void)
     struct       fore200e*     fore200e;
     int                        index, link;
 
-    printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n");
+    printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
 
     /* for each configured bus interface */
     for (link = 0, bus = fore200e_bus; bus->model_name; bus++) {
@@ -2657,11 +2858,13 @@ fore200e_cleanup(struct fore200e** head)
 
 
 static int
-fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
+fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
 {
-    struct sock *s;
-    struct fore200e* fore200e  = FORE200E_DEV(dev);
-    int              len, left = *pos;
+    struct fore200e*     fore200e  = FORE200E_DEV(dev);
+    struct fore200e_vcc* fore200e_vcc;
+    struct atm_vcc*      vcc;
+    int                  i, len, left = *pos;
+    unsigned long        flags;
 
     if (!left--) {
 
@@ -2694,14 +2897,15 @@ fore200e_proc_read(struct atm_dev *dev,l
 
     if (!left--)
 	return sprintf(page,
-		       "   supplied small bufs (1):\t%d\n"
-		       "   supplied large bufs (1):\t%d\n"
-		       "   supplied small bufs (2):\t%d\n"
-		       "   supplied large bufs (2):\t%d\n",
-		       fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_SMALL ].count,
-		       fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_LARGE ].count,
-		       fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_SMALL ].count,
-		       fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_LARGE ].count);
+		       "   free small bufs, scheme 1:\t%d\n"
+		       "   free large bufs, scheme 1:\t%d\n"
+		       "   free small bufs, scheme 2:\t%d\n"
+		       "   free large bufs, scheme 2:\t%d\n",
+		       fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_SMALL ].freebuf_count,
+		       fore200e->host_bsq[ BUFFER_SCHEME_ONE ][ BUFFER_MAGN_LARGE ].freebuf_count,
+		       fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_SMALL ].freebuf_count,
+		       fore200e->host_bsq[ BUFFER_SCHEME_TWO ][ BUFFER_MAGN_LARGE ].freebuf_count);
+
     if (!left--) {
 	u32 hb = fore200e->bus->read(&fore200e->cp_queues->heartbeat);
 
@@ -2740,7 +2944,7 @@ fore200e_proc_read(struct atm_dev *dev,l
 	u32 media_index    = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type));
 	u32 oc3_index;
 
-	if (media_index < 0 || media_index > 4)
+	if ((media_index < 0) || (media_index > 4))
 	    media_index = 5;
 	
 	switch (fore200e->loop_mode) {
@@ -2887,49 +3091,60 @@ fore200e_proc_read(struct atm_dev *dev,l
 		       "     large b1:\t\t\t%10u\n"
 		       "     small b2:\t\t\t%10u\n"
 		       "     large b2:\t\t\t%10u\n"
-		       "     RX PDUs:\t\t\t%10u\n",
+		       "     RX PDUs:\t\t\t%10u\n"
+		       "     TX PDUs:\t\t\t%10lu\n",
 		       fore200e_swap(fore200e->stats->aux.small_b1_failed),
 		       fore200e_swap(fore200e->stats->aux.large_b1_failed),
 		       fore200e_swap(fore200e->stats->aux.small_b2_failed),
 		       fore200e_swap(fore200e->stats->aux.large_b2_failed),
-		       fore200e_swap(fore200e->stats->aux.rpd_alloc_failed));
-    
+		       fore200e_swap(fore200e->stats->aux.rpd_alloc_failed),
+                       fore200e->tx_sat);
+
     if (!left--)
 	return sprintf(page,"\n"
 		       " receive carrier:\t\t\t%s\n",
 		       fore200e->stats->aux.receive_carrier ? "ON" : "OFF!");
     
     if (!left--) {
-	struct atm_vcc *vcc;
-	struct fore200e_vcc* fore200e_vcc;
-	
-	len = sprintf(page,"\n"    
-		      " VCCs:\n  address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n");
-	
-	read_lock(&vcc_sklist_lock);
-	for (s = vcc_sklist; s; s = s->next) {
-	    vcc = s->protinfo.af_atm;
+	return sprintf(page,"\n"    
+		       " VCCs:\n  address   VPI VCI   AAL "
+		       "TX PDUs   TX min/max size  RX PDUs   RX min/max size\n");
+    }
 
-	    if (vcc->dev != fore200e->atm_dev)
-		    continue;
+
+    for (i = 0; i < NBR_CONNECT; i++) {
+
+	vcc = fore200e->vc_map[i].vcc;
+
+	if (vcc == NULL) 
+	    continue;
+
+	spin_lock_irqsave(&fore200e->q_lock, flags);
+
+	if (vcc && test_bit(ATM_VF_READY, &vcc->flags) && !left--) {
 
 	    fore200e_vcc = FORE200E_VCC(vcc);
-	    
-	    len += sprintf(page + len,
-			   "  %x\t%d.%d:%d\t\t(%d/%d)\t(%d/%d)\n",
+	    ASSERT(fore200e_vcc);
+	
+	    len = sprintf(page,
+			   "  %08x  %03d %05d %1d   %09lu %05d/%05d      %09lu %05d/%05d\n",
 			   (u32)(unsigned long)vcc,
 			   vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
+			   fore200e_vcc->tx_pdu,
 			   fore200e_vcc->tx_min_pdu > 0xFFFF ? 0 : fore200e_vcc->tx_min_pdu,
 			   fore200e_vcc->tx_max_pdu,
+			   fore200e_vcc->rx_pdu,
 			   fore200e_vcc->rx_min_pdu > 0xFFFF ? 0 : fore200e_vcc->rx_min_pdu,
 			   fore200e_vcc->rx_max_pdu
 		);
+
+	    spin_unlock_irqrestore(&fore200e->q_lock, flags);
+	    return len;
 	}
-	read_unlock(&vcc_sklist_lock);
 
-	return len;
+	spin_unlock_irqrestore(&fore200e->q_lock, flags);
     }
-    
+
     return 0;
 }
 
@@ -2966,7 +3181,7 @@ static const struct atmdev_ops fore200e_
 	send:         fore200e_send,
 	change_qos:   fore200e_change_qos,
 	proc_read:    fore200e_proc_read,
-	owner:        THIS_MODULE,
+	owner:        THIS_MODULE
 };
 
 
@@ -3027,4 +3242,6 @@ static const struct fore200e_bus fore200
     {}
 };
 
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
+#endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/atm/fore200e.h linux-2.4.27-rc4/drivers/atm/fore200e.h
--- linux-2.4.26/drivers/atm/fore200e.h	2000-12-11 21:22:12.000000000 +0000
+++ linux-2.4.27-rc4/drivers/atm/fore200e.h	2004-07-30 16:24:26.000000000 +0000
@@ -23,19 +23,21 @@
 #define BUFFER_S2_SIZE       SMALL_BUFFER_SIZE    /* size of small buffers, scheme 2 */
 #define BUFFER_L2_SIZE       LARGE_BUFFER_SIZE    /* size of large buffers, scheme 2 */
 
-#define BUFFER_S1_NBR        (RBD_BLK_SIZE * 2)
-#define BUFFER_L1_NBR        (RBD_BLK_SIZE * 2)
+#define BUFFER_S1_NBR        (RBD_BLK_SIZE * 6)
+#define BUFFER_L1_NBR        (RBD_BLK_SIZE * 4)
 
-#define BUFFER_S2_NBR        (RBD_BLK_SIZE * 2)
-#define BUFFER_L2_NBR        (RBD_BLK_SIZE * 2)
+#define BUFFER_S2_NBR        (RBD_BLK_SIZE * 6)
+#define BUFFER_L2_NBR        (RBD_BLK_SIZE * 4)
 
 
 #define QUEUE_SIZE_CMD       16	     /* command queue capacity       */
 #define QUEUE_SIZE_RX	     64	     /* receive queue capacity       */
 #define QUEUE_SIZE_TX	     256     /* transmit queue capacity      */
-#define QUEUE_SIZE_BS        16	     /* buffer supply queue capacity */
+#define QUEUE_SIZE_BS        32	     /* buffer supply queue capacity */
 
-#define NBR_CONNECT          1024    /* number of ATM connections     */
+#define FORE200E_VPI_BITS     0
+#define FORE200E_VCI_BITS    10
+#define NBR_CONNECT          (1 << (FORE200E_VPI_BITS + FORE200E_VCI_BITS)) /* number of connections */
 
 
 #define TSD_FIXED            2
@@ -207,6 +209,7 @@ typedef struct tpd_haddr {
     )
 } tpd_haddr_t;
 
+#define TPD_HADDR_SHIFT 5  /* addr aligned on 32 byte boundary */
 
 /* cp resident transmit queue entry */
 
@@ -517,13 +520,15 @@ typedef struct cp_cmdq_entry {
 /* host resident transmit queue entry */
 
 typedef struct host_txq_entry {
-    struct cp_txq_entry*   cp_entry;    /* addr of cp resident tx queue entry */
-    enum   status*         status;      /* addr of host resident status       */
-    struct tpd*            tpd;         /* addr of transmit PDU descriptor    */
-    u32                    tpd_dma;     /* DMA address of tpd                 */
-    struct sk_buff*        skb;         /* related skb                        */
-    struct atm_vcc*        vcc;         /* related vcc                        */
-    void*                  data;        /* copy of misaligned data            */
+    struct cp_txq_entry*    cp_entry;    /* addr of cp resident tx queue entry       */
+    enum   status*          status;      /* addr of host resident status             */
+    struct tpd*             tpd;         /* addr of transmit PDU descriptor          */
+    u32                     tpd_dma;     /* DMA address of tpd                       */
+    struct sk_buff*         skb;         /* related skb                              */
+    void*                   data;        /* copy of misaligned data                  */
+    unsigned long           incarn;      /* vc_map incarnation when submitted for tx */
+    struct fore200e_vc_map* vc_map;
+
 } host_txq_entry_t;
 
 
@@ -576,6 +581,10 @@ typedef struct buffer {
     enum   buffer_scheme scheme;      /* buffer scheme           */
     enum   buffer_magn   magn;        /* buffer magnitude        */
     struct chunk         data;        /* data buffer             */
+#ifdef FORE200E_BSQ_DEBUG
+    unsigned long        index;       /* buffer # in queue       */
+    int                  supplied;    /* 'buffer supplied' flag  */
+#endif
 } buffer_t;
 
 
@@ -602,6 +611,7 @@ typedef struct host_cmdq {
 typedef struct host_txq {
     struct host_txq_entry host_entry[ QUEUE_SIZE_TX ];    /* host resident tx queue entries         */
     int                   head;                           /* head of tx queue                       */
+    int                   tail;                           /* tail of tx queue                       */
     struct chunk          tpd;                            /* array of tpds                          */
     struct chunk          status;                         /* arry of completion status              */
     int                   txing;                          /* number of pending PDUs in tx queue     */
@@ -626,8 +636,8 @@ typedef struct host_bsq {
     struct chunk          rbd_block;                      /* array of rbds                             */
     struct chunk          status;                         /* array of completion status                */
     struct buffer*        buffer;                         /* array of rx buffers                       */
-    int                   free;                           /* index of first free rx buffer             */
-    volatile int          count;                          /* count of supplied rx buffers              */
+    struct buffer*        freebuf;                        /* list of free rx buffers                   */
+    volatile int          freebuf_count;                  /* count of free rx buffers                  */
 } host_bsq_t;
 
 
@@ -846,6 +856,17 @@ typedef struct fore200e_bus {
 #endif
 
 
+/* vc mapping */
+
+typedef struct fore200e_vc_map {
+    struct atm_vcc* vcc;       /* vcc entry              */
+    unsigned long   incarn;    /* vcc incarnation number */
+} fore200e_vc_map_t;
+
+#define FORE200E_VC_MAP(fore200e, vpi, vci)  \
+        (& (fore200e)->vc_map[ ((vpi) << FORE200E_VCI_BITS) | (vci) ])
+
+
 /* per-device data */
 
 typedef struct fore200e {
@@ -879,20 +900,29 @@ typedef struct fore200e {
     struct stats*              stats;                  /* last snapshot of the stats         */
     
     struct semaphore           rate_sf;                /* protects rate reservation ops      */
-    struct tasklet_struct      tasklet;                /* performs interrupt work            */
+    spinlock_t                 q_lock;                 /* protects queue ops                 */
+#ifdef FORE200E_USE_TASKLET
+    struct tasklet_struct      tx_tasklet;             /* performs tx interrupt work         */
+    struct tasklet_struct      rx_tasklet;             /* performs rx interrupt work         */
+#endif
+    unsigned long              tx_sat;                 /* tx queue saturation count          */
 
+    unsigned long              incarn_count;
+    struct fore200e_vc_map     vc_map[ NBR_CONNECT ];  /* vc mapping                         */
 } fore200e_t;
 
 
 /* per-vcc data */
 
 typedef struct fore200e_vcc {
-    enum buffer_scheme scheme;        /* rx buffer scheme                   */
-    struct tpd_rate    rate;          /* tx rate control data               */
-    int                rx_min_pdu;    /* size of smallest PDU received      */
-    int                rx_max_pdu;    /* size of largest PDU received       */
-    int                tx_min_pdu;    /* size of smallest PDU transmitted   */
-    int                tx_max_pdu;    /* size of largest PDU transmitted    */
+    enum buffer_scheme     scheme;             /* rx buffer scheme                   */
+    struct tpd_rate        rate;               /* tx rate control data               */
+    int                    rx_min_pdu;         /* size of smallest PDU received      */
+    int                    rx_max_pdu;         /* size of largest PDU received       */
+    int                    tx_min_pdu;         /* size of smallest PDU transmitted   */
+    int                    tx_max_pdu;         /* size of largest PDU transmitted    */
+    unsigned long          tx_pdu;             /* nbr of tx pdus                     */
+    unsigned long          rx_pdu;             /* nbr of rx pdus                     */
 } fore200e_vcc_t;
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/atm/nicstar.c linux-2.4.27-rc4/drivers/atm/nicstar.c
--- linux-2.4.26/drivers/atm/nicstar.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/atm/nicstar.c	2004-07-30 16:26:32.000000000 +0000
@@ -760,7 +760,7 @@ static int __devinit ns_init_card(int i,
    for (j = 0; j < NUM_HB; j++)
    {
       struct sk_buff *hb;
-      hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
+      hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
       if (hb == NULL)
       {
          printk("nicstar%d: can't allocate %dth of %d huge buffers.\n",
@@ -780,7 +780,7 @@ static int __devinit ns_init_card(int i,
    for (j = 0; j < NUM_LB; j++)
    {
       struct sk_buff *lb;
-      lb = alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
+      lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
       if (lb == NULL)
       {
          printk("nicstar%d: can't allocate %dth of %d large buffers.\n",
@@ -816,7 +816,7 @@ static int __devinit ns_init_card(int i,
    for (j = 0; j < NUM_SB; j++)
    {
       struct sk_buff *sb;
-      sb = alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
+      sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
       if (sb == NULL)
       {
          printk("nicstar%d: can't allocate %dth of %d small buffers.\n",
@@ -1318,7 +1318,7 @@ static void ns_irq_handler(int irq, void
              card->index);
       for (i = 0; i < card->sbnr.min; i++)
       {
-         sb = alloc_skb(NS_SMSKBSIZE, GFP_ATOMIC);
+         sb = dev_alloc_skb(NS_SMSKBSIZE);
          if (sb == NULL)
          {
             writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG);
@@ -1344,7 +1344,7 @@ static void ns_irq_handler(int irq, void
              card->index);
       for (i = 0; i < card->lbnr.min; i++)
       {
-         lb = alloc_skb(NS_LGSKBSIZE, GFP_ATOMIC);
+         lb = dev_alloc_skb(NS_LGSKBSIZE);
          if (lb == NULL)
          {
             writel(readl(card->membase + CFG) & ~NS_CFG_EFBIE, card->membase + CFG);
@@ -2167,7 +2167,7 @@ static void dequeue_rx(ns_dev *card, ns_
       cell = skb->data;
       for (i = ns_rsqe_cellcount(rsqe); i; i--)
       {
-         if ((sb = alloc_skb(NS_SMSKBSIZE, GFP_ATOMIC)) == NULL)
+         if ((sb = dev_alloc_skb(NS_SMSKBSIZE)) == NULL)
          {
             printk("nicstar%d: Can't allocate buffers for aal0.\n",
                    card->index);
@@ -2399,7 +2399,7 @@ static void dequeue_rx(ns_dev *card, ns_
          if (hb == NULL)		/* No buffers in the queue */
          {
 
-            hb = alloc_skb(NS_HBUFSIZE, GFP_ATOMIC);
+            hb = dev_alloc_skb(NS_HBUFSIZE);
             if (hb == NULL)
             {
                printk("nicstar%d: Out of huge buffers.\n", card->index);
@@ -2413,7 +2413,7 @@ static void dequeue_rx(ns_dev *card, ns_
             else if (card->hbpool.count < card->hbnr.min)
 	    {
                struct sk_buff *new_hb;
-               if ((new_hb = alloc_skb(NS_HBUFSIZE, GFP_ATOMIC)) != NULL)
+               if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
                {
                   skb_queue_tail(&card->hbpool.queue, new_hb);
                   card->hbpool.count++;
@@ -2424,14 +2424,14 @@ static void dequeue_rx(ns_dev *card, ns_
          if (--card->hbpool.count < card->hbnr.min)
          {
             struct sk_buff *new_hb;
-            if ((new_hb = alloc_skb(NS_HBUFSIZE, GFP_ATOMIC)) != NULL)
+            if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
             {
                skb_queue_tail(&card->hbpool.queue, new_hb);
                card->hbpool.count++;
             }
             if (card->hbpool.count < card->hbnr.min)
 	    {
-               if ((new_hb = alloc_skb(NS_HBUFSIZE, GFP_ATOMIC)) != NULL)
+               if ((new_hb = dev_alloc_skb(NS_HBUFSIZE)) != NULL)
                {
                   skb_queue_tail(&card->hbpool.queue, new_hb);
                   card->hbpool.count++;
@@ -2513,7 +2513,7 @@ static void ns_sb_destructor(struct sk_b
 
    do
    {
-      sb = alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
+      sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
       if (sb == NULL)
          break;
       skb_queue_tail(&card->sbpool.queue, sb);
@@ -2536,7 +2536,7 @@ static void ns_lb_destructor(struct sk_b
 
    do
    {
-      lb = alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
+      lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
       if (lb == NULL)
          break;
       skb_queue_tail(&card->lbpool.queue, lb);
@@ -2555,7 +2555,7 @@ static void ns_hb_destructor(struct sk_b
 
    while (card->hbpool.count < card->hbnr.init)
    {
-      hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
+      hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
       if (hb == NULL)
          break;
       skb_queue_tail(&card->hbpool.queue, hb);
@@ -2627,7 +2627,7 @@ static void dequeue_sm_buf(ns_dev *card,
    if (card->sbfqc < card->sbnr.init)
    {
       struct sk_buff *new_sb;
-      if ((new_sb = alloc_skb(NS_SMSKBSIZE, GFP_ATOMIC)) != NULL)
+      if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL)
       {
          skb_queue_tail(&card->sbpool.queue, new_sb);
          skb_reserve(new_sb, NS_AAL0_HEADER);
@@ -2639,7 +2639,7 @@ static void dequeue_sm_buf(ns_dev *card,
 #endif /* NS_USE_DESTRUCTORS */
    {
       struct sk_buff *new_sb;
-      if ((new_sb = alloc_skb(NS_SMSKBSIZE, GFP_ATOMIC)) != NULL)
+      if ((new_sb = dev_alloc_skb(NS_SMSKBSIZE)) != NULL)
       {
          skb_queue_tail(&card->sbpool.queue, new_sb);
          skb_reserve(new_sb, NS_AAL0_HEADER);
@@ -2660,7 +2660,7 @@ static void dequeue_lg_buf(ns_dev *card,
    if (card->lbfqc < card->lbnr.init)
    {
       struct sk_buff *new_lb;
-      if ((new_lb = alloc_skb(NS_LGSKBSIZE, GFP_ATOMIC)) != NULL)
+      if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL)
       {
          skb_queue_tail(&card->lbpool.queue, new_lb);
          skb_reserve(new_lb, NS_SMBUFSIZE);
@@ -2672,7 +2672,7 @@ static void dequeue_lg_buf(ns_dev *card,
 #endif /* NS_USE_DESTRUCTORS */
    {
       struct sk_buff *new_lb;
-      if ((new_lb = alloc_skb(NS_LGSKBSIZE, GFP_ATOMIC)) != NULL)
+      if ((new_lb = dev_alloc_skb(NS_LGSKBSIZE)) != NULL)
       {
          skb_queue_tail(&card->lbpool.queue, new_lb);
          skb_reserve(new_lb, NS_SMBUFSIZE);
@@ -2866,7 +2866,7 @@ static int ns_ioctl(struct atm_dev *dev,
 	       {
                   struct sk_buff *sb;
 
-                  sb = alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
+                  sb = __dev_alloc_skb(NS_SMSKBSIZE, GFP_KERNEL);
                   if (sb == NULL)
                      return -ENOMEM;
                   skb_queue_tail(&card->sbpool.queue, sb);
@@ -2880,7 +2880,7 @@ static int ns_ioctl(struct atm_dev *dev,
 	       {
                   struct sk_buff *lb;
 
-                  lb = alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
+                  lb = __dev_alloc_skb(NS_LGSKBSIZE, GFP_KERNEL);
                   if (lb == NULL)
                      return -ENOMEM;
                   skb_queue_tail(&card->lbpool.queue, lb);
@@ -2909,7 +2909,7 @@ static int ns_ioctl(struct atm_dev *dev,
                {
                   struct sk_buff *hb;
 
-                  hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
+                  hb = __dev_alloc_skb(NS_HBUFSIZE, GFP_KERNEL);
                   if (hb == NULL)
                      return -ENOMEM;
                   ns_grab_int_lock(card, flags);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/block/Config.in linux-2.4.27-rc4/drivers/block/Config.in
--- linux-2.4.26/drivers/block/Config.in	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/drivers/block/Config.in	2004-07-30 16:26:48.000000000 +0000
@@ -39,6 +39,7 @@ dep_mbool '       SCSI tape drive suppor
 dep_mbool '       Enable monitor thread' CONFIG_CISS_MONITOR_THREAD $CONFIG_BLK_CPQ_CISS_DA
 dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
 dep_tristate 'Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)' CONFIG_BLK_DEV_UMEM $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate 'Promise SATA SX8 support' CONFIG_BLK_DEV_SX8 $CONFIG_PCI
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
 dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/block/Makefile linux-2.4.27-rc4/drivers/block/Makefile
--- linux-2.4.26/drivers/block/Makefile	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/block/Makefile	2004-07-30 16:30:33.000000000 +0000
@@ -31,6 +31,7 @@ obj-$(CONFIG_BLK_CPQ_CISS_DA)  += cciss.
 obj-$(CONFIG_BLK_DEV_DAC960)	+= DAC960.o
 obj-$(CONFIG_BLK_DEV_UMEM)	+= umem.o
 obj-$(CONFIG_BLK_DEV_NBD)	+= nbd.o
+obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
 
 subdir-$(CONFIG_PARIDE) += paride
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/block/cciss.c linux-2.4.27-rc4/drivers/block/cciss.c
--- linux-2.4.26/drivers/block/cciss.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/block/cciss.c	2004-07-30 16:31:48.000000000 +0000
@@ -45,13 +45,13 @@
 #include <linux/genhd.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.4.50)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,50)
+#define DRIVER_NAME "HP CISS Driver (v 2.4.52)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,52)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.50");
-MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400 6i"); 
+MODULE_DESCRIPTION("Driver for HP SA5xxx SA6xxx Controllers version 2.4.52");
+MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400 6i SA6422 V100"); 
 MODULE_LICENSE("GPL");
 
 #include "cciss_cmd.h"
@@ -78,6 +78,10 @@ const struct pci_device_id cciss_pci_dev
                         0x0E11, 0x409D, 0, 0, 0},
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
                         0x0E11, 0x4091, 0, 0, 0},
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
+                        0x0E11, 0x409E, 0, 0, 0},
+	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
+                        0x103C, 0x3211, 0, 0, 0},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -98,6 +102,8 @@ static struct board_type products[] = {
 	{ 0x409C0E11, "Smart Array 6400", &SA5_access},
 	{ 0x409D0E11, "Smart Array 6400 EM", &SA5_access},
 	{ 0x40910E11, "Smart Array 6i", &SA5_access},
+	{ 0x409E0E11, "Smart Array 6422", &SA5_access},
+	{ 0x3211103C, "Smart Array V100", &SA5_access},
 };
 
 /* How long to wait (in millesconds) for board to go into simple mode */
@@ -487,6 +493,142 @@ static int cciss_release(struct inode *i
 	return 0;
 }
 
+#ifdef __x86_64__
+/* for AMD 64 bit kernel compatibility with 32-bit userland ioctls */
+extern int sys_ioctl(unsigned int fd, unsigned cmd, unsigned long arg);
+
+extern int 
+register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int,
+      unsigned int, unsigned long, struct file *));
+extern int unregister_ioctl32_conversion(unsigned int cmd);
+
+static int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, struct file *file);
+static int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg, 
+	struct file *file);
+
+typedef long (*handler type) (unsigned int, unsigned int, unsigned long,
+				struct file *);
+
+static struct ioctl32_map {
+	unsigned int cmd; 
+	handler_type handler;
+	int registered;
+} cciss_ioctl32_map[] = {
+	{ CCISS_GETPCIINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETINTINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_SETINTINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETNODENAME,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_SETNODENAME,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETHEARTBEAT,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETBUSTYPES,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETFIRMVER,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETDRIVVER,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REVALIDVOLS,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_PASSTHRU32,	cciss_ioctl32_passthru, 0 },
+	{ CCISS_DEREGDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REGNEWDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_REGNEWD,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_RESCANDISK,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_GETLUNINFO,	(handler_type) sys_ioctl, 0 },
+	{ CCISS_BIG_PASSTHRU32,	cciss_ioctl32_big_passthru, 0 },
+};
+#define NCCISS_IOCTL32_ENTRIES (sizeof(cciss_ioctl32_map) / sizeof(cciss_ioctl32_map[0]))
+static void register_cciss_ioctl32(void)
+{
+	int i, rc;
+
+	for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) {
+		rc = register_ioctl32_conversion(
+			cciss_ioctl32_map[i].cmd,
+			cciss_ioctl32_map[i].handler);
+		if (rc != 0) {
+			printk(KERN_WARNING "cciss: failed to register "
+				"32 bit compatible ioctl 0x%08x\n", 
+				cciss_ioctl32_map[i].cmd);
+			cciss_ioctl32_map[i].registered = 0;
+		} else
+			cciss_ioctl32_map[i].registered = 1;
+	}
+}
+static void unregister_cciss_ioctl32(void)
+{
+	int i, rc;
+
+	for (i=0; i < NCCISS_IOCTL32_ENTRIES; i++) {
+		if (!cciss_ioctl32_map[i].registered)
+			continue;
+		rc = unregister_ioctl32_conversion(
+			cciss_ioctl32_map[i].cmd);
+		if (rc == 0) {
+			cciss_ioctl32_map[i].registered = 0;
+			continue;
+		}
+		printk(KERN_WARNING "cciss: failed to unregister "
+			"32 bit compatible ioctl 0x%08x\n",
+			cciss_ioctl32_map[i].cmd);
+	}
+}
+int cciss_ioctl32_passthru(unsigned int fd, unsigned cmd, unsigned long arg, 
+				struct file *file)
+{
+	IOCTL32_Command_struct *arg32 = 
+		(IOCTL32_Command_struct *) arg;
+	IOCTL_Command_struct arg64;
+	mm_segment_t old_fs; 
+	int err;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(arg64.buf, &arg32->buf);
+	if (err) 
+		return -EFAULT; 
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, CCISS_PASSTHRU, (unsigned long) &arg64);
+	set_fs(old_fs);
+	if (err)
+		return err;
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	if (err) 
+		return -EFAULT; 
+	return err;
+}
+int cciss_ioctl32_big_passthru(unsigned int fd, unsigned cmd, unsigned long arg,
+					struct file *file)
+{
+	BIG_IOCTL32_Command_struct *arg32 = 
+		(BIG_IOCTL32_Command_struct *) arg;
+	BIG_IOCTL_Command_struct arg64;
+	mm_segment_t old_fs; 
+	int err;
+
+	err = 0;
+	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
+	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
+	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |= get_user(arg64.buf_size, &arg32->buf_size);
+	err |= get_user(arg64.malloc_size, &arg32->malloc_size);
+	err |= get_user(arg64.buf, &arg32->buf);
+	if (err) return -EFAULT; 
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, CCISS_BIG_PASSTHRU, (unsigned long) &arg64);
+	set_fs(old_fs);
+	if (err)
+		return err;
+	err |= copy_to_user(&arg32->error_info, &arg64.error_info, sizeof(&arg32->error_info));
+	if (err) 
+		return -EFAULT; 
+	return err;
+}
+#else 
+static inline void register_cciss_ioctl32(void) {}
+static inline void unregister_cciss_ioctl32(void) {}
+#endif
 /*
  * ioctl 
  */
@@ -3317,7 +3459,7 @@ int __init cciss_init(void)
 EXPORT_NO_SYMBOLS;
 static int __init init_cciss_module(void)
 {
-
+	register_cciss_ioctl32();
 	return cciss_init();
 }
 
@@ -3325,6 +3467,7 @@ static void __exit cleanup_cciss_module(
 {
 	int i;
 
+	unregister_cciss_ioctl32();
 	pci_unregister_driver(&cciss_pci_driver);
 	/* double check that all controller entrys have been removed */
 	for (i=0; i< MAX_CTLR; i++) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/block/cciss_scsi.c linux-2.4.27-rc4/drivers/block/cciss_scsi.c
--- linux-2.4.26/drivers/block/cciss_scsi.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/block/cciss_scsi.c	2004-07-30 16:24:41.000000000 +0000
@@ -1569,7 +1569,7 @@ static void
 cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
 {
 	int size;
-	unsigned int flags;
+	unsigned long flags;
 
 	*pos = *pos -1; *len = *len - 1; // cut off the last trailing newline
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/block/sx8.c linux-2.4.27-rc4/drivers/block/sx8.c
--- linux-2.4.26/drivers/block/sx8.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/block/sx8.c	2004-07-30 16:27:10.000000000 +0000
@@ -0,0 +1,2083 @@
+/*
+ *  carmel.c: Driver for Promise SATA SX8 looks-like-I2O hardware
+ *
+ *  Copyright 2004 Red Hat, Inc.
+ *
+ *  Author/maintainer:  Jeff Garzik <jgarzik@pobox.com>
+ *
+ *  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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/blk.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/compiler.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/hdreg.h>
+#include <linux/fs.h>
+#include <linux/blkpg.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+#include <asm/uaccess.h>
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Promise SATA SX8 (carmel) block driver");
+
+#if 0
+#define CARM_DEBUG
+#define CARM_VERBOSE_DEBUG
+#else
+#undef CARM_DEBUG
+#undef CARM_VERBOSE_DEBUG
+#endif
+#undef CARM_NDEBUG
+
+#define DRV_NAME "carmel"
+#define DRV_VERSION "0.8-24.1"
+#define PFX DRV_NAME ": "
+
+#define NEXT_RESP(idx)	((idx + 1) % RMSG_Q_LEN)
+
+/* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */
+#define TAG_ENCODE(tag)	(((tag) << 16) | 0xf)
+#define TAG_DECODE(tag)	(((tag) >> 16) & 0x1f)
+#define TAG_VALID(tag)	((((tag) & 0xf) == 0xf) && (TAG_DECODE(tag) < 32))
+
+/* note: prints function name for you */
+#ifdef CARM_DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#ifdef CARM_VERBOSE_DEBUG
+#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define VPRINTK(fmt, args...)
+#endif	/* CARM_VERBOSE_DEBUG */
+#else
+#define DPRINTK(fmt, args...)
+#define VPRINTK(fmt, args...)
+#endif	/* CARM_DEBUG */
+
+#ifdef CARM_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+        if(unlikely(!(expr))) {                                   \
+        printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
+        #expr,__FILE__,__FUNCTION__,__LINE__);          \
+        }
+#endif
+
+/* defines only for the constants which don't work well as enums */
+struct carm_host;
+
+enum {
+	/* adapter-wide limits */
+	CARM_MAX_PORTS		= 8,
+	CARM_SHM_SIZE		= (4096 << 7),
+	CARM_PART_SHIFT		= 5,
+	CARM_MINORS_PER_MAJOR	= (1 << CARM_PART_SHIFT),
+	CARM_MAX_WAIT_Q		= CARM_MAX_PORTS + 1,
+
+	/* command message queue limits */
+	CARM_MAX_REQ		= 64,	       /* max command msgs per host */
+	CARM_MAX_Q		= 1,		   /* one command at a time */
+	CARM_MSG_LOW_WATER	= (CARM_MAX_REQ / 4),	     /* refill mark */
+
+	/* S/G limits, host-wide and per-request */
+	CARM_MAX_REQ_SG		= 32,	     /* max s/g entries per request */
+	CARM_SG_BOUNDARY	= 0xffffUL,	    /* s/g segment boundary */
+	CARM_MAX_HOST_SG	= 600,		/* max s/g entries per host */
+	CARM_SG_LOW_WATER	= (CARM_MAX_HOST_SG / 4),   /* re-fill mark */
+
+	/* hardware registers */
+	CARM_IHQP		= 0x1c,
+	CARM_INT_STAT		= 0x10, /* interrupt status */
+	CARM_INT_MASK		= 0x14, /* interrupt mask */
+	CARM_HMUC		= 0x18, /* host message unit control */
+	RBUF_ADDR_LO		= 0x20, /* response msg DMA buf low 32 bits */
+	RBUF_ADDR_HI		= 0x24, /* response msg DMA buf high 32 bits */
+	RBUF_BYTE_SZ		= 0x28,
+	CARM_RESP_IDX		= 0x2c,
+	CARM_CMS0		= 0x30, /* command message size reg 0 */
+	CARM_LMUC		= 0x48,
+	CARM_HMPHA		= 0x6c,
+	CARM_INITC		= 0xb5,
+
+	/* bits in CARM_INT_{STAT,MASK} */
+	INT_RESERVED		= 0xfffffff0,
+	INT_WATCHDOG		= (1 << 3),	/* watchdog timer */
+	INT_Q_OVERFLOW		= (1 << 2),	/* cmd msg q overflow */
+	INT_Q_AVAILABLE		= (1 << 1),	/* cmd msg q has free space */
+	INT_RESPONSE		= (1 << 0),	/* response msg available */
+	INT_ACK_MASK		= INT_WATCHDOG | INT_Q_OVERFLOW,
+	INT_DEF_MASK		= INT_RESERVED | INT_Q_OVERFLOW |
+				  INT_RESPONSE,
+
+	/* command messages, and related register bits */
+	CARM_HAVE_RESP		= 0x01,
+	CARM_MSG_READ		= 1,
+	CARM_MSG_WRITE		= 2,
+	CARM_MSG_VERIFY		= 3,
+	CARM_MSG_GET_CAPACITY	= 4,
+	CARM_MSG_FLUSH		= 5,
+	CARM_MSG_IOCTL		= 6,
+	CARM_MSG_ARRAY		= 8,
+	CARM_MSG_MISC		= 9,
+	CARM_CME		= (1 << 2),
+	CARM_RME		= (1 << 1),
+	CARM_WZBC		= (1 << 0),
+	CARM_RMI		= (1 << 0),
+	CARM_Q_FULL		= (1 << 3),
+	CARM_MSG_SIZE		= 288,
+	CARM_Q_LEN		= 48,
+
+	/* CARM_MSG_IOCTL messages */
+	CARM_IOC_SCAN_CHAN	= 5,	/* scan channels for devices */
+	CARM_IOC_GET_TCQ	= 13,	/* get tcq/ncq depth */
+	CARM_IOC_SET_TCQ	= 14,	/* set tcq/ncq depth */
+
+	IOC_SCAN_CHAN_NODEV	= 0x1f,
+	IOC_SCAN_CHAN_OFFSET	= 0x40,
+
+	/* CARM_MSG_ARRAY messages */
+	CARM_ARRAY_INFO		= 0,
+
+	ARRAY_NO_EXIST		= (1 << 31),
+
+	/* response messages */
+	RMSG_SZ			= 8,	/* sizeof(struct carm_response) */
+	RMSG_Q_LEN		= 48,	/* resp. msg list length */
+	RMSG_OK			= 1,	/* bit indicating msg was successful */
+					/* length of entire resp. msg buffer */
+	RBUF_LEN		= RMSG_SZ * RMSG_Q_LEN,
+
+	PDC_SHM_SIZE		= (4096 << 7), /* length of entire h/w buffer */
+
+	/* CARM_MSG_MISC messages */
+	MISC_GET_FW_VER		= 2,
+	MISC_ALLOC_MEM		= 3,
+	MISC_SET_TIME		= 5,
+
+	/* MISC_GET_FW_VER feature bits */
+	FW_VER_4PORT		= (1 << 2), /* 1=4 ports, 0=8 ports */
+	FW_VER_NON_RAID		= (1 << 1), /* 1=non-RAID firmware, 0=RAID */
+	FW_VER_ZCR		= (1 << 0), /* zero channel RAID (whatever that is) */
+
+	/* carm_host flags */
+	FL_NON_RAID		= FW_VER_NON_RAID,
+	FL_4PORT		= FW_VER_4PORT,
+	FL_FW_VER_MASK		= (FW_VER_NON_RAID | FW_VER_4PORT),
+	FL_DAC			= (1 << 16),
+	FL_DYN_MAJOR		= (1 << 17),
+};
+
+enum carm_magic_numbers {
+	CARM_MAGIC_HOST		= 0xdeadbeefUL,
+	CARM_MAGIC_PORT		= 0xbedac0edUL,
+};
+
+enum scatter_gather_types {
+	SGT_32BIT		= 0,
+	SGT_64BIT		= 1,
+};
+
+enum host_states {
+	HST_INVALID,		/* invalid state; never used */
+	HST_ALLOC_BUF,		/* setting up master SHM area */
+	HST_ERROR,		/* we never leave here */
+	HST_PORT_SCAN,		/* start dev scan */
+	HST_DEV_SCAN_START,	/* start per-device probe */
+	HST_DEV_SCAN,		/* continue per-device probe */
+	HST_DEV_ACTIVATE,	/* activate devices we found */
+	HST_PROBE_FINISHED,	/* probe is complete */
+	HST_PROBE_START,	/* initiate probe */
+	HST_SYNC_TIME,		/* tell firmware what time it is */
+	HST_GET_FW_VER,		/* get firmware version, adapter port cnt */
+};
+
+#ifdef CARM_DEBUG
+static const char *state_name[] = {
+	"HST_INVALID",
+	"HST_ALLOC_BUF",
+	"HST_ERROR",
+	"HST_PORT_SCAN",
+	"HST_DEV_SCAN_START",
+	"HST_DEV_SCAN",
+	"HST_DEV_ACTIVATE",
+	"HST_PROBE_FINISHED",
+	"HST_PROBE_START",
+	"HST_SYNC_TIME",
+	"HST_GET_FW_VER",
+};
+#endif
+
+struct carm_port {
+	unsigned long			magic;
+	unsigned int			port_no;
+	unsigned int			n_queued;
+	struct carm_host		*host;
+	struct tasklet_struct		tasklet;
+	request_queue_t			q;
+
+	/* attached device characteristics */
+	u64				capacity;
+	char				name[41];
+	u16				dev_geom_head;
+	u16				dev_geom_sect;
+	u16				dev_geom_cyl;
+};
+
+struct carm_request {
+	unsigned int			tag;
+	int				n_elem;
+	unsigned int			msg_type;
+	unsigned int			msg_subtype;
+	unsigned int			msg_bucket;
+	struct request			*rq;
+	struct carm_port		*port;
+	struct request			special_rq;
+	struct scatterlist		sg[CARM_MAX_REQ_SG];
+};
+
+struct carm_host {
+	unsigned long			magic;
+	unsigned long			flags;
+	void				*mmio;
+	void				*shm;
+	dma_addr_t			shm_dma;
+
+	int				major;
+	int				id;
+	char				name[32];
+
+	struct pci_dev			*pdev;
+	unsigned int			state;
+	u32				fw_ver;
+
+	request_queue_t			oob_q;
+	unsigned int			n_oob;
+	struct tasklet_struct		oob_tasklet;
+
+	unsigned int			hw_sg_used;
+
+	unsigned int			resp_idx;
+
+	unsigned int			wait_q_prod;
+	unsigned int			wait_q_cons;
+	request_queue_t			*wait_q[CARM_MAX_WAIT_Q];
+
+	unsigned int			n_msgs;
+	u64				msg_alloc;
+	struct carm_request		req[CARM_MAX_REQ];
+	void				*msg_base;
+	dma_addr_t			msg_dma;
+
+	int				cur_scan_dev;
+	unsigned long			dev_active;
+	unsigned long			dev_present;
+	struct carm_port		port[CARM_MAX_PORTS];
+
+	struct tq_struct		fsm_task;
+
+	struct semaphore		probe_sem;
+
+	struct gendisk			gendisk;
+	struct hd_struct		gendisk_hd[256];
+	int				blk_sizes[256];
+	int				blk_block_sizes[256];
+	int				blk_sect_sizes[256];
+
+	struct list_head		host_list_node;
+};
+
+struct carm_response {
+	u32 ret_handle;
+	u32 status;
+}  __attribute__((packed));
+
+struct carm_msg_sg {
+	u32 start;
+	u32 len;
+}  __attribute__((packed));
+
+struct carm_msg_rw {
+	u8 type;
+	u8 id;
+	u8 sg_count;
+	u8 sg_type;
+	u32 handle;
+	u32 lba;
+	u16 lba_count;
+	u16 lba_high;
+	struct carm_msg_sg sg[32];
+}  __attribute__((packed));
+
+struct carm_msg_allocbuf {
+	u8 type;
+	u8 subtype;
+	u8 n_sg;
+	u8 sg_type;
+	u32 handle;
+	u32 addr;
+	u32 len;
+	u32 evt_pool;
+	u32 n_evt;
+	u32 rbuf_pool;
+	u32 n_rbuf;
+	u32 msg_pool;
+	u32 n_msg;
+	struct carm_msg_sg sg[8];
+}  __attribute__((packed));
+
+struct carm_msg_ioctl {
+	u8 type;
+	u8 subtype;
+	u8 array_id;
+	u8 reserved1;
+	u32 handle;
+	u32 data_addr;
+	u32 reserved2;
+}  __attribute__((packed));
+
+struct carm_msg_sync_time {
+	u8 type;
+	u8 subtype;
+	u16 reserved1;
+	u32 handle;
+	u32 reserved2;
+	u32 timestamp;
+}  __attribute__((packed));
+
+struct carm_msg_get_fw_ver {
+	u8 type;
+	u8 subtype;
+	u16 reserved1;
+	u32 handle;
+	u32 data_addr;
+	u32 reserved2;
+}  __attribute__((packed));
+
+struct carm_fw_ver {
+	u32 version;
+	u8 features;
+	u8 reserved1;
+	u16 reserved2;
+}  __attribute__((packed));
+
+struct carm_array_info {
+	u32 size;
+
+	u16 size_hi;
+	u16 stripe_size;
+
+	u32 mode;
+
+	u16 stripe_blk_sz;
+	u16 reserved1;
+
+	u16 cyl;
+	u16 head;
+
+	u16 sect;
+	u8 array_id;
+	u8 reserved2;
+
+	char name[40];
+
+	u32 array_status;
+
+	/* device list continues beyond this point? */
+}  __attribute__((packed));
+
+static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void carm_remove_one (struct pci_dev *pdev);
+static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
+			   unsigned int cmd, unsigned long arg);
+static request_queue_t *carm_find_queue(kdev_t device);
+static int carm_revalidate_disk(kdev_t dev);
+
+static struct pci_device_id carm_pci_tbl[] = {
+	{ PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ PCI_VENDOR_ID_PROMISE, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	{ }	/* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, carm_pci_tbl);
+
+static struct pci_driver carm_driver = {
+	.name		= DRV_NAME,
+	.id_table	= carm_pci_tbl,
+	.probe		= carm_init_one,
+	.remove		= carm_remove_one,
+};
+
+static struct block_device_operations carm_bd_ops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= carm_bdev_ioctl,
+};
+
+static unsigned int carm_host_id;
+static unsigned long carm_major_alloc;
+
+
+static struct carm_host *carm_from_dev(kdev_t dev, struct carm_port **port_out)
+{
+	struct carm_host *host;
+	struct carm_port *port;
+	request_queue_t *q;
+
+	q = carm_find_queue(dev);
+	if (!q || !q->queuedata) {
+		printk(KERN_ERR PFX "queue not found for major %d minor %d\n",
+			MAJOR(dev), MINOR(dev));
+		return NULL;
+	}
+
+	port = q->queuedata;
+	if (unlikely(port->magic != CARM_MAGIC_PORT)) {
+		printk(KERN_ERR PFX "bad port magic number for major %d minor %d\n",
+			MAJOR(dev), MINOR(dev));
+		return NULL;
+	}
+
+	host = port->host;
+	if (unlikely(host->magic != CARM_MAGIC_HOST)) {
+		printk(KERN_ERR PFX "bad host magic number for major %d minor %d\n",
+			MAJOR(dev), MINOR(dev));
+		return NULL;
+	}
+
+	if (port_out)
+		*port_out = port;
+	return host;
+}
+
+static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
+			   unsigned int cmd, unsigned long arg)
+{
+	void *usermem = (void *) arg;
+	struct carm_port *port = NULL;
+	struct carm_host *host;
+
+	host = carm_from_dev(ino->i_rdev, &port);
+	if (!host)
+		return -EINVAL;
+
+	switch (cmd) {
+	case HDIO_GETGEO: {
+		struct hd_geometry geom;
+
+		if (!usermem)
+			return -EINVAL;
+
+		if (port->dev_geom_cyl) {
+			geom.heads = port->dev_geom_head;
+			geom.sectors = port->dev_geom_sect;
+			geom.cylinders = port->dev_geom_cyl;
+		} else {
+			u32 tmp = ((u32)port->capacity) / (0xff * 0x3f);
+			geom.heads = 0xff;
+			geom.sectors = 0x3f;
+			if (tmp > 65536)
+				geom.cylinders = 0xffff;
+			else
+				geom.cylinders = tmp;
+		}
+		geom.start = host->gendisk_hd[MINOR(ino->i_rdev)].start_sect;
+
+		if (copy_to_user(usermem, &geom, sizeof(geom)))
+			return -EFAULT;
+		return 0;
+	}
+
+	case HDIO_GETGEO_BIG: {
+		struct hd_big_geometry geom;
+
+		if (!usermem)
+			return -EINVAL;
+
+		if (port->dev_geom_cyl) {
+			geom.heads = port->dev_geom_head;
+			geom.sectors = port->dev_geom_sect;
+			geom.cylinders = port->dev_geom_cyl;
+		} else {
+			geom.heads = 0xff;
+			geom.sectors = 0x3f;
+			geom.cylinders = ((u32)port->capacity) / (0xff * 0x3f);
+		}
+		geom.start = host->gendisk_hd[MINOR(ino->i_rdev)].start_sect;
+
+		if (copy_to_user(usermem, &geom, sizeof(geom)))
+			return -EFAULT;
+		return 0;
+	}
+
+	case BLKRRPART:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		return carm_revalidate_disk(ino->i_rdev);
+
+	case BLKGETSIZE:
+	case BLKGETSIZE64:
+	case BLKFLSBUF:
+	case BLKBSZSET:
+	case BLKBSZGET:
+	case BLKROSET:
+	case BLKROGET:
+	case BLKRASET:
+	case BLKRAGET:
+	case BLKPG:
+	case BLKELVGET:
+	case BLKELVSET:
+		return blk_ioctl(ino->i_rdev, cmd, arg);
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static inline unsigned long msecs_to_jiffies(unsigned long msecs)
+{
+	return ((HZ * msecs + 999) / 1000);
+}
+
+static void msleep(unsigned long msecs)
+{
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(msecs) + 1);
+}
+
+static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
+
+static inline int carm_lookup_bucket(u32 msg_size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
+		if (msg_size <= msg_sizes[i])
+			return i;
+	
+	return -ENOENT;
+}
+
+static void carm_init_buckets(void *mmio)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(msg_sizes); i++)
+		writel(msg_sizes[i], mmio + CARM_CMS0 + (4 * i));
+}
+
+static inline void *carm_ref_msg(struct carm_host *host,
+				 unsigned int msg_idx)
+{
+	return host->msg_base + (msg_idx * CARM_MSG_SIZE);
+}
+
+static inline dma_addr_t carm_ref_msg_dma(struct carm_host *host,
+					  unsigned int msg_idx)
+{
+	return host->msg_dma + (msg_idx * CARM_MSG_SIZE);
+}
+
+static int carm_send_msg(struct carm_host *host,
+			 struct carm_request *crq)
+{
+	void *mmio = host->mmio;
+	u32 msg = (u32) carm_ref_msg_dma(host, crq->tag);
+	u32 cm_bucket = crq->msg_bucket;
+	u32 tmp;
+	int rc = 0;
+
+	VPRINTK("ENTER\n");
+
+	tmp = readl(mmio + CARM_HMUC);
+	if (tmp & CARM_Q_FULL) {
+#if 0
+		tmp = readl(mmio + CARM_INT_MASK);
+		tmp |= INT_Q_AVAILABLE;
+		writel(tmp, mmio + CARM_INT_MASK);
+		readl(mmio + CARM_INT_MASK);	/* flush */
+#endif
+		DPRINTK("host msg queue full\n");
+		rc = -EBUSY;
+	} else {
+		writel(msg | (cm_bucket << 1), mmio + CARM_IHQP);
+		readl(mmio + CARM_IHQP);	/* flush */
+	}
+
+	return rc;
+}
+
+static struct carm_request *carm_get_request(struct carm_host *host)
+{
+	unsigned int i;
+
+	/* obey global hardware limit on S/G entries */
+	if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG))
+		return NULL;
+
+	for (i = 0; i < CARM_MAX_Q; i++)
+		if ((host->msg_alloc & (1ULL << i)) == 0) {
+			struct carm_request *crq = &host->req[i];
+			crq->port = NULL;
+			crq->n_elem = 0;
+
+			host->msg_alloc |= (1ULL << i);
+			host->n_msgs++;
+
+			assert(host->n_msgs <= CARM_MAX_REQ);
+			return crq;
+		}
+	
+	DPRINTK("no request available, returning NULL\n");
+	return NULL;
+}
+
+static int carm_put_request(struct carm_host *host, struct carm_request *crq)
+{
+	assert(crq->tag < CARM_MAX_Q);
+
+	if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0))
+		return -EINVAL; /* tried to clear a tag that was not active */
+
+	assert(host->hw_sg_used >= crq->n_elem);
+
+	host->msg_alloc &= ~(1ULL << crq->tag);
+	host->hw_sg_used -= crq->n_elem;
+	host->n_msgs--;
+
+	return 0;
+}
+
+static void carm_insert_special(request_queue_t *q, struct request *rq,
+				void *data, int at_head)
+{
+	unsigned long flags;
+
+	rq->cmd = SPECIAL;
+	rq->special = data;
+	rq->q = NULL;
+	rq->nr_segments = 0;
+	rq->elevator_sequence = 0;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	if (at_head)
+		list_add(&rq->queue, &q->queue_head);
+	else
+		list_add_tail(&rq->queue, &q->queue_head);
+	q->request_fn(q);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+static struct carm_request *carm_get_special(struct carm_host *host)
+{
+	unsigned long flags;
+	struct carm_request *crq = NULL;
+	int tries = 5000;
+
+	while (tries-- > 0) {
+		spin_lock_irqsave(&io_request_lock, flags);
+		crq = carm_get_request(host);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+
+		if (crq)
+			break;
+		msleep(10);
+	}
+
+	if (!crq)
+		return NULL;
+
+	crq->rq = &crq->special_rq;
+	return crq;
+}
+
+static int carm_array_info (struct carm_host *host, unsigned int array_idx)
+{
+	struct carm_msg_ioctl *ioc;
+	unsigned int idx;
+	u32 msg_data;
+	dma_addr_t msg_dma;
+	struct carm_request *crq;
+	int rc;
+	unsigned long flags;
+
+	crq = carm_get_special(host);
+	if (!crq) {
+		rc = -ENOMEM;
+		goto err_out;
+	}
+
+	idx = crq->tag;
+
+	ioc = carm_ref_msg(host, idx);
+	msg_dma = carm_ref_msg_dma(host, idx);
+	msg_data = (u32) (msg_dma + sizeof(struct carm_array_info));
+
+	crq->msg_type = CARM_MSG_ARRAY;
+	crq->msg_subtype = CARM_ARRAY_INFO;
+	rc = carm_lookup_bucket(sizeof(struct carm_msg_ioctl) +
+				sizeof(struct carm_array_info));
+	BUG_ON(rc < 0);
+	crq->msg_bucket = (u32) rc;
+
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->type	= CARM_MSG_ARRAY;
+	ioc->subtype	= CARM_ARRAY_INFO;
+	ioc->array_id	= (u8) array_idx;
+	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ioc->data_addr	= cpu_to_le32(msg_data);
+
+	assert(host->state == HST_DEV_SCAN_START ||
+	       host->state == HST_DEV_SCAN);
+
+	DPRINTK("blk_insert_request, tag == %u\n", idx);
+	carm_insert_special(&host->oob_q, crq->rq, crq, 1);
+
+	return 0;
+
+err_out:
+	spin_lock_irqsave(&io_request_lock, flags);
+	host->state = HST_ERROR;
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	return rc;
+}
+
+typedef unsigned int (*carm_sspc_t)(struct carm_host *, unsigned int, void *);
+
+static int carm_send_special (struct carm_host *host, carm_sspc_t func)
+{
+	struct carm_request *crq;
+	struct carm_msg_ioctl *ioc;
+	void *mem;
+	unsigned int idx, msg_size;
+	int rc;
+
+	crq = carm_get_special(host);
+	if (!crq)
+		return -ENOMEM;
+
+	idx = crq->tag;
+
+	mem = carm_ref_msg(host, idx);
+
+	msg_size = func(host, idx, mem);
+
+	ioc = mem;
+	crq->msg_type = ioc->type;
+	crq->msg_subtype = ioc->subtype;
+	rc = carm_lookup_bucket(msg_size);
+	BUG_ON(rc < 0);
+	crq->msg_bucket = (u32) rc;
+
+	DPRINTK("blk_insert_request, tag == %u\n", idx);
+	carm_insert_special(&host->oob_q, crq->rq, crq, 1);
+
+	return 0;
+}
+
+static unsigned int carm_fill_sync_time(struct carm_host *host,
+					unsigned int idx, void *mem)
+{
+	struct timeval tv;
+	struct carm_msg_sync_time *st = mem;
+
+	do_gettimeofday(&tv);
+
+	memset(st, 0, sizeof(*st));
+	st->type	= CARM_MSG_MISC;
+	st->subtype	= MISC_SET_TIME;
+	st->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	st->timestamp	= cpu_to_le32(tv.tv_sec);
+
+	return sizeof(struct carm_msg_sync_time);
+}
+
+static unsigned int carm_fill_alloc_buf(struct carm_host *host,
+					unsigned int idx, void *mem)
+{
+	struct carm_msg_allocbuf *ab = mem;
+
+	memset(ab, 0, sizeof(*ab));
+	ab->type	= CARM_MSG_MISC;
+	ab->subtype	= MISC_ALLOC_MEM;
+	ab->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ab->n_sg	= 1;
+	ab->sg_type	= SGT_32BIT;
+	ab->addr	= cpu_to_le32(host->shm_dma + (PDC_SHM_SIZE >> 1));
+	ab->len		= cpu_to_le32(PDC_SHM_SIZE >> 1);
+	ab->evt_pool	= cpu_to_le32(host->shm_dma + (16 * 1024));
+	ab->n_evt	= cpu_to_le32(1024);
+	ab->rbuf_pool	= cpu_to_le32(host->shm_dma);
+	ab->n_rbuf	= cpu_to_le32(RMSG_Q_LEN);
+	ab->msg_pool	= cpu_to_le32(host->shm_dma + RBUF_LEN);
+	ab->n_msg	= cpu_to_le32(CARM_Q_LEN);
+	ab->sg[0].start	= cpu_to_le32(host->shm_dma + (PDC_SHM_SIZE >> 1));
+	ab->sg[0].len	= cpu_to_le32(65536);
+
+	return sizeof(struct carm_msg_allocbuf);
+}
+
+static unsigned int carm_fill_scan_channels(struct carm_host *host,
+					    unsigned int idx, void *mem)
+{
+	struct carm_msg_ioctl *ioc = mem;
+	u32 msg_data = (u32) (carm_ref_msg_dma(host, idx) +
+			      IOC_SCAN_CHAN_OFFSET);
+
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->type	= CARM_MSG_IOCTL;
+	ioc->subtype	= CARM_IOC_SCAN_CHAN;
+	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ioc->data_addr	= cpu_to_le32(msg_data);
+
+	/* fill output data area with "no device" default values */
+	mem += IOC_SCAN_CHAN_OFFSET;
+	memset(mem, IOC_SCAN_CHAN_NODEV, CARM_MAX_PORTS);
+
+	return IOC_SCAN_CHAN_OFFSET + CARM_MAX_PORTS;
+}
+
+static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
+					 unsigned int idx, void *mem)
+{
+	struct carm_msg_get_fw_ver *ioc = mem;
+	u32 msg_data = (u32) (carm_ref_msg_dma(host, idx) + sizeof(*ioc));
+
+	memset(ioc, 0, sizeof(*ioc));
+	ioc->type	= CARM_MSG_MISC;
+	ioc->subtype	= MISC_GET_FW_VER;
+	ioc->handle	= cpu_to_le32(TAG_ENCODE(idx));
+	ioc->data_addr	= cpu_to_le32(msg_data);
+
+	return sizeof(struct carm_msg_get_fw_ver) +
+	       sizeof(struct carm_fw_ver);
+}
+
+static void carm_activate_disk(struct carm_host *host,
+			       struct carm_port *port)
+{
+	int minor_start = port->port_no << CARM_PART_SHIFT;
+	int start, end, i;
+
+	host->gendisk_hd[minor_start].nr_sects = port->capacity;
+	host->blk_sizes[minor_start] = port->capacity;
+
+	start = minor_start;
+	end = minor_start + CARM_MINORS_PER_MAJOR;
+	for (i = start; i < end; i++) {
+		invalidate_device(MKDEV(host->major, i), 1);
+		host->gendisk.part[i].start_sect = 0;
+		host->gendisk.part[i].nr_sects = 0;
+		host->blk_block_sizes[i] = 512;
+		host->blk_sect_sizes[i] = 512;
+	}
+
+	grok_partitions(&host->gendisk, port->port_no, 
+			CARM_MINORS_PER_MAJOR,
+			port->capacity);
+}
+
+static int carm_revalidate_disk(kdev_t dev)
+{
+	struct carm_host *host;
+	struct carm_port *port = NULL;
+
+	host = carm_from_dev(dev, &port);
+	if (!host)
+		return -EINVAL;
+
+	carm_activate_disk(host, port);
+
+	return 0;
+}
+
+static inline void complete_buffers(struct buffer_head *bh, int status)
+{
+	struct buffer_head *xbh;
+	
+	while (bh) {
+		xbh = bh->b_reqnext; 
+		bh->b_reqnext = NULL; 
+		blk_finished_io(bh->b_size >> 9);
+		bh->b_end_io(bh, status);
+		bh = xbh;
+	}
+} 
+
+static inline void carm_end_request_queued(struct carm_host *host,
+					   struct carm_request *crq,
+					   int uptodate)
+{
+	struct request *req = crq->rq;
+	int rc;
+
+	complete_buffers(req->bh, uptodate);
+	end_that_request_last(req);
+
+	rc = carm_put_request(host, crq);
+	assert(rc == 0);
+}
+
+static inline void carm_push_q (struct carm_host *host, request_queue_t *q)
+{
+	unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
+
+	VPRINTK("STOPPED QUEUE %p\n", q);
+
+	host->wait_q[idx] = q;
+	host->wait_q_prod++;
+	BUG_ON(host->wait_q_prod == host->wait_q_cons); /* overrun */
+}
+
+static inline request_queue_t *carm_pop_q(struct carm_host *host)
+{
+	unsigned int idx;
+
+	if (host->wait_q_prod == host->wait_q_cons)
+		return NULL;
+
+	idx = host->wait_q_cons % CARM_MAX_WAIT_Q;
+	host->wait_q_cons++;
+
+	return host->wait_q[idx];
+}
+
+static inline void carm_round_robin(struct carm_host *host)
+{
+	request_queue_t *q = carm_pop_q(host);
+	if (q) {
+		struct tasklet_struct *tasklet;
+		if (q == &host->oob_q)
+			tasklet = &host->oob_tasklet;
+		else {
+			struct carm_port *port = q->queuedata;
+			tasklet = &port->tasklet;
+		}
+		tasklet_schedule(tasklet);
+		VPRINTK("STARTED QUEUE %p\n", q);
+	}
+}
+
+static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
+			int is_ok)
+{
+	carm_end_request_queued(host, crq, is_ok);
+	if (CARM_MAX_Q == 1)
+		carm_round_robin(host);
+	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
+		 (host->hw_sg_used <= CARM_SG_LOW_WATER)) {
+		carm_round_robin(host);
+	}
+}
+
+static inline int carm_new_segment(request_queue_t *q, struct request *rq)
+{
+        if (rq->nr_segments < CARM_MAX_REQ_SG) {
+                rq->nr_segments++;
+                return 1;
+        }
+        return 0;
+}
+
+static int carm_back_merge_fn(request_queue_t *q, struct request *rq,
+                             struct buffer_head *bh, int max_segments)
+{
+	if (blk_seg_merge_ok(rq->bhtail, bh))	
+                return 1;
+        return carm_new_segment(q, rq);
+}
+
+static int carm_front_merge_fn(request_queue_t *q, struct request *rq,
+                             struct buffer_head *bh, int max_segments)
+{
+	if (blk_seg_merge_ok(bh, rq->bh))
+                return 1;
+        return carm_new_segment(q, rq);
+}
+
+static int carm_merge_requests_fn(request_queue_t *q, struct request *rq,
+                                 struct request *nxt, int max_segments)
+{
+        int total_segments = rq->nr_segments + nxt->nr_segments;
+
+	if (blk_seg_merge_ok(rq->bhtail, nxt->bh))
+                total_segments--;
+
+        if (total_segments > CARM_MAX_REQ_SG)
+                return 0;
+
+        rq->nr_segments = total_segments;
+        return 1;
+}
+
+static void carm_oob_rq_fn(request_queue_t *q)
+{
+	struct carm_host *host = q->queuedata;
+
+	tasklet_schedule(&host->oob_tasklet);
+}
+
+static void carm_rq_fn(request_queue_t *q)
+{
+	struct carm_port *port = q->queuedata;
+
+	tasklet_schedule(&port->tasklet);
+}
+
+static void carm_oob_tasklet(unsigned long _data)
+{
+	struct carm_host *host = (void *) _data;
+	request_queue_t *q = &host->oob_q;
+	struct carm_request *crq;
+	struct request *rq;
+	int rc, have_work = 1;
+	struct list_head *queue_head = &q->queue_head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	if (q->plugged || list_empty(queue_head))
+		have_work = 0;
+
+	if (!have_work)
+		goto out;
+
+	while (1) {
+		DPRINTK("get req\n");
+		if (list_empty(queue_head))
+			break;
+
+		rq = blkdev_entry_next_request(queue_head);
+
+		crq = rq->special;
+		assert(crq != NULL);
+		assert(crq->rq == rq);
+
+		crq->n_elem = 0;
+
+		DPRINTK("send req\n");
+		rc = carm_send_msg(host, crq);
+		if (rc) {
+			carm_push_q(host, q);
+			break;		/* call us again later, eventually */
+		} else
+			blkdev_dequeue_request(rq);
+	}
+
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+static int blk_rq_map_sg(request_queue_t *q, struct request *rq,
+			 struct scatterlist *sg)
+{
+	int n_elem = 0;
+	struct buffer_head *bh = rq->bh;
+	u64 last_phys = ~0ULL;
+
+	while (bh) {
+		if (bh_phys(bh) == last_phys) {
+			sg[n_elem - 1].length += bh->b_size;
+			last_phys += bh->b_size;
+		} else {
+			if (unlikely(n_elem == CARM_MAX_REQ_SG))
+				BUG();
+			sg[n_elem].page = bh->b_page;
+			sg[n_elem].length = bh->b_size;
+			sg[n_elem].offset = bh_offset(bh);
+			last_phys = bh_phys(bh) + bh->b_size;
+			n_elem++;
+		}
+
+		bh = bh->b_reqnext;
+	}
+
+	return n_elem;
+}
+
+static void carm_rw_tasklet(unsigned long _data)
+{
+	struct carm_port *port = (void *) _data;
+	struct carm_host *host = port->host;
+	request_queue_t *q = &port->q;
+	struct carm_msg_rw *msg;
+	struct carm_request *crq;
+	struct request *rq;
+	struct scatterlist *sg;
+	int writing = 0, pci_dir, i, n_elem, rc, have_work = 1;
+	u32 tmp;
+	unsigned int msg_size;
+	unsigned long flags;
+	struct list_head *queue_head = &q->queue_head;
+	unsigned long start_sector;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	if (q->plugged || list_empty(queue_head))
+		have_work = 0;
+
+	if (!have_work)
+		goto out;
+
+queue_one_request:
+	VPRINTK("get req\n");
+	if (list_empty(queue_head))
+		goto out;
+
+	rq = blkdev_entry_next_request(queue_head);
+
+	crq = carm_get_request(host);
+	if (!crq) {
+		carm_push_q(host, q);
+		goto out;	/* call us again later, eventually */
+	}
+	crq->rq = rq;
+
+	if (rq_data_dir(rq) == WRITE) {
+		writing = 1;
+		pci_dir = PCI_DMA_TODEVICE;
+	} else {
+		pci_dir = PCI_DMA_FROMDEVICE;
+	}
+
+	/* get scatterlist from block layer */
+	sg = &crq->sg[0];
+	n_elem = blk_rq_map_sg(q, rq, sg);
+	if (n_elem <= 0) {
+		carm_end_rq(host, crq, 0);
+		goto out;	/* request with no s/g entries? */
+	}
+
+	/* map scatterlist to PCI bus addresses */
+	n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
+	if (n_elem <= 0) {
+		carm_end_rq(host, crq, 0);
+		goto out;	/* request with no s/g entries? */
+	}
+	crq->n_elem = n_elem;
+	crq->port = port;
+	host->hw_sg_used += n_elem;
+
+	/*
+	 * build read/write message
+	 */
+
+	VPRINTK("build msg\n");
+	msg = (struct carm_msg_rw *) carm_ref_msg(host, crq->tag);
+
+	if (writing) {
+		msg->type = CARM_MSG_WRITE;
+		crq->msg_type = CARM_MSG_WRITE;
+	} else {
+		msg->type = CARM_MSG_READ;
+		crq->msg_type = CARM_MSG_READ;
+	}
+
+	start_sector = rq->sector;
+	start_sector += host->gendisk_hd[MINOR(rq->rq_dev)].start_sect;
+
+	msg->id		= port->port_no;
+	msg->sg_count	= n_elem;
+	msg->sg_type	= SGT_32BIT;
+	msg->handle	= cpu_to_le32(TAG_ENCODE(crq->tag));
+	msg->lba	= cpu_to_le32(start_sector & 0xffffffff);
+	tmp		= (start_sector >> 16) >> 16;
+	msg->lba_high	= cpu_to_le16( (u16) tmp );
+	msg->lba_count	= cpu_to_le16(rq->nr_sectors);
+
+	msg_size = sizeof(struct carm_msg_rw) - sizeof(msg->sg);
+	for (i = 0; i < n_elem; i++) {
+		struct carm_msg_sg *carm_sg = &msg->sg[i];
+		carm_sg->start = cpu_to_le32(sg_dma_address(&crq->sg[i]));
+		carm_sg->len = cpu_to_le32(sg_dma_len(&crq->sg[i]));
+		msg_size += sizeof(struct carm_msg_sg);
+	}
+
+	rc = carm_lookup_bucket(msg_size);
+	BUG_ON(rc < 0);
+	crq->msg_bucket = (u32) rc;
+
+	/*
+	 * queue read/write message to hardware
+	 */
+
+	VPRINTK("send msg, tag == %u\n", crq->tag);
+	rc = carm_send_msg(host, crq);
+	if (rc) {
+		carm_put_request(host, crq);
+		carm_push_q(host, q);
+		goto out;	/* call us again later, eventually */
+	} else
+		blkdev_dequeue_request(rq);
+
+	goto queue_one_request;
+
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+static void carm_handle_array_info(struct carm_host *host,
+				   struct carm_request *crq, u8 *mem,
+				   int is_ok)
+{
+	struct carm_port *port;
+	u8 *msg_data = mem + sizeof(struct carm_array_info);
+	struct carm_array_info *desc = (struct carm_array_info *) msg_data;
+	u64 lo, hi;
+	int cur_port;
+	size_t slen;
+
+	DPRINTK("ENTER\n");
+
+	carm_end_rq(host, crq, is_ok);
+
+	if (!is_ok)
+		goto out;
+	if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
+		goto out;
+
+	cur_port = host->cur_scan_dev;
+
+	/* should never occur */
+	if ((cur_port < 0) || (cur_port >= CARM_MAX_PORTS)) {
+		printk(KERN_ERR PFX "BUG: cur_scan_dev==%d, array_id==%d\n",
+		       cur_port, (int) desc->array_id);
+		goto out;
+	}
+
+	port = &host->port[cur_port];
+
+	lo = (u64) le32_to_cpu(desc->size);
+	hi = (u64) le32_to_cpu(desc->size_hi);
+
+	port->capacity = lo | (hi << 32);
+	port->dev_geom_head = le16_to_cpu(desc->head);
+	port->dev_geom_sect = le16_to_cpu(desc->sect);
+	port->dev_geom_cyl = le16_to_cpu(desc->cyl);
+
+	host->dev_active |= (1 << cur_port);
+
+	strncpy(port->name, desc->name, sizeof(port->name));
+	port->name[sizeof(port->name) - 1] = 0;
+	slen = strlen(port->name);
+	while (slen && (port->name[slen - 1] == ' ')) {
+		port->name[slen - 1] = 0;
+		slen--;
+	}
+
+	printk(KERN_INFO DRV_NAME "(%s): port %u device %Lu sectors\n",
+	       pci_name(host->pdev), port->port_no, port->capacity);
+	printk(KERN_INFO DRV_NAME "(%s): port %u device \"%s\"\n",
+	       pci_name(host->pdev), port->port_no, port->name);
+
+out:
+	assert(host->state == HST_DEV_SCAN);
+	schedule_task(&host->fsm_task);
+}
+
+static void carm_handle_scan_chan(struct carm_host *host,
+				  struct carm_request *crq, u8 *mem,
+				  int is_ok)
+{
+	u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
+	unsigned int i, dev_count = 0;
+	int new_state = HST_DEV_SCAN_START;
+
+	DPRINTK("ENTER\n");
+
+	carm_end_rq(host, crq, is_ok);
+
+	if (!is_ok) {
+		new_state = HST_ERROR;
+		goto out;
+	}
+
+	/* TODO: scan and support non-disk devices */
+	for (i = 0; i < 8; i++)
+		if (msg_data[i] == 0) { /* direct-access device (disk) */
+			host->dev_present |= (1 << i);
+			dev_count++;
+		}
+
+	printk(KERN_INFO DRV_NAME "(%s): found %u interesting devices\n",
+	       pci_name(host->pdev), dev_count);
+
+out:
+	assert(host->state == HST_PORT_SCAN);
+	host->state = new_state;
+	schedule_task(&host->fsm_task);
+}
+
+static void carm_handle_generic(struct carm_host *host,
+				struct carm_request *crq, int is_ok,
+				int cur_state, int next_state)
+{
+	DPRINTK("ENTER\n");
+
+	carm_end_rq(host, crq, is_ok);
+
+	assert(host->state == cur_state);
+	if (is_ok)
+		host->state = next_state;
+	else
+		host->state = HST_ERROR;
+	schedule_task(&host->fsm_task);
+}
+
+static inline void carm_handle_rw(struct carm_host *host,
+				  struct carm_request *crq, int is_ok)
+{
+	int pci_dir;
+
+	VPRINTK("ENTER\n");
+
+	if (rq_data_dir(crq->rq) == WRITE)
+		pci_dir = PCI_DMA_TODEVICE;
+	else
+		pci_dir = PCI_DMA_FROMDEVICE;
+
+	pci_unmap_sg(host->pdev, &crq->sg[0], crq->n_elem, pci_dir);
+
+	carm_end_rq(host, crq, is_ok);
+}
+
+static inline void carm_handle_resp(struct carm_host *host,
+				    u32 ret_handle_le, u32 status)
+{
+	u32 handle = le32_to_cpu(ret_handle_le);
+	unsigned int msg_idx;
+	struct carm_request *crq;
+	int is_ok = (status == RMSG_OK);
+	u8 *mem;
+
+	VPRINTK("ENTER, handle == 0x%x\n", handle);
+
+	if (unlikely(!TAG_VALID(handle))) {
+		printk(KERN_ERR DRV_NAME "(%s): BUG: invalid tag 0x%x\n",
+		       pci_name(host->pdev), handle);
+		return;
+	}
+
+	msg_idx = TAG_DECODE(handle);
+	VPRINTK("tag == %u\n", msg_idx);
+
+	crq = &host->req[msg_idx];
+
+	/* fast path */
+	if (likely(crq->msg_type == CARM_MSG_READ ||
+		   crq->msg_type == CARM_MSG_WRITE)) {
+		carm_handle_rw(host, crq, is_ok);
+		return;
+	}
+
+	mem = carm_ref_msg(host, msg_idx);
+
+	switch (crq->msg_type) {
+	case CARM_MSG_IOCTL: {
+		switch (crq->msg_subtype) {
+		case CARM_IOC_SCAN_CHAN:
+			carm_handle_scan_chan(host, crq, mem, is_ok);
+			break;
+		default:
+			/* unknown / invalid response */
+			goto err_out;
+		}
+		break;
+	}
+
+	case CARM_MSG_MISC: {
+		switch (crq->msg_subtype) {
+		case MISC_ALLOC_MEM:
+			carm_handle_generic(host, crq, is_ok,
+					    HST_ALLOC_BUF, HST_SYNC_TIME);
+			break;
+		case MISC_SET_TIME:
+			carm_handle_generic(host, crq, is_ok,
+					    HST_SYNC_TIME, HST_GET_FW_VER);
+			break;
+		case MISC_GET_FW_VER: {
+			struct carm_fw_ver *ver = (struct carm_fw_ver *)
+				mem + sizeof(struct carm_msg_get_fw_ver);
+			if (is_ok) {
+				host->fw_ver = le32_to_cpu(ver->version);
+				host->flags |= (ver->features & FL_FW_VER_MASK);
+			}
+			carm_handle_generic(host, crq, is_ok,
+					    HST_GET_FW_VER, HST_PORT_SCAN);
+			break;
+		}
+		default:
+			/* unknown / invalid response */
+			goto err_out;
+		}
+		break;
+	}
+
+	case CARM_MSG_ARRAY: {
+		switch (crq->msg_subtype) {
+		case CARM_ARRAY_INFO:
+			carm_handle_array_info(host, crq, mem, is_ok);
+			break;
+		default:
+			/* unknown / invalid response */
+			goto err_out;
+		}
+		break;
+	}
+
+	default:
+		/* unknown / invalid response */
+		goto err_out;
+	}
+
+	return;
+
+err_out:
+	printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
+	       pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
+	carm_end_rq(host, crq, 0);
+}
+
+static inline void carm_handle_responses(struct carm_host *host)
+{
+	void *mmio = host->mmio;
+	struct carm_response *resp = (struct carm_response *) host->shm;
+	unsigned int work = 0;
+	unsigned int idx = host->resp_idx % RMSG_Q_LEN;
+
+	while (1) {
+		u32 status = le32_to_cpu(resp[idx].status);
+
+		if (status == 0xffffffff) {
+			VPRINTK("ending response on index %u\n", idx);
+			writel(idx << 3, mmio + CARM_RESP_IDX);
+			break;
+		}
+
+		/* response to a message we sent */
+		else if ((status & (1 << 31)) == 0) {
+			VPRINTK("handling msg response on index %u\n", idx);
+			carm_handle_resp(host, resp[idx].ret_handle, status);
+			resp[idx].status = 0xffffffff;
+		}
+
+		/* asynchronous events the hardware throws our way */
+		else if ((status & 0xff000000) == (1 << 31)) {
+			u8 *evt_type_ptr = (u8 *) &resp[idx];
+			u8 evt_type = *evt_type_ptr;
+			printk(KERN_WARNING DRV_NAME "(%s): unhandled event type %d\n",
+			       pci_name(host->pdev), (int) evt_type);
+			resp[idx].status = 0xffffffff;
+		}
+
+		idx = NEXT_RESP(idx);
+		work++;
+	}
+
+	VPRINTK("EXIT, work==%u\n", work);
+	host->resp_idx += work;
+}
+
+static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
+{
+	struct carm_host *host = __host;
+	void *mmio;
+	u32 mask;
+	int handled = 0;
+	unsigned long flags;
+
+	if (!host) {
+		VPRINTK("no host\n");
+		return IRQ_NONE;
+	}
+
+	spin_lock_irqsave(&io_request_lock, flags);
+
+	mmio = host->mmio;
+
+	/* reading should also clear interrupts */
+	mask = readl(mmio + CARM_INT_STAT);
+
+	if (mask == 0 || mask == 0xffffffff) {
+		VPRINTK("no work, mask == 0x%x\n", mask);
+		goto out;
+	}
+
+	if (mask & INT_ACK_MASK)
+		writel(mask, mmio + CARM_INT_STAT);
+
+	if (unlikely(host->state == HST_INVALID)) {
+		VPRINTK("not initialized yet, mask = 0x%x\n", mask);
+		goto out;
+	}
+
+	if (mask & CARM_HAVE_RESP) {
+		handled = 1;
+		carm_handle_responses(host);
+	}
+
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	VPRINTK("EXIT\n");
+	return IRQ_RETVAL(handled);
+}
+
+static void carm_fsm_task (void *_data)
+{
+	struct carm_host *host = _data;
+	unsigned long flags;
+	unsigned int state;
+	int rc, i, next_dev;
+	int reschedule = 0;
+	int new_state = HST_INVALID;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	state = host->state;
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	DPRINTK("ENTER, state == %s\n", state_name[state]);
+
+	switch (state) {
+	case HST_PROBE_START:
+		new_state = HST_ALLOC_BUF;
+		reschedule = 1;
+		break;
+
+	case HST_ALLOC_BUF:
+		rc = carm_send_special(host, carm_fill_alloc_buf);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_SYNC_TIME:
+		rc = carm_send_special(host, carm_fill_sync_time);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_GET_FW_VER:
+		rc = carm_send_special(host, carm_fill_get_fw_ver);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_PORT_SCAN:
+		rc = carm_send_special(host, carm_fill_scan_channels);
+		if (rc) {
+			new_state = HST_ERROR;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_DEV_SCAN_START:
+		host->cur_scan_dev = -1;
+		new_state = HST_DEV_SCAN;
+		reschedule = 1;
+		break;
+
+	case HST_DEV_SCAN:
+		next_dev = -1;
+		for (i = host->cur_scan_dev + 1; i < CARM_MAX_PORTS; i++)
+			if (host->dev_present & (1 << i)) {
+				next_dev = i;
+				break;
+			}
+
+		if (next_dev >= 0) {
+			host->cur_scan_dev = next_dev;
+			rc = carm_array_info(host, next_dev);
+			if (rc) {
+				new_state = HST_ERROR;
+				reschedule = 1;
+			}
+		} else {
+			new_state = HST_DEV_ACTIVATE;
+			reschedule = 1;
+		}
+		break;
+
+	case HST_DEV_ACTIVATE: {
+		int activated = 0;
+		for (i = 0; i < CARM_MAX_PORTS; i++)
+			if (host->dev_active & (1 << i)) {
+				carm_activate_disk(host, &host->port[i]);
+				activated++;
+			}
+
+		printk(KERN_INFO DRV_NAME "(%s): %d ports activated\n",
+		       pci_name(host->pdev), activated);
+
+		new_state = HST_PROBE_FINISHED;
+		reschedule = 1;
+		break;
+	}
+
+	case HST_PROBE_FINISHED:
+		up(&host->probe_sem);
+		break;
+
+	case HST_ERROR:
+		/* FIXME: TODO */
+		break;
+
+	default:
+		/* should never occur */
+		printk(KERN_ERR PFX "BUG: unknown state %d\n", state);
+		assert(0);
+		break;
+	}
+
+	if (new_state != HST_INVALID) {
+		spin_lock_irqsave(&io_request_lock, flags);
+		host->state = new_state;
+		spin_unlock_irqrestore(&io_request_lock, flags);
+	}
+	if (reschedule)
+		schedule_task(&host->fsm_task);
+}
+
+static int carm_init_wait(void *mmio, u32 bits, unsigned int test_bit)
+{
+	unsigned int i;
+
+	for (i = 0; i < 50000; i++) {
+		u32 tmp = readl(mmio + CARM_LMUC);
+		udelay(100);
+
+		if (test_bit) {
+			if ((tmp & bits) == bits)
+				return 0;
+		} else {
+			if ((tmp & bits) == 0)
+				return 0;
+		}
+
+		cond_resched();
+	}
+
+	printk(KERN_ERR PFX "carm_init_wait timeout, bits == 0x%x, test_bit == %s\n",
+	       bits, test_bit ? "yes" : "no");
+	return -EBUSY;
+}
+
+static void carm_init_responses(struct carm_host *host)
+{
+	void *mmio = host->mmio;
+	unsigned int i;
+	struct carm_response *resp = (struct carm_response *) host->shm;
+
+	for (i = 0; i < RMSG_Q_LEN; i++)
+		resp[i].status = 0xffffffff;
+
+	writel(0, mmio + CARM_RESP_IDX);
+}
+
+static int carm_init_host(struct carm_host *host)
+{
+	void *mmio = host->mmio;
+	u32 tmp;
+	u8 tmp8;
+	int rc;
+	unsigned long flags;
+
+	DPRINTK("ENTER\n");
+
+	writel(0, mmio + CARM_INT_MASK);
+
+	tmp8 = readb(mmio + CARM_INITC);
+	if (tmp8 & 0x01) {
+		tmp8 &= ~0x01;
+		writeb(tmp8, CARM_INITC);
+		readb(mmio + CARM_INITC);	/* flush */
+
+		DPRINTK("snooze...\n");
+		msleep(5000);
+	}
+
+	tmp = readl(mmio + CARM_HMUC);
+	if (tmp & CARM_CME) {
+		DPRINTK("CME bit present, waiting\n");
+		rc = carm_init_wait(mmio, CARM_CME, 1);
+		if (rc) {
+			DPRINTK("EXIT, carm_init_wait 1 failed\n");
+			return rc;
+		}
+	}
+	if (tmp & CARM_RME) {
+		DPRINTK("RME bit present, waiting\n");
+		rc = carm_init_wait(mmio, CARM_RME, 1);
+		if (rc) {
+			DPRINTK("EXIT, carm_init_wait 2 failed\n");
+			return rc;
+		}
+	}
+
+	tmp &= ~(CARM_RME | CARM_CME);
+	writel(tmp, mmio + CARM_HMUC);
+	readl(mmio + CARM_HMUC);	/* flush */
+
+	rc = carm_init_wait(mmio, CARM_RME | CARM_CME, 0);
+	if (rc) {
+		DPRINTK("EXIT, carm_init_wait 3 failed\n");
+		return rc;
+	}
+
+	carm_init_buckets(mmio);
+
+	writel(host->shm_dma & 0xffffffff, mmio + RBUF_ADDR_LO);
+	writel((host->shm_dma >> 16) >> 16, mmio + RBUF_ADDR_HI);
+	writel(RBUF_LEN, mmio + RBUF_BYTE_SZ);
+
+	tmp = readl(mmio + CARM_HMUC);
+	tmp |= (CARM_RME | CARM_CME | CARM_WZBC);
+	writel(tmp, mmio + CARM_HMUC);
+	readl(mmio + CARM_HMUC);	/* flush */
+
+	rc = carm_init_wait(mmio, CARM_RME | CARM_CME, 1);
+	if (rc) {
+		DPRINTK("EXIT, carm_init_wait 4 failed\n");
+		return rc;
+	}
+
+	writel(0, mmio + CARM_HMPHA);
+	writel(INT_DEF_MASK, mmio + CARM_INT_MASK);
+
+	carm_init_responses(host);
+
+	/* start initialization, probing state machine */
+	spin_lock_irqsave(&io_request_lock, flags);
+	assert(host->state == HST_INVALID);
+	host->state = HST_PROBE_START;
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	schedule_task(&host->fsm_task);
+
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
+static void carm_init_ports (struct carm_host *host)
+{
+	struct carm_port *port;
+	request_queue_t *q;
+	unsigned int i;
+
+	for (i = 0; i < CARM_MAX_PORTS; i++) {
+		port = &host->port[i];
+		port->magic = CARM_MAGIC_PORT;
+		port->host = host;
+		port->port_no = i;
+		tasklet_init(&port->tasklet, carm_rw_tasklet,
+			     (unsigned long) port);
+
+		q = &port->q;
+
+		blk_init_queue(q, carm_rq_fn);
+		q->queuedata = port;
+		blk_queue_bounce_limit(q, host->pdev->dma_mask);
+		blk_queue_headactive(q, 0);
+
+		q->back_merge_fn = carm_back_merge_fn;
+		q->front_merge_fn = carm_front_merge_fn;
+		q->merge_requests_fn = carm_merge_requests_fn;
+	}
+}
+
+static request_queue_t *carm_find_queue(kdev_t device)
+{
+	struct carm_host *host;
+
+	host = blk_dev[MAJOR(device)].data;
+	if (!host)
+		return NULL;
+	if (host->magic != CARM_MAGIC_HOST)
+		return NULL;
+
+	DPRINTK("match: major %d, minor %d\n",
+		MAJOR(device), MINOR(device));
+	return &host->port[MINOR(device) >> CARM_PART_SHIFT].q;
+}
+
+static int carm_init_disks(struct carm_host *host)
+{
+	host->gendisk.major = host->major;
+	host->gendisk.major_name = host->name;
+	host->gendisk.minor_shift = CARM_PART_SHIFT;
+	host->gendisk.max_p = CARM_MINORS_PER_MAJOR;
+	host->gendisk.part = host->gendisk_hd;
+	host->gendisk.sizes = host->blk_sizes;
+	host->gendisk.nr_real = CARM_MAX_PORTS;
+	host->gendisk.fops = &carm_bd_ops;
+
+	blk_dev[host->major].queue = carm_find_queue;
+	blk_dev[host->major].data = host;
+	blk_size[host->major] = host->blk_sizes;
+	blksize_size[host->major] = host->blk_block_sizes;
+	hardsect_size[host->major] = host->blk_sect_sizes;
+
+	add_gendisk(&host->gendisk);
+
+	return 0;
+}
+
+static void carm_free_disks(struct carm_host *host)
+{
+	unsigned int i;
+
+	del_gendisk(&host->gendisk);
+
+	for (i = 0; i < CARM_MAX_PORTS; i++) {
+		struct carm_port *port = &host->port[i];
+
+		blk_cleanup_queue(&port->q);
+	}
+
+	blk_dev[host->major].queue = NULL;
+	blk_dev[host->major].data = NULL;
+	blk_size[host->major] = NULL;
+	blksize_size[host->major] = NULL;
+	hardsect_size[host->major] = NULL;
+}
+
+static void carm_stop_tasklets(struct carm_host *host)
+{
+	unsigned int i;
+
+	tasklet_kill(&host->oob_tasklet);
+
+	for (i = 0; i < CARM_MAX_PORTS; i++) {
+		struct carm_port *port = &host->port[i];
+		tasklet_kill(&port->tasklet);
+	}
+}
+
+static int carm_init_shm(struct carm_host *host)
+{
+	host->shm = pci_alloc_consistent(host->pdev, CARM_SHM_SIZE,
+					 &host->shm_dma);
+	if (!host->shm)
+		return -ENOMEM;
+
+	host->msg_base = host->shm + RBUF_LEN;
+	host->msg_dma = host->shm_dma + RBUF_LEN;
+
+	memset(host->shm, 0xff, RBUF_LEN);
+	memset(host->msg_base, 0, PDC_SHM_SIZE - RBUF_LEN);
+
+	return 0;
+}
+
+static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static unsigned int printed_version;
+	struct carm_host *host;
+	unsigned int pci_dac;
+	int rc;
+	unsigned int i;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
+	rc = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+	if (!rc) {
+		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+		if (rc) {
+			printk(KERN_ERR DRV_NAME "(%s): consistent DMA mask failure\n",
+				pci_name(pdev));
+			goto err_out_regions;
+		}
+		pci_dac = 1;
+	} else {
+#endif
+		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
+		if (rc) {
+			printk(KERN_ERR DRV_NAME "(%s): DMA mask failure\n",
+				pci_name(pdev));
+			goto err_out_regions;
+		}
+		pci_dac = 0;
+#if IF_64BIT_DMA_IS_POSSIBLE /* grrrr... */
+	}
+#endif
+
+	host = kmalloc(sizeof(*host), GFP_KERNEL);
+	if (!host) {
+		printk(KERN_ERR DRV_NAME "(%s): memory alloc failure\n",
+		       pci_name(pdev));
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(host, 0, sizeof(*host));
+	host->magic = CARM_MAGIC_HOST;
+	host->pdev = pdev;
+	host->flags = pci_dac ? FL_DAC : 0;
+	INIT_TQUEUE(&host->fsm_task, carm_fsm_task, host);
+	INIT_LIST_HEAD(&host->host_list_node);
+	init_MUTEX_LOCKED(&host->probe_sem);
+	tasklet_init(&host->oob_tasklet, carm_oob_tasklet,
+		     (unsigned long) host);
+	carm_init_ports(host);
+
+	for (i = 0; i < ARRAY_SIZE(host->req); i++)
+		host->req[i].tag = i;
+
+	host->mmio = ioremap(pci_resource_start(pdev, 0),
+			     pci_resource_len(pdev, 0));
+	if (!host->mmio) {
+		printk(KERN_ERR DRV_NAME "(%s): MMIO alloc failure\n",
+		       pci_name(pdev));
+		rc = -ENOMEM;
+		goto err_out_kfree;
+	}
+
+	rc = carm_init_shm(host);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME "(%s): DMA SHM alloc failure\n",
+		       pci_name(pdev));
+		goto err_out_iounmap;
+	}
+
+	blk_init_queue(&host->oob_q, carm_oob_rq_fn);
+	host->oob_q.queuedata = host;
+	blk_queue_bounce_limit(&host->oob_q, pdev->dma_mask);
+	blk_queue_headactive(&host->oob_q, 0);
+
+	/*
+	 * Figure out which major to use: 160, 161, or dynamic
+	 */
+	if (!test_and_set_bit(0, &carm_major_alloc))
+		host->major = 160;
+	else if (!test_and_set_bit(1, &carm_major_alloc))
+		host->major = 161;
+	else
+		host->flags |= FL_DYN_MAJOR;
+
+	host->id = carm_host_id;
+	sprintf(host->name, DRV_NAME "%d", carm_host_id);
+
+	rc = register_blkdev(host->major, host->name, &carm_bd_ops);
+	if (rc < 0)
+		goto err_out_free_majors;
+	if (host->flags & FL_DYN_MAJOR)
+		host->major = rc;
+
+	rc = carm_init_disks(host);
+	if (rc)
+		goto err_out_blkdev_disks;
+
+	pci_set_master(pdev);
+
+	rc = request_irq(pdev->irq, carm_interrupt, SA_SHIRQ, DRV_NAME, host);
+	if (rc) {
+		printk(KERN_ERR DRV_NAME "(%s): irq alloc failure\n",
+		       pci_name(pdev));
+		goto err_out_blkdev_disks;
+	}
+
+	rc = carm_init_host(host);
+	if (rc)
+		goto err_out_free_irq;
+
+	DPRINTK("waiting for probe_sem\n");
+	down(&host->probe_sem);
+
+	printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n",
+	       host->name, pci_name(pdev), (int) CARM_MAX_PORTS,
+	       pci_resource_start(pdev, 0), pdev->irq, host->major);
+
+	carm_host_id++;
+	pci_set_drvdata(pdev, host);
+	return 0;
+
+err_out_free_irq:
+	free_irq(pdev->irq, host);
+err_out_blkdev_disks:
+	carm_free_disks(host);
+	unregister_blkdev(host->major, host->name);
+err_out_free_majors:
+	if (host->major == 160)
+		clear_bit(0, &carm_major_alloc);
+	else if (host->major == 161)
+		clear_bit(1, &carm_major_alloc);
+	blk_cleanup_queue(&host->oob_q);
+	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
+err_out_iounmap:
+	iounmap(host->mmio);
+err_out_kfree:
+	kfree(host);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static void carm_remove_one (struct pci_dev *pdev)
+{
+	struct carm_host *host = pci_get_drvdata(pdev);
+
+	if (!host) {
+		printk(KERN_ERR PFX "BUG: no host data for PCI(%s)\n",
+		       pci_name(pdev));
+		return;
+	}
+
+	free_irq(pdev->irq, host);
+	carm_stop_tasklets(host);
+	carm_free_disks(host);
+	unregister_blkdev(host->major, host->name);
+	if (host->major == 160)
+		clear_bit(0, &carm_major_alloc);
+	else if (host->major == 161)
+		clear_bit(1, &carm_major_alloc);
+	blk_cleanup_queue(&host->oob_q);
+	pci_free_consistent(pdev, CARM_SHM_SIZE, host->shm, host->shm_dma);
+	iounmap(host->mmio);
+	kfree(host);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static int __init carm_init(void)
+{
+	return pci_module_init(&carm_driver);
+}
+
+static void __exit carm_exit(void)
+{
+	pci_unregister_driver(&carm_driver);
+}
+
+module_init(carm_init);
+module_exit(carm_exit);
+
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/Makefile.lib linux-2.4.27-rc4/drivers/bluetooth/Makefile.lib
--- linux-2.4.26/drivers/bluetooth/Makefile.lib	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/Makefile.lib	2004-07-30 16:28:37.000000000 +0000
@@ -1 +1,2 @@
-obj-$(CONFIG_BLUEZ_HCIBFUSB) += firmware_class.o
+obj-$(CONFIG_BLUEZ_HCIBFUSB)	+= firmware_class.o
+obj-$(CONFIG_BLUEZ_HCIBT3C)	+= firmware_class.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/bfusb.c linux-2.4.27-rc4/drivers/bluetooth/bfusb.c
--- linux-2.4.26/drivers/bluetooth/bfusb.c	2003-11-28 18:26:19.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/bfusb.c	2004-07-30 16:25:26.000000000 +0000
@@ -359,11 +359,11 @@ static void bfusb_rx_complete(struct urb
 
 	BT_DBG("bfusb %p urb %p skb %p len %d", bfusb, urb, skb, skb->len);
 
-	if (!test_bit(HCI_RUNNING, &bfusb->hdev.flags))
-		return;
-
 	read_lock(&bfusb->lock);
 
+	if (!test_bit(HCI_RUNNING, &bfusb->hdev.flags))
+		goto unlock;
+
 	if (urb->status || !count)
 		goto resubmit;
 
@@ -414,6 +414,7 @@ resubmit:
 					bfusb->hdev.name, urb, err);
 	}
 
+unlock:
 	read_unlock(&bfusb->lock);
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/bt3c_cs.c linux-2.4.27-rc4/drivers/bluetooth/bt3c_cs.c
--- linux-2.4.26/drivers/bluetooth/bt3c_cs.c	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/bt3c_cs.c	2004-07-30 16:27:32.000000000 +0000
@@ -24,8 +24,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#define __KERNEL_SYSCALLS__
-
 #include <linux/kernel.h>
 #include <linux/kmod.h>
 #include <linux/init.h>
@@ -48,6 +46,8 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 
+#include <linux/firmware.h>
+
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
@@ -485,78 +485,101 @@ static int bt3c_hci_ioctl(struct hci_dev
 
 
 
-/* ======================== User mode firmware loader ======================== */
+/* ======================== Card services HCI interaction ======================== */
 
 
-#define FW_LOADER  "/sbin/bluefw"
-static int errno;
+static int bt3c_load_firmware(bt3c_info_t *info, unsigned char *firmware, int count)
+{
+	char *ptr = (char *) firmware;
+	char b[9];
+	unsigned int iobase, size, addr, fcs, tmp;
+	int i, err = 0;
 
+	iobase = info->link.io.BasePort1;
 
-static int bt3c_fw_loader_exec(void *dev)
-{
-	char *argv[] = { FW_LOADER, "pccard", dev, NULL };
-	char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
-	int err;
+	/* Reset */
 
-	err = exec_usermodehelper(FW_LOADER, argv, envp);
-	if (err)
-		printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev);
+	bt3c_io_write(iobase, 0x8040, 0x0404);
+	bt3c_io_write(iobase, 0x8040, 0x0400);
 
-	return err;
-}
+	udelay(1);
 
+	bt3c_io_write(iobase, 0x8040, 0x0404);
 
-static int bt3c_firmware_load(bt3c_info_t *info)
-{
-	sigset_t tmpsig;
-	char dev[16];
-	pid_t pid;
-	int result;
+	udelay(17);
 
-	/* Check if root fs is mounted */
-	if (!current->fs->root) {
-		printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n");
-		return -EPERM;
-	}
+	/* Load */
 
-	sprintf(dev, "%04x", info->link.io.BasePort1);
+	while (count) {
+		if (ptr[0] != 'S') {
+			printk(KERN_WARNING "bt3c_cs: Bad address in firmware.\n");
+			err = -EFAULT;
+			goto error;
+		}
 
-	pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0);
-	if (pid < 0) {
-		printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid);
-		return pid;
-	}
+		memset(b, 0, sizeof(b));
+		memcpy(b, ptr + 2, 2);
+		size = simple_strtol(b, NULL, 16);
+
+		memset(b, 0, sizeof(b));
+		memcpy(b, ptr + 4, 8);
+		addr = simple_strtol(b, NULL, 16);
+
+		memset(b, 0, sizeof(b));
+		memcpy(b, ptr + (size * 2) + 2, 2);
+		fcs = simple_strtol(b, NULL, 16);
+
+		memset(b, 0, sizeof(b));
+		for (tmp = 0, i = 0; i < size; i++) {
+			memcpy(b, ptr + (i * 2) + 2, 2);
+			tmp += simple_strtol(b, NULL, 16);
+		}
 
-	/* Block signals, everything but SIGKILL/SIGSTOP */
-	spin_lock_irq(&current->sigmask_lock);
-	tmpsig = current->blocked;
-	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+		if (((tmp + fcs) & 0xff) != 0xff) {
+			printk(KERN_WARNING "bt3c_cs: Checksum error in firmware.\n");
+			err = -EILSEQ;
+			goto error;
+		}
 
-	result = waitpid(pid, NULL, __WCLONE);
+		if (ptr[1] == '3') {
+			bt3c_address(iobase, addr);
 
-	/* Allow signals again */
-	spin_lock_irq(&current->sigmask_lock);
-	current->blocked = tmpsig;
-	recalc_sigpending(current);
-	spin_unlock_irq(&current->sigmask_lock);
+			memset(b, 0, sizeof(b));
+			for (i = 0; i < (size - 4) / 2; i++) {
+				memcpy(b, ptr + (i * 4) + 12, 4);
+				tmp = simple_strtol(b, NULL, 16);
+				bt3c_put(iobase, tmp);
+			}
+		}
 
-	if (result != pid) {
-		printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result);
-		return -result;
+		ptr   += (size * 2) + 6;
+		count -= (size * 2) + 6;
 	}
 
-	return 0;
-}
+	udelay(17);
 
+	/* Boot */
 
+	bt3c_address(iobase, 0x3000);
+	outb(inb(iobase + CONTROL) | 0x40, iobase + CONTROL);
 
-/* ======================== Card services HCI interaction ======================== */
+error:
+	udelay(17);
+
+	/* Clear */
+
+	bt3c_io_write(iobase, 0x7006, 0x0000);
+	bt3c_io_write(iobase, 0x7005, 0x0000);
+	bt3c_io_write(iobase, 0x7001, 0x0000);
+
+	return err;
+}
 
 
 int bt3c_open(bt3c_info_t *info)
 {
+	const struct firmware *firmware;
+	char device[16];
 	struct hci_dev *hdev;
 	int err;
 
@@ -570,8 +593,22 @@ int bt3c_open(bt3c_info_t *info)
 
 	/* Load firmware */
 
-	if ((err = bt3c_firmware_load(info)) < 0)
+	snprintf(device, sizeof(device), "bt3c%4.4x", info->link.io.BasePort1);
+
+	err = request_firmware(&firmware, "BT3CPCC.bin", device);
+	if (err < 0) {
+		printk(KERN_WARNING "bt3c_cs: Firmware request failed.\n");
+		return err;
+	}
+
+	err = bt3c_load_firmware(info, firmware->data, firmware->size);
+
+	release_firmware(firmware);
+
+	if (err < 0) {
+		printk(KERN_WARNING "bt3c_cs: Firmware loading failed.\n");
 		return err;
+	}
 
 	/* Timeout before it is safe to send the first HCI packet */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/hci_bcsp.c linux-2.4.27-rc4/drivers/bluetooth/hci_bcsp.c
--- linux-2.4.26/drivers/bluetooth/hci_bcsp.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/hci_bcsp.c	2004-07-30 16:27:12.000000000 +0000
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 
 #include <linux/version.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/hci_ldisc.c linux-2.4.27-rc4/drivers/bluetooth/hci_ldisc.c
--- linux-2.4.26/drivers/bluetooth/hci_ldisc.c	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/hci_ldisc.c	2004-07-30 16:30:59.000000000 +0000
@@ -33,7 +33,6 @@
 #include <linux/module.h>
 
 #include <linux/version.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/hci_uart.h linux-2.4.27-rc4/drivers/bluetooth/hci_uart.h
--- linux-2.4.26/drivers/bluetooth/hci_uart.h	2003-06-13 14:51:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/hci_uart.h	2004-07-30 16:29:11.000000000 +0000
@@ -35,11 +35,12 @@
 #define HCIUARTGETPROTO	_IOR('U', 201, int)
 
 /* UART protocols */
-#define HCI_UART_MAX_PROTO	3
+#define HCI_UART_MAX_PROTO	4
 
 #define HCI_UART_H4	0
 #define HCI_UART_BCSP	1
-#define HCI_UART_NCSP	2
+#define HCI_UART_3WIRE	2
+#define HCI_UART_H4DS	3
 
 #ifdef __KERNEL__
 struct hci_uart;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/hci_usb.c linux-2.4.27-rc4/drivers/bluetooth/hci_usb.c
--- linux-2.4.26/drivers/bluetooth/hci_usb.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/hci_usb.c	2004-07-30 16:31:29.000000000 +0000
@@ -30,7 +30,7 @@
  *
  * $Id: hci_usb.c,v 1.8 2002/07/18 17:23:09 maxk Exp $    
  */
-#define VERSION "2.5"
+#define VERSION "2.6"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -76,14 +76,15 @@ static struct usb_device_id bluetooth_id
 	/* AVM BlueFRITZ! USB v2.0 */
 	{ USB_DEVICE(0x057c, 0x3800) },
 
-	/* Ericsson with non-standard id */
-	{ USB_DEVICE(0x0bdb, 0x1002) },
+	/* Bluetooth Ultraport Module from IBM */
+	{ USB_DEVICE(0x04bf, 0x030a) },
 
-	/* ALPS Module with non-standard id */
+	/* ALPS Modules with non-standard id */
+	{ USB_DEVICE(0x044e, 0x3001) },
 	{ USB_DEVICE(0x044e, 0x3002) },
 
-	/* Bluetooth Ultraport Module from IBM */
-	{ USB_DEVICE(0x04bf, 0x030a) },
+	/* Ericsson with non-standard id */
+	{ USB_DEVICE(0x0bdb, 0x1002) },
 
 	{ }	/* Terminating entry */
 };
@@ -100,6 +101,9 @@ static struct usb_device_id blacklist_id
 	/* Digianswer device */
 	{ USB_DEVICE(0x08fd, 0x0001), driver_info: HCI_DIGIANSWER },
 
+	/* RTX Telecom based adapter with buggy SCO support */
+	{ USB_DEVICE(0x0400, 0x0807), driver_info: HCI_BROKEN_ISOC },
+
 	{ }	/* Terminating entry */
 };
 
@@ -699,11 +703,11 @@ static void hci_usb_rx_complete(struct u
 	BT_DBG("%s urb %p type %d status %d count %d flags %x", hdev->name, urb,
 			_urb->type, urb->status, count, urb->transfer_flags);
 
-	if (!test_bit(HCI_RUNNING, &hdev->flags))
-		return;
-
 	read_lock(&husb->completion_lock);
 
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		goto unlock;
+
 	if (urb->status || !count)
 		goto resubmit;
 
@@ -740,6 +744,8 @@ resubmit:
 		BT_DBG("%s urb %p type %d resubmit status %d", hdev->name, urb,
 				_urb->type, err);
 	}
+
+unlock:
 	read_unlock(&husb->completion_lock);
 }
 
@@ -876,7 +882,7 @@ static void *hci_usb_probe(struct usb_de
 	}
 
 #ifdef CONFIG_BLUEZ_HCIUSB_SCO
-	if (!isoc_in_ep[1] || !isoc_out_ep[1]) {
+	if (id->driver_info & HCI_BROKEN_ISOC || !isoc_in_ep[1] || !isoc_out_ep[1]) {
 		BT_DBG("Isoc endpoints not found");
 		isoc_iface = NULL;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/bluetooth/hci_usb.h linux-2.4.27-rc4/drivers/bluetooth/hci_usb.h
--- linux-2.4.26/drivers/bluetooth/hci_usb.h	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/bluetooth/hci_usb.h	2004-07-30 16:29:20.000000000 +0000
@@ -40,6 +40,7 @@
 #define HCI_IGNORE           0x01
 #define HCI_RESET            0x02
 #define HCI_DIGIANSWER       0x04
+#define HCI_BROKEN_ISOC      0x08
 
 #define HCI_MAX_IFACE_NUM	3 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/cdrom/cdrom.c linux-2.4.27-rc4/drivers/cdrom/cdrom.c
--- linux-2.4.26/drivers/cdrom/cdrom.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/cdrom/cdrom.c	2004-07-30 16:26:03.000000000 +0000
@@ -1,7 +1,8 @@
 /* linux/drivers/cdrom/cdrom.c. 
    Copyright (c) 1996, 1997 David A. van Leeuwen.
    Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
-   Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk>
+   Copyright (c) 1998-2004 Jens Axboe <axboe@image.dk>
+   Copyright (c) 2004, Iomega Corp.
 
    May be copied or modified under the terms of the GNU General Public
    License.  See linux/COPYING for more information.
@@ -447,6 +448,100 @@ struct cdrom_device_info *cdrom_find_dev
 	return cdi;
 }
 
+int cdrom_get_random_writable(struct cdrom_device_info *cdi,
+			      struct rwrt_feature_desc *rfd)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[24];
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;	/* often 0x46 */
+	cgc.cmd[3] = CDF_RWRT;			/* often 0x0020 */
+	cgc.cmd[8] = sizeof(buffer);		/* often 0x18 */
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+		return ret;
+
+	memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
+	return 0;
+}
+
+int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
+{
+	struct cdrom_generic_command cgc;
+	char buffer[16];
+	__u16 *feature_code;
+	int ret;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+	cgc.cmd[3] = CDF_HWDM;
+	cgc.cmd[8] = sizeof(buffer);
+	cgc.quiet = 1;
+
+	if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
+		return ret;
+
+	feature_code = (__u16 *) &buffer[sizeof(struct feature_header)];
+	if (be16_to_cpu(*feature_code) == CDF_HWDM)
+		return 0;
+
+	return 1;
+}
+
+
+int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	*write = 0;
+
+	if ((ret = cdrom_get_random_writable(cdi, &rfd)))
+		return ret;
+
+	if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
+		*write = 1;
+
+	return 0;
+}
+
+static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
+{
+	struct rwrt_feature_desc rfd;
+	int ret;
+
+	if ((ret = cdrom_has_defect_mgt(cdi)))
+		return ret;
+	else
+		if ((ret = cdrom_get_random_writable(cdi, &rfd)))
+			return ret;
+		else if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
+			ret = !rfd.curr;
+
+	cdinfo(CD_OPEN, "can open for random write\n");
+	return ret;
+}
+
+/*
+ * returns 0 for ok to open write, non-0 to disallow
+ */
+static int cdrom_open_write(struct cdrom_device_info *cdi)
+{
+	int ret;
+	if (CDROM_CAN(CDC_RAM) &&
+	    !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R)) 
+		ret = cdrom_ram_open_write(cdi);
+	else
+		ret = 1;
+
+	return ret;
+}
+
 /* We use the open-option O_NONBLOCK to indicate that the
  * purpose of opening is only for subsequent ioctl() calls; no device
  * integrity checks are performed.
@@ -465,8 +560,15 @@ int cdrom_open(struct inode *ip, struct 
 	if ((cdi = cdrom_find_device(dev)) == NULL)
 		return -ENODEV;
 
-	if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM))
-		return -EROFS;
+	cdi->use_count++;
+	ret = -EROFS;
+	if (fp->f_mode & FMODE_WRITE) {
+		/* printk("cdrom: %s opening for WRITE\n", current->comm); */
+		if (!CDROM_CAN(CDC_RAM))
+			goto out;
+		if (cdrom_open_write(cdi))
+			goto out;
+	}
 
 	/* if this was a O_NONBLOCK open and we should honor the flags,
 	 * do a quick open without drive/disc integrity checks. */
@@ -475,12 +577,13 @@ int cdrom_open(struct inode *ip, struct 
 	else
 		ret = open_for_data(cdi);
 
-	if (!ret) cdi->use_count++;
-
 	cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
 	/* Do this on open.  Don't wait for mount, because they might
 	    not be mounting, but opening with O_NONBLOCK */
 	check_disk_change(dev);
+out:
+	if (ret)
+		cdi->use_count--;
 	return ret;
 }
 
@@ -657,15 +760,14 @@ int cdrom_release(struct inode *ip, stru
 
 	cdinfo(CD_CLOSE, "entering cdrom_release\n"); 
 
-	if (cdi->use_count > 0)
-		cdi->use_count--;
-	if (cdi->use_count == 0)
+	if (!--cdi->use_count) {
 		cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
-	if (cdi->use_count == 0 &&
-	    cdo->capability & CDC_LOCK && !keeplocked) {
-		cdinfo(CD_CLOSE, "Unlocking door!\n");
-		cdo->lock_door(cdi, 0);
+		if ((cdo->capability & CDC_LOCK) && !keeplocked) {
+			cdinfo(CD_CLOSE, "Unlocking door!\n");
+			cdo->lock_door(cdi, 0);
+		}
 	}
+
 	opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
 		!(fp && fp->f_flags & O_NONBLOCK);
 	cdo->release(cdi);
@@ -1909,10 +2011,24 @@ static int cdrom_do_cmd(struct cdrom_dev
 		}
 	}
 
+	/*
+	 * queue command and wait for it to complete
+	 */
 	ret = cdi->ops->generic_packet(cdi, cgc);
-	__copy_to_user(usense, cgc->sense, sizeof(*usense));
+
+	/*
+	 * always copy back sense, command need not have failed for it to
+	 * contain useful info
+	 */
+	if (usense)
+		__copy_to_user(usense, cgc->sense, sizeof(*usense));
+
+	/*
+	 * this really needs to be modified to copy back good bytes
+	 */
 	if (!ret && cgc->data_direction == CGC_DATA_READ)
 		__copy_to_user(ubuf, cgc->buffer, cgc->buflen);
+
 	if (cgc->data_direction == CGC_DATA_READ ||
 	    cgc->data_direction == CGC_DATA_WRITE) {
 		kfree(cgc->buffer);
@@ -2392,6 +2508,7 @@ EXPORT_SYMBOL(cdrom_mode_select);
 EXPORT_SYMBOL(cdrom_mode_sense);
 EXPORT_SYMBOL(init_cdrom_command);
 EXPORT_SYMBOL(cdrom_find_device);
+EXPORT_SYMBOL(cdrom_is_random_writable);
 
 #ifdef CONFIG_SYSCTL
 
@@ -2488,6 +2605,10 @@ int cdrom_sysctl_info(ctl_table *ctl, in
 	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
 	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0);
 
+	pos += sprintf(info+pos, "\nCan write RAM:\t");
+	for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
+	    pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_RAM) != 0);
+
 	strcpy(info+pos,"\n\n");
 		
         return proc_dostring(ctl, write, filp, buffer, lenp);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/ChangeLog linux-2.4.27-rc4/drivers/char/ChangeLog
--- linux-2.4.26/drivers/char/ChangeLog	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/ChangeLog	2004-07-30 16:29:00.000000000 +0000
@@ -1,3 +1,8 @@
+2002-09-21  Marek Michalkiewicz  <marekm@amelek.gda.pl>
+
+	* parport_serial.c: Move from ../parport/ here, must be initialised
+	after serial.c for register_serial to work.
+
 2001-08-11  Tim Waugh  <twaugh@redhat.com>
 
 	* serial.c (get_pci_port): Deal with awkward Titan cards.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/Config.in linux-2.4.27-rc4/drivers/char/Config.in
--- linux-2.4.26/drivers/char/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/Config.in	2004-07-30 16:26:26.000000000 +0000
@@ -273,7 +273,6 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
    if [ "$CONFIG_SGI_IP22" = "y" ]; then
       dep_tristate '  Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22
    fi
-   dep_tristate '  AMD 766/768 TCO Timer/Watchdog' CONFIG_AMD7XX_TCO $CONFIG_EXPERIMENTAL
    if [ "$CONFIG_8xx" = "y" ]; then
       tristate '  MPC8xx Watchdog Timer' CONFIG_8xx_WDT
    fi
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/Makefile linux-2.4.27-rc4/drivers/char/Makefile
--- linux-2.4.26/drivers/char/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/Makefile	2004-07-30 16:31:38.000000000 +0000
@@ -171,6 +171,7 @@ endif
 
 obj-$(CONFIG_VT) += vt.o vc_screen.o consolemap.o consolemap_deftbl.o $(CONSOLE) selection.o
 obj-$(CONFIG_SERIAL) += $(SERIAL)
+obj-$(CONFIG_PARPORT_SERIAL) += parport_serial.o
 obj-$(CONFIG_SERIAL_HCDP) += hcdp_serial.o
 obj-$(CONFIG_SERIAL_21285) += serial_21285.o
 obj-$(CONFIG_SERIAL_SA1100) += serial_sa1100.o
@@ -320,7 +321,6 @@ obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
 obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
-obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o
 obj-$(CONFIG_INDYDOG) += indydog.o
 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/agp/agp.h linux-2.4.27-rc4/drivers/char/agp/agp.h
--- linux-2.4.26/drivers/char/agp/agp.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/agp/agp.h	2004-07-30 16:27:50.000000000 +0000
@@ -316,6 +316,9 @@ struct agp_bridge_data {
 #ifndef PCI_DEVICE_ID_ATI_RS200
 #define PCI_DEVICE_ID_ATI_RS200		0xcab2
 #endif
+#ifndef PCI_DEVICE_ID_ATI_RS200_REV2
+#define PCI_DEVICE_ID_ATI_RS200_REV2	0xcbb2
+#endif
 #ifndef PCI_DEVICE_ID_ATI_RS250
 #define PCI_DEVICE_ID_ATI_RS250		0xcab3
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/agp/agpgart_be.c linux-2.4.27-rc4/drivers/char/agp/agpgart_be.c
--- linux-2.4.26/drivers/char/agp/agpgart_be.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/agp/agpgart_be.c	2004-07-30 16:26:01.000000000 +0000
@@ -5738,6 +5738,7 @@ static int ati_create_gatt_table(void)
 
 	if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) ||
+	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_REV2) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_B) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) {
 		pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp);
@@ -5792,6 +5793,7 @@ static int ati_fetch_size(void)
 
 	if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) ||
+	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_REV2) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_B) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) {
 		pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp);
@@ -5825,6 +5827,7 @@ static int ati_configure(void)
 
 	if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) ||
+	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_REV2) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_B) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) {
         	pci_write_config_dword(agp_bridge.dev, ATI_RS100_IG_AGPMODE, 0x20000);
@@ -5863,6 +5866,7 @@ static void ati_cleanup(void)
 	/* Write back the previous size and disable gart translation */
 	if ((agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS100) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200) ||
+	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_REV2) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS200_B) ||
 	    (agp_bridge.dev->device == PCI_DEVICE_ID_ATI_RS250)) {
 		pci_read_config_dword(agp_bridge.dev, ATI_RS100_APSIZE, &temp);
@@ -6426,6 +6430,12 @@ static struct {
 	  "ATI",
 	  "IGP330/340/345/350/M",
 	  ati_generic_setup },
+	{ PCI_DEVICE_ID_ATI_RS200_REV2,
+          PCI_VENDOR_ID_ATI,
+          ATI_RS200,
+          "ATI",
+          "IGP345M (rev 2)",
+          ati_generic_setup },
 	{ PCI_DEVICE_ID_ATI_RS200_B,
 	  PCI_VENDOR_ID_ATI,
 	  ATI_RS200,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/amd7xx_tco.c linux-2.4.27-rc4/drivers/char/amd7xx_tco.c
--- linux-2.4.26/drivers/char/amd7xx_tco.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/amd7xx_tco.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,387 +0,0 @@
-/*
- *	AMD 766/768 TCO Timer Driver
- *	(c) Copyright 2002 Zwane Mwaikambo <zwane@holomorphy.com>
- *	All Rights Reserved.
- *
- *	Parts from;
- *	Hardware driver for the AMD 768 Random Number Generator (RNG)
- *	(c) Copyright 2001 Red Hat Inc <alan@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.
- *
- *	The author(s) of this software shall not be held liable for damages
- *	of any nature resulting due to the use of this software. This
- *	software is provided AS-IS with no warranties.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-#include <linux/ioport.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#define AMDTCO_MODULE_VER	"build 20021116"
-#define AMDTCO_MODULE_NAME	"amd7xx_tco"
-#define PFX			AMDTCO_MODULE_NAME ": "
-
-#define	MAX_TIMEOUT	38	/* max of 38 seconds, although the system will only
-				 * reset itself after the second timeout */
-
-/* pmbase registers */
-#define TCO_RELOAD_REG	0x40		/* bits 0-5 are current count, 6-7 are reserved */
-#define TCO_INITVAL_REG	0x41		/* bits 0-5 are value to load, 6-7 are reserved */
-#define TCO_TIMEOUT_MASK	0x3f
-#define TCO_STATUS1_REG 0x44
-#define TCO_STATUS2_REG	0x46
-#define NDTO_STS2	(1 << 1)	/* we're interested in the second timeout */ 
-#define BOOT_STS	(1 << 2)	/* will be set if NDTO_STS2 was set before reboot */
-#define TCO_CTRL1_REG	0x48
-#define TCO_HALT	(1 << 11)
-#define NO_REBOOT	(1 << 10)	/* in DevB:3x48 */
-
-static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n";
-static int timeout = 38;
-static u32 pmbase;		/* PMxx I/O base */
-static struct pci_dev *dev;
-static struct semaphore open_sem;
-static spinlock_t amdtco_lock;	/* only for device access */
-static int expect_close = 0;
-
-MODULE_PARM(timeout, "i");
-MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38");
-
-static inline u8 seconds_to_ticks(int seconds)
-{
-	/* the internal timer is stored as ticks which decrement
-	 * every 0.6 seconds */
-	return (seconds * 10) / 6;
-}
-
-static inline int ticks_to_seconds(u8 ticks)
-{
-	return (ticks * 6) / 10;
-}
-
-static inline int amdtco_status(void)
-{
-	u16 reg;
-	int status = 0;
-
-	reg = inb(pmbase+TCO_CTRL1_REG);
-	if ((reg & TCO_HALT) == 0)
-		status |= WDIOF_KEEPALIVEPING;
-
-	reg = inb(pmbase+TCO_STATUS2_REG);
-	if (reg & BOOT_STS)
-		status |= WDIOF_CARDRESET;
-
-	return status;
-}
-
-static inline void amdtco_ping(void)
-{
-	outb(1, pmbase+TCO_RELOAD_REG);
-}
-
-static inline int amdtco_gettimeout(void)
-{
-	u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK;
-	return ticks_to_seconds(reg);
-}
-
-static inline void amdtco_settimeout(unsigned int timeout)
-{
-	u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK;
-	outb(reg, pmbase+TCO_INITVAL_REG);
-}
-
-static inline void amdtco_global_enable(void)
-{
-	u16 reg;
-
-	spin_lock(&amdtco_lock);
-
-	/* clear NO_REBOOT on DevB:3x48 p97 */
-	pci_read_config_word(dev, 0x48, &reg);
-	reg &= ~NO_REBOOT;
-	pci_write_config_word(dev, 0x48, reg);
-
-	spin_unlock(&amdtco_lock);
-}
-
-static inline void amdtco_enable(void)
-{
-	u16 reg;
-	
-	spin_lock(&amdtco_lock);
-	reg = inw(pmbase+TCO_CTRL1_REG);
-	reg &= ~TCO_HALT;
-	outw(reg, pmbase+TCO_CTRL1_REG);
-	spin_unlock(&amdtco_lock);
-}
-
-static inline void amdtco_disable(void)
-{
-	u16 reg;
-
-	spin_lock(&amdtco_lock);
-	reg = inw(pmbase+TCO_CTRL1_REG);
-	reg |= TCO_HALT;
-	outw(reg, pmbase+TCO_CTRL1_REG);
-	spin_unlock(&amdtco_lock);
-}
-
-static int amdtco_fop_open(struct inode *inode, struct file *file)
-{
-	if (down_trylock(&open_sem))
-		return -EBUSY;
-
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	
-	MOD_INC_USE_COUNT;
-#endif
-
-	if (timeout > MAX_TIMEOUT)
-		timeout = MAX_TIMEOUT;
-
-	amdtco_disable();
-	amdtco_settimeout(timeout);	
-	amdtco_global_enable();
-	amdtco_enable();
-	amdtco_ping();
-	printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n",
-		amdtco_gettimeout(), timeout);
-	
-	return 0;
-}
-
-
-static int amdtco_fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int new_timeout;
-	int tmp;
-
-	static struct watchdog_info ident = {
-		options:	WDIOF_SETTIMEOUT | WDIOF_CARDRESET,
-		identity:	"AMD 766/768"
-	};
-
-	switch (cmd) {
-		default:
-			return -ENOTTY;	
-
-		case WDIOC_GETSUPPORT:
-			if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident))
-				return -EFAULT;
-			return 0;
-
-		case WDIOC_GETSTATUS:
-			return put_user(amdtco_status(), (int *)arg);
-	
-		case WDIOC_KEEPALIVE:
-			amdtco_ping();
-			return 0;
-
-		case WDIOC_SETTIMEOUT:
-			if (get_user(new_timeout, (int *)arg))
-				return -EFAULT;
-			
-			if (new_timeout < 0)
-				return -EINVAL;
-		
-			if (new_timeout > MAX_TIMEOUT)
-				new_timeout = MAX_TIMEOUT;
-
-			timeout = new_timeout;
-			amdtco_settimeout(timeout);
-			/* fall through and return the new timeout */
-
-		case WDIOC_GETTIMEOUT:
-			return put_user(amdtco_gettimeout(), (int *)arg);
-		
-		case WDIOC_SETOPTIONS:
-			if (copy_from_user(&tmp, (int *)arg, sizeof tmp))
-                                return -EFAULT;
-
-			if (tmp & WDIOS_DISABLECARD)
-				amdtco_disable();
-
-			if (tmp & WDIOS_ENABLECARD)
-				amdtco_enable();
-			
-			return 0;
-	}
-}
-
-
-static int amdtco_fop_release(struct inode *inode, struct file *file)
-{
-	if (expect_close) {
-		amdtco_disable();	
-		printk(KERN_INFO PFX "Watchdog disabled\n");
-	} else {
-		amdtco_ping();
-		printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout);
-	}	
-	
-	up(&open_sem);
-	return 0;
-}
-
-
-static ssize_t amdtco_fop_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	
-	if (len) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		size_t i;
-		char c;
-		expect_close = 0;
-		
-		for (i = 0; i != len; i++) {
-			if (get_user(c, data + i))
-				return -EFAULT;
-
-			if (c == 'V')
-				expect_close = 1;
-		}
-#endif
-		amdtco_ping();
-	}
-
-	return len;
-}
-
-
-static int amdtco_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-	if (code == SYS_DOWN || code == SYS_HALT)
-		amdtco_disable();
-
-	return NOTIFY_DONE;
-}
-
-
-static struct notifier_block amdtco_notifier =
-{
-	notifier_call:	amdtco_notify_sys
-};
-
-static struct file_operations amdtco_fops =
-{
-	owner:		THIS_MODULE,
-	write:		amdtco_fop_write,
-	ioctl:		amdtco_fop_ioctl,
-	open:		amdtco_fop_open,
-	release:	amdtco_fop_release
-};
-
-static struct miscdevice amdtco_miscdev =
-{
-	minor:		WATCHDOG_MINOR,
-	name:		"watchdog",
-	fops:		&amdtco_fops
-};
-
-static struct pci_device_id amdtco_pci_tbl[] __initdata = {
-	{ 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE (pci, amdtco_pci_tbl);
-
-static int __init amdtco_init(void)
-{
-	int ret;
-
-	sema_init(&open_sem, 1);
-	spin_lock_init(&amdtco_lock);
-
-	pci_for_each_dev(dev) {
-		if (pci_match_device (amdtco_pci_tbl, dev) != NULL)
-			goto found_one;
-	}
-
-	return -ENODEV;
-
-found_one:
-	
-	if ((ret = register_reboot_notifier(&amdtco_notifier))) {
-		printk(KERN_ERR PFX "Unable to register reboot notifier err = %d\n", ret);
-		goto out_clean;
-	}
-
-	if ((ret = misc_register(&amdtco_miscdev))) {
-		printk(KERN_ERR PFX "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR);
-		goto out_unreg_reboot;
-	}
-
-	pci_read_config_dword(dev, 0x58, &pmbase);
-	pmbase &= 0x0000FF00;
-
-	if (pmbase == 0) {
-		printk (KERN_ERR PFX "power management base not set\n");
-		ret = -EIO;
-		goto out_unreg_misc;
-	}
-
-	/* ret = 0; */
-	printk(banner);
-	goto out_clean;
-
-out_unreg_misc:
-	misc_deregister(&amdtco_miscdev);
-out_unreg_reboot:
-	unregister_reboot_notifier(&amdtco_notifier);
-out_clean:
-	return ret;
-}
-
-static void __exit amdtco_exit(void)
-{
-	misc_deregister(&amdtco_miscdev);
-	unregister_reboot_notifier(&amdtco_notifier);
-}
-
-
-#ifndef MODULE
-static int __init amdtco_setup(char *str)
-{
-	int ints[4];
-
-	str = get_options (str, ARRAY_SIZE(ints), ints);
-	if (ints[0] > 0)
-		timeout = ints[1];
-
-	if (!timeout || timeout > 38)
-		timeout = MAX_TIMEOUT;
-
-	return 1;
-}
-
-__setup("amd7xx_tco=", amdtco_setup);
-#endif
-
-module_init(amdtco_init);
-module_exit(amdtco_exit);
-
-MODULE_AUTHOR("Zwane Mwaikambo <zwane@holomorphy.com>");
-MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver");
-MODULE_LICENSE("GPL");
-EXPORT_NO_SYMBOLS;
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/drm/drmP.h linux-2.4.27-rc4/drivers/char/drm/drmP.h
--- linux-2.4.26/drivers/char/drm/drmP.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/drm/drmP.h	2004-07-30 16:30:03.000000000 +0000
@@ -52,6 +52,7 @@
 #include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>	/* For (un)lock_kernel */
+#include <asm/system.h>	/* for cmpxchg() */
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #if defined(__alpha__) || defined(__powerpc__)
@@ -174,38 +175,7 @@ __cmpxchg(volatile void *ptr, unsigned l
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
 
-#elif __i386__
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
-				      unsigned long new, int size)
-{
-	unsigned long prev;
-	switch (size) {
-	case 1:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 2:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	case 4:
-		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
-				     : "=a"(prev)
-				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
-				     : "memory");
-		return prev;
-	}
-	return old;
-}
-
-#define cmpxchg(ptr,o,n)						\
-  ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),		\
-				 (unsigned long)(n),sizeof(*(ptr))))
-#endif /* i386 & alpha */
+#endif /* alpha */
 #endif
 #define __REALLY_HAVE_SG	(__HAVE_SG)
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/drm/sis_mm.c linux-2.4.27-rc4/drivers/char/drm/sis_mm.c
--- linux-2.4.26/drivers/char/drm/sis_mm.c	2002-11-28 23:53:12.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/drm/sis_mm.c	2004-07-30 16:29:50.000000000 +0000
@@ -120,7 +120,7 @@ int sis_fb_free(struct inode *inode, str
     return -1;
   }
 
-  sis_free(fb.free);
+  sis_free((u32)fb.free);
   if(!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
     retval = -1;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/parport_serial.c linux-2.4.27-rc4/drivers/char/parport_serial.c
--- linux-2.4.26/drivers/char/parport_serial.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/parport_serial.c	2004-07-30 16:31:11.000000000 +0000
@@ -0,0 +1,436 @@
+/*
+ * Support for common PCI multi-I/O cards (which is most of them)
+ *
+ * Copyright (C) 2001  Tim Waugh <twaugh@redhat.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.
+ *
+ *
+ * Multi-function PCI cards are supposed to present separate logical
+ * devices on the bus.  A common thing to do seems to be to just use
+ * one logical device with lots of base address registers for both
+ * parallel ports and serial ports.  This driver is for dealing with
+ * that.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/parport.h>
+#include <linux/parport_pc.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/list.h>
+
+#include <asm/serial.h>
+
+enum parport_pc_pci_cards {
+	titan_110l = 0,
+	titan_210l,
+	netmos_9735,
+	netmos_9835,
+	avlab_1s1p,
+	avlab_1s1p_650,
+	avlab_1s1p_850,
+	avlab_1s2p,
+	avlab_1s2p_650,
+	avlab_1s2p_850,
+	avlab_2s1p,
+	avlab_2s1p_650,
+	avlab_2s1p_850,
+	siig_1s1p_10x,
+	siig_2s1p_10x,
+	siig_2p1s_20x,
+	siig_1s1p_20x,
+	siig_2s1p_20x,
+};
+
+
+/* each element directly indexed from enum list, above */
+static struct parport_pc_pci {
+	int numports;
+	struct { /* BAR (base address registers) numbers in the config
+                    space header */
+		int lo;
+		int hi; /* -1 if not there, >6 for offset-method (max
+                           BAR is 6) */
+	} addr[4];
+
+	/* If set, this is called immediately after pci_enable_device.
+	 * If it returns non-zero, no probing will take place and the
+	 * ports will not be used. */
+	int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int autodma);
+
+	/* If set, this is called after probing for ports.  If 'failed'
+	 * is non-zero we couldn't use any of the ports. */
+	void (*postinit_hook) (struct pci_dev *pdev, int failed);
+} cards[] __devinitdata = {
+	/* titan_110l */		{ 1, { { 3, -1 }, } },
+	/* titan_210l */		{ 1, { { 3, -1 }, } },
+	/* netmos_9735 (not tested) */	{ 1, { { 2, -1 }, } },
+	/* netmos_9835 */		{ 1, { { 2, -1 }, } },
+	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
+	/* avlab_1s1p_650 */		{ 1, { { 1, 2}, } },
+	/* avlab_1s1p_850 */		{ 1, { { 1, 2}, } },
+	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
+	/* avlab_1s2p_650 */		{ 2, { { 1, 2}, { 3, 4 },} },
+	/* avlab_1s2p_850 */		{ 2, { { 1, 2}, { 3, 4 },} },
+	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
+	/* avlab_2s1p_650 */		{ 1, { { 2, 3}, } },
+	/* avlab_2s1p_850 */		{ 1, { { 2, 3}, } },
+	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
+	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
+	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
+	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
+	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
+};
+
+static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
+	/* PCI cards */
+	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
+	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9735,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9735 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9835 },
+	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
+	{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
+	{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
+	{ 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850},
+	{ 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p},
+	{ 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650},
+	{ 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850},
+	{ 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p},
+	{ 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650},
+	{ 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850},
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
+
+	{ 0, } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
+
+struct pci_board_no_ids {
+	int flags;
+	int num_ports;
+	int base_baud;
+	int uart_offset;
+	int reg_shift;
+	int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
+			int enable);
+	int first_uart_offset;
+};
+
+static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+	return pci_siig10x_fn(dev, NULL, enable);
+}
+
+static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
+{
+	return pci_siig20x_fn(dev, NULL, enable);
+}
+
+static struct pci_board_no_ids pci_boards[] __devinitdata = {
+	/*
+	 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
+	 * Offset to get to next UART's registers,
+	 * Register shift to use for memory-mapped I/O,
+	 * Initialization function, first UART offset
+	 */
+
+// Cards not tested are marked n/t
+// If you have one of these cards and it works for you, please tell me..
+
+/* titan_110l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
+/* titan_210l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
+/* netmos_9735 (n/t)*/	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* netmos_9835 */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_1s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
+/* avlab_2s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
+/* siig_1s1p_10x */	{ SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
+/* siig_2s1p_10x */	{ SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
+/* siig_2p1s_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* siig_1s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+/* siig_2s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
+};
+
+struct parport_serial_private {
+	int num_ser;
+	int line[20];
+	struct pci_board_no_ids ser;
+	int num_par;
+	struct parport *port[PARPORT_MAX];
+};
+
+static int __devinit get_pci_port (struct pci_dev *dev,
+				   struct pci_board_no_ids *board,
+				   struct serial_struct *req,
+				   int idx)
+{
+	unsigned long port;
+	int base_idx;
+	int max_port;
+	int offset;
+
+	base_idx = SPCI_FL_GET_BASE(board->flags);
+	if (board->flags & SPCI_FL_BASE_TABLE)
+		base_idx += idx;
+
+	if (board->flags & SPCI_FL_REGION_SZ_CAP) {
+		max_port = pci_resource_len(dev, base_idx) / 8;
+		if (idx >= max_port)
+			return 1;
+	}
+
+	offset = board->first_uart_offset;
+
+	/* Timedia/SUNIX uses a mixture of BARs and offsets */
+	/* Ugh, this is ugly as all hell --- TYT */
+	if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
+		switch(idx) {
+			case 0: base_idx=0;
+				break;
+			case 1: base_idx=0; offset=8;
+				break;
+			case 2: base_idx=1;
+				break;
+			case 3: base_idx=1; offset=8;
+				break;
+			case 4: /* BAR 2*/
+			case 5: /* BAR 3 */
+			case 6: /* BAR 4*/
+			case 7: base_idx=idx-2; /* BAR 5*/
+		}
+
+	port =  pci_resource_start(dev, base_idx) + offset;
+
+	if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
+		port += idx * (board->uart_offset ? board->uart_offset : 8);
+
+	if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
+		int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
+		req->port = port;
+		if (high_bits_offset)
+			req->port_high = port >> high_bits_offset;
+		else
+			req->port_high = 0;
+		return 0;
+	}
+	req->io_type = SERIAL_IO_MEM;
+	req->iomem_base = ioremap(port, board->uart_offset);
+	req->iomem_reg_shift = board->reg_shift;
+	req->port = 0;
+	return req->iomem_base ? 0 : 1;
+}
+
+/* Register the serial port(s) of a PCI card. */
+static int __devinit serial_register (struct pci_dev *dev,
+				      const struct pci_device_id *id)
+{
+	struct pci_board_no_ids *board = &pci_boards[id->driver_data];
+	struct parport_serial_private *priv = pci_get_drvdata (dev);
+	struct serial_struct serial_req;
+	int base_baud;
+	int k;
+	int success = 0;
+
+	priv->ser = *board;
+	if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
+		return 1;
+
+	base_baud = board->base_baud;
+	if (!base_baud)
+		base_baud = BASE_BAUD;
+	memset (&serial_req, 0, sizeof (serial_req));
+
+	for (k = 0; k < board->num_ports; k++) {
+		int line;
+		serial_req.irq = dev->irq;
+		if (get_pci_port (dev, board, &serial_req, k))
+			break;
+		serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
+		serial_req.baud_base = base_baud;
+		line = register_serial (&serial_req);
+		if (line < 0) {
+			printk (KERN_DEBUG
+				"parport_serial: register_serial failed\n");
+			continue;
+		}
+		priv->line[priv->num_ser++] = line;
+		success = 1;
+	}
+
+	return success ? 0 : 1;
+}
+
+/* Register the parallel port(s) of a PCI card. */
+static int __devinit parport_register (struct pci_dev *dev,
+				       const struct pci_device_id *id)
+{
+	struct parport_serial_private *priv = pci_get_drvdata (dev);
+	int i = id->driver_data, n;
+	int success = 0;
+
+	if (cards[i].preinit_hook &&
+	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
+		return -ENODEV;
+
+	for (n = 0; n < cards[i].numports; n++) {
+		struct parport *port;
+		int lo = cards[i].addr[n].lo;
+		int hi = cards[i].addr[n].hi;
+		unsigned long io_lo, io_hi;
+		io_lo = pci_resource_start (dev, lo);
+		io_hi = 0;
+		if ((hi >= 0) && (hi <= 6))
+			io_hi = pci_resource_start (dev, hi);
+		else if (hi > 6)
+			io_lo += hi; /* Reinterpret the meaning of
+                                        "hi" as an offset (see SYBA
+                                        def.) */
+		/* TODO: test if sharing interrupts works */
+		printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
+			"I/O at %#lx(%#lx)\n",
+			parport_serial_pci_tbl[i].vendor,
+			parport_serial_pci_tbl[i].device, io_lo, io_hi);
+		port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
+					      PARPORT_DMA_NONE, dev);
+		if (port) {
+			priv->port[priv->num_par++] = port;
+			success = 1;
+		}
+	}
+
+	if (cards[i].postinit_hook)
+		cards[i].postinit_hook (dev, !success);
+
+	return success ? 0 : 1;
+}
+
+static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
+					       const struct pci_device_id *id)
+{
+	struct parport_serial_private *priv;
+	int err;
+
+	priv = kmalloc (sizeof *priv, GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->num_ser = priv->num_par = 0;
+	pci_set_drvdata (dev, priv);
+
+	err = pci_enable_device (dev);
+	if (err) {
+		pci_set_drvdata (dev, NULL);
+		kfree (priv);
+		return err;
+	}
+
+	if (parport_register (dev, id)) {
+		pci_set_drvdata (dev, NULL);
+		kfree (priv);
+		return -ENODEV;
+	}
+
+	if (serial_register (dev, id)) {
+		int i;
+		for (i = 0; i < priv->num_par; i++)
+			parport_pc_unregister_port (priv->port[i]);
+		pci_set_drvdata (dev, NULL);
+		kfree (priv);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
+{
+	struct parport_serial_private *priv = pci_get_drvdata (dev);
+	int i;
+
+	// Serial ports
+	for (i = 0; i < priv->num_ser; i++) {
+		unregister_serial (priv->line[i]);
+
+		if (priv->ser.init_fn)
+			(priv->ser.init_fn) (dev, &priv->ser, 0);
+	}
+	pci_set_drvdata (dev, NULL);
+
+	// Parallel ports
+	for (i = 0; i < priv->num_par; i++)
+		parport_pc_unregister_port (priv->port[i]);
+
+	kfree (priv);
+	return;
+}
+
+static struct pci_driver parport_serial_pci_driver = {
+	name:		"parport_serial",
+	id_table:	parport_serial_pci_tbl,
+	probe:		parport_serial_pci_probe,
+	remove:		__devexit_p(parport_serial_pci_remove),
+};
+
+
+static int __init parport_serial_init (void)
+{
+	return pci_module_init (&parport_serial_pci_driver);
+}
+
+static void __exit parport_serial_exit (void)
+{
+	pci_unregister_driver (&parport_serial_pci_driver);
+	return;
+}
+
+MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
+MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
+MODULE_LICENSE("GPL");
+
+module_init(parport_serial_init);
+module_exit(parport_serial_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/sysrq.c linux-2.4.27-rc4/drivers/char/sysrq.c
--- linux-2.4.26/drivers/char/sysrq.c	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/sysrq.c	2004-07-30 16:30:49.000000000 +0000
@@ -365,7 +365,7 @@ static struct sysrq_key_op *sysrq_key_ta
 /* v */	NULL,
 /* w */	NULL,
 /* x */	NULL,
-/* w */	NULL,
+/* y */	NULL,
 /* z */	NULL
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/char/tipar.c linux-2.4.27-rc4/drivers/char/tipar.c
--- linux-2.4.26/drivers/char/tipar.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/char/tipar.c	2004-07-30 16:27:14.000000000 +0000
@@ -66,7 +66,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "1.18"
+#define DRIVER_VERSION "1.19"
 #define DRIVER_AUTHOR  "Romain Lievin <roms@lpg.ticalc.org>"
 #define DRIVER_DESC    "Device driver for TI/PC parallel link cables"
 #define DRIVER_LICENSE "GPL"
@@ -124,7 +124,7 @@ init_ti_parallel(int minor)
 
 /* ----- global defines ----------------------------------------------- */
 
-#define START(x) { x=jiffies+HZ/(timeout/10); }
+#define START(x) { x = jiffies + (HZ * timeout) / 10; }
 #define WAIT(x)  { \
   if (time_before((x), jiffies)) return -1; \
   if (need_resched()) schedule(); }
@@ -366,11 +366,14 @@ tipar_ioctl(struct inode *inode, struct 
 
 	switch (cmd) {
 	case IOCTL_TIPAR_DELAY:
-	  delay = (int)arg;    //get_user(delay, &arg);
-	  break;
+		delay = (int)arg;    //get_user(delay, &arg);
+		break;
 	case IOCTL_TIPAR_TIMEOUT:
-	  timeout = (int)arg;  //get_user(timeout, &arg);
-	  break;
+		if (arg != 0)
+                        timeout = (int)arg;
+                else
+                        retval = -EINVAL;
+		break;
 	default:
 		retval = -ENOTTY;
 		break;
@@ -404,7 +407,10 @@ tipar_setup(char *str)
 	str = get_options(str, ARRAY_SIZE(ints), ints);
 
 	if (ints[0] > 0) {
-		timeout = ints[1];
+		if (ints[1] != 0)
+                        timeout = ints[1];
+                else
+                        printk("tipar: wrong timeout value (0), using default value instead.");
 		if (ints[0] > 1) {
 			delay = ints[2];
 		}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/Config.in linux-2.4.27-rc4/drivers/hotplug/Config.in
--- linux-2.4.26/drivers/hotplug/Config.in	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/Config.in	2004-07-30 16:26:08.000000000 +0000
@@ -14,4 +14,11 @@ fi
 if [ "$CONFIG_ACPI_INTERPRETER" = "y" ]; then
    dep_tristate '  ACPI PCI Hotplug driver' CONFIG_HOTPLUG_PCI_ACPI $CONFIG_HOTPLUG_PCI
 fi
+dep_tristate '  SHPC PCI Hotplug driver' CONFIG_HOTPLUG_PCI_SHPC $CONFIG_HOTPLUG_PCI
+dep_mbool '    Use polling mechanism for hot-plug events (for testing purpose)' CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE $CONFIG_HOTPLUG_PCI_SHPC
+if [ "$CONFIG_ACPI" = "n" ]; then
+dep_mbool '    For AMD SHPC only: Use HRT for resource/configuration' CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY $CONFIG_HOTPLUG_PCI_SHPC 
+fi
+dep_tristate '  PCI Express Hotplug driver' CONFIG_HOTPLUG_PCI_PCIE $CONFIG_HOTPLUG_PCI
+dep_mbool '    Use polling mechanism for hot-plug events (for testing purpose)' CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE $CONFIG_HOTPLUG_PCI_PCIE
 endmenu
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/Makefile linux-2.4.27-rc4/drivers/hotplug/Makefile
--- linux-2.4.26/drivers/hotplug/Makefile	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/Makefile	2004-07-30 16:29:55.000000000 +0000
@@ -4,7 +4,7 @@
 
 O_TARGET	:= vmlinux-obj.o
 
-list-multi	:= cpqphp.o pci_hotplug.o ibmphp.o acpiphp.o 
+list-multi	:= cpqphp.o pci_hotplug.o ibmphp.o acpiphp.o shpchp.o pciehp.o 
 
 export-objs	:= pci_hotplug_core.o pci_hotplug_util.o
 
@@ -12,6 +12,8 @@ obj-$(CONFIG_HOTPLUG_PCI)		+= pci_hotplu
 obj-$(CONFIG_HOTPLUG_PCI_COMPAQ)	+= cpqphp.o
 obj-$(CONFIG_HOTPLUG_PCI_IBM)		+= ibmphp.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI)		+= acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_SHPC)		+= shpchp.o
+obj-$(CONFIG_HOTPLUG_PCI_PCIE)		+= pciehp.o
 
 pci_hotplug-objs	:=	pci_hotplug_core.o	\
 				pci_hotplug_util.o
@@ -32,11 +34,36 @@ acpiphp_objs		:=	acpiphp_core.o	\
 				acpiphp_pci.o	\
 				acpiphp_res.o
 
+pciehp-objs		:=	pciehp_core.o	\
+				pciehp_ctrl.o	\
+				pciehp_hpc.o	\
+				pciehp_pci.o
+ifdef CONFIG_ACPI_INTERPRETER
+  pciehp-objs += pciehprm_acpi.o
+else
+  pciehp-objs += pciehprm_nonacpi.o
+  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi 
+endif
+
+shpchp-objs		:=	shpchp_core.o	\
+				shpchp_ctrl.o	\
+				shpchp_hpc.o	\
+				shpchp_pci.o
+ifdef CONFIG_ACPI_INTERPRETER
+  shpchp-objs += shpchprm_acpi.o
+  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi 
+else
+  ifdef CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY
+    shpchp-objs += shpchprm_legacy.o
+  else
+    shpchp-objs += shpchprm_nonacpi.o
+  endif
+endif
+
 ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
 	cpqphp-objs += cpqphp_nvram.o
 endif
 
-
 include $(TOPDIR)/Rules.make
 
 pci_hotplug.o: $(pci_hotplug-objs)
@@ -50,3 +77,10 @@ ibmphp.o: $(ibmphp-objs)
 
 acpiphp.o: $(acpiphp_objs)
 	$(LD) -r -o $@ $(acpiphp_objs)
+
+pciehp.o: $(pciehp-objs)
+	$(LD) -r -o $@ $(pciehp-objs)
+
+shpchp.o: $(shpchp-objs)
+	$(LD) -r -o $@ $(shpchp-objs)
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/acpiphp.h linux-2.4.27-rc4/drivers/hotplug/acpiphp.h
--- linux-2.4.26/drivers/hotplug/acpiphp.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/acpiphp.h	2004-07-30 16:24:46.000000000 +0000
@@ -36,63 +36,7 @@
 #include <linux/acpi.h>
 #include "pci_hotplug.h"
 
-#if ACPI_CA_VERSION < 0x20020201
-/* until we get a new version of the ACPI driver for both ia32 and ia64 ... */
-#define acpi_util_eval_error(h,p,s)
-
-static acpi_status
-acpi_evaluate_integer (
-	acpi_handle		handle,
-	acpi_string		pathname,
-	acpi_object_list	*arguments,
-	unsigned long		*data)
-{
-	acpi_status		status = AE_OK;
-	acpi_object		element;
-	acpi_buffer		buffer = {sizeof(acpi_object), &element};
-
-	if (!data)
-		return AE_BAD_PARAMETER;
-
-	status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
-	if (ACPI_FAILURE(status)) {
-		acpi_util_eval_error(handle, pathname, status);
-		return status;
-	}
-
-	if (element.type != ACPI_TYPE_INTEGER) {
-		acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
-		return AE_BAD_DATA;
-	}
-
-	*data = element.integer.value;
-
-	return AE_OK;
-}
-#else  /* ACPI_CA_VERSION < 0x20020201 */
 #include <acpi/acpi_bus.h>
-#endif
-
-/* compatibility stuff for ACPI CA */
-#ifndef ACPI_MEMORY_RANGE
-#define ACPI_MEMORY_RANGE MEMORY_RANGE
-#endif
-
-#ifndef ACPI_IO_RANGE
-#define ACPI_IO_RANGE IO_RANGE
-#endif
-
-#ifndef ACPI_BUS_NUMBER_RANGE
-#define ACPI_BUS_NUMBER_RANGE BUS_NUMBER_RANGE
-#endif
-
-#ifndef ACPI_PREFETCHABLE_MEMORY
-#define ACPI_PREFETCHABLE_MEMORY PREFETCHABLE_MEMORY
-#endif
-
-#ifndef ACPI_PRODUCER
-#define ACPI_PRODUCER PRODUCER
-#endif
 
 #define dbg(format, arg...)					\
 	do {							\
@@ -258,7 +202,7 @@ struct acpiphp_func {
 
 #define SLOT_POWEREDON		(0x00000001)
 #define SLOT_ENABLED		(0x00000002)
-#define SLOT_MULTIFUNCTION	(x000000004)
+#define SLOT_MULTIFUNCTION	(0x00000004)
 
 /* function flags */
 
@@ -269,8 +213,6 @@ struct acpiphp_func {
 #define FUNC_HAS_PS2		(0x00000040)
 #define FUNC_HAS_PS3		(0x00000080)
 
-#define FUNC_EXISTS		(0x10000000) /* to make sure we call _EJ0 only for existing funcs */
-
 /* function prototypes */
 
 /* acpiphp_glue.c */
@@ -288,6 +230,7 @@ extern u8 acpiphp_get_power_status (stru
 extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
 extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
+extern u32 acpiphp_get_address (struct acpiphp_slot *slot);
 
 /* acpiphp_pci.c */
 extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/acpiphp_core.c linux-2.4.27-rc4/drivers/hotplug/acpiphp_core.c
--- linux-2.4.26/drivers/hotplug/acpiphp_core.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/acpiphp_core.c	2004-07-30 16:30:47.000000000 +0000
@@ -30,14 +30,14 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/module.h>
+
+#include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include <linux/init.h>
 #include "pci_hotplug.h"
 #include "acpiphp.h"
 
@@ -73,6 +73,7 @@ static int get_power_status	(struct hotp
 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_address		(struct hotplug_slot *slot, u32 *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);
 
@@ -86,6 +87,7 @@ static struct hotplug_slot_ops acpi_hotp
 	.get_attention_status	= get_attention_status,
 	.get_latch_status	= get_latch_status,
 	.get_adapter_status	= get_adapter_status,
+	.get_address		= get_address,
 	.get_max_bus_speed	= get_max_bus_speed,
 	.get_cur_bus_speed	= get_cur_bus_speed,
 };
@@ -322,6 +324,28 @@ static int get_adapter_status (struct ho
 }
 
 
+/**
+ * get_address - get pci address of a slot
+ * @hotplug_slot: slot to get status
+ * @busdev: pointer to struct pci_busdev (seg, bus, dev)
+ *
+ */
+static int get_address (struct hotplug_slot *hotplug_slot, u32 *value)
+{
+	struct slot *slot = get_slot(hotplug_slot, __FUNCTION__);
+	int retval = 0;
+
+	if (slot == NULL)
+		return -ENODEV;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	*value = acpiphp_get_address(slot->acpi_slot);
+
+	return retval;
+}
+
+
 /* return dummy value because ACPI doesn't provide any method... */
 static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/acpiphp_glue.c linux-2.4.27-rc4/drivers/hotplug/acpiphp_glue.c
--- linux-2.4.26/drivers/hotplug/acpiphp_glue.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/acpiphp_glue.c	2004-07-30 16:30:49.000000000 +0000
@@ -26,12 +26,12 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/module.h>
+
+#include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
-#include <linux/init.h>
 #include <asm/semaphore.h>
 
 #include "pci_hotplug.h"
@@ -389,12 +389,8 @@ static struct pci_bus *find_pci_bus(cons
 static void decode_hpp(struct acpiphp_bridge *bridge)
 {
 	acpi_status status;
-#if ACPI_CA_VERSION < 0x20020201
-	acpi_buffer buffer;
-#else
 	struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
 				      .pointer = NULL};
-#endif
 	union acpi_object *package;
 	int i;
 
@@ -404,21 +400,7 @@ static void decode_hpp(struct acpiphp_br
 	bridge->hpp.enable_SERR = 0;
 	bridge->hpp.enable_PERR = 0;
 
-#if ACPI_CA_VERSION < 0x20020201
-	buffer.length = 0;
-	buffer.pointer = NULL;
-
-	status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
-
-	if (status == AE_BUFFER_OVERFLOW) {
-		buffer.pointer = kmalloc(buffer.length, GFP_KERNEL);
-		if (!buffer.pointer)
-			return;
-		status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
-	}
-#else
 	status = acpi_evaluate_object(bridge->handle, "_HPP", NULL, &buffer);
-#endif
 
 	if (ACPI_FAILURE(status)) {
 		dbg("_HPP evaluation failed\n");
@@ -494,12 +476,8 @@ static void init_bridge_misc (struct acp
 static void add_host_bridge (acpi_handle *handle, int seg, int bus)
 {
 	acpi_status status;
-#if ACPI_CA_VERSION < 0x20020201
-	acpi_buffer buffer;
-#else
 	struct acpi_buffer buffer = { .length = ACPI_ALLOCATE_BUFFER,
 				      .pointer = NULL};
-#endif
 	struct acpiphp_bridge *bridge;
 
 	bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
@@ -522,22 +500,8 @@ static void add_host_bridge (acpi_handle
 
 	/* decode resources */
 
-#if ACPI_CA_VERSION < 0x20020201
-	buffer.length = 0;
-	buffer.pointer = NULL;
-
 	status = acpi_get_current_resources(handle, &buffer);
 
-	if (status == AE_BUFFER_OVERFLOW) {
-		buffer.pointer = kmalloc(buffer.length, GFP_KERNEL);
-		if (!buffer.pointer)
-			return;
-		status = acpi_get_current_resources(handle, &buffer);
-	}
-#else
-	status = acpi_get_current_resources(handle, &buffer);
-#endif
-
 	if (ACPI_FAILURE(status)) {
 		err("failed to decode bridge resources\n");
 		kfree(bridge);
@@ -819,7 +783,7 @@ static int power_on_slot (struct acpiphp
 	struct list_head *l;
 	int retval = 0;
 
-	/* is this already enabled? */
+	/* if already enabled, just skip */
 	if (slot->flags & SLOT_POWEREDON)
 		goto err_exit;
 
@@ -827,14 +791,14 @@ static int power_on_slot (struct acpiphp
 		func = list_entry(l, struct acpiphp_func, sibling);
 
 		if (func->flags & FUNC_HAS_PS0) {
-			dbg("%s: executing _PS0 on %s\n", __FUNCTION__,
-			    func->pci_dev->slot_name);
+			dbg("%s: executing _PS0\n", __FUNCTION__);
 			status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
 			if (ACPI_FAILURE(status)) {
 				warn("%s: _PS0 failed\n", __FUNCTION__);
 				retval = -1;
 				goto err_exit;
-			}
+			} else
+				break;
 		}
 	}
 
@@ -857,20 +821,21 @@ static int power_off_slot (struct acpiph
 
 	int retval = 0;
 
-	/* is this already enabled? */
+	/* if already disabled, just skip */
 	if ((slot->flags & SLOT_POWEREDON) == 0)
 		goto err_exit;
 
 	list_for_each (l, &slot->funcs) {
 		func = list_entry(l, struct acpiphp_func, sibling);
 
-		if (func->flags & (FUNC_HAS_PS3 | FUNC_EXISTS)) {
+		if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) {
 			status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
 			if (ACPI_FAILURE(status)) {
 				warn("%s: _PS3 failed\n", __FUNCTION__);
 				retval = -1;
 				goto err_exit;
-			}
+			} else
+				break;
 		}
 	}
 
@@ -878,20 +843,19 @@ static int power_off_slot (struct acpiph
 		func = list_entry(l, struct acpiphp_func, sibling);
 
 		/* We don't want to call _EJ0 on non-existing functions. */
-		if (func->flags & (FUNC_HAS_EJ0 | FUNC_EXISTS)) {
+		if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) {
 			/* _EJ0 method take one argument */
 			arg_list.count = 1;
 			arg_list.pointer = &arg;
 			arg.type = ACPI_TYPE_INTEGER;
 			arg.integer.value = 1;
-
 			status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);
 			if (ACPI_FAILURE(status)) {
 				warn("%s: _EJ0 failed\n", __FUNCTION__);
 				retval = -1;
 				goto err_exit;
-			}
-			func->flags &= (~FUNC_EXISTS);
+			} else
+				break;
 		}
 	}
 
@@ -973,8 +937,6 @@ static int enable_device (struct acpiphp
 		retval = acpiphp_configure_function(func);
 		if (retval)
 			goto err_exit;
-
-		func->flags |= FUNC_EXISTS;
 	}
 
 	slot->flags |= SLOT_ENABLED;
@@ -1003,15 +965,12 @@ static int disable_device (struct acpiph
 	list_for_each (l, &slot->funcs) {
 		func = list_entry(l, struct acpiphp_func, sibling);
 
-		if (func->pci_dev) {
-			if (acpiphp_unconfigure_function(func) == 0) {
-				func->pci_dev = NULL;
-			} else {
+		if (func->pci_dev)
+			if (acpiphp_unconfigure_function(func)) {
 				err("failed to unconfigure device\n");
 				retval = -1;
 				goto err_exit;
 			}
-		}
 	}
 
 	slot->flags &= (~SLOT_ENABLED);
@@ -1391,7 +1350,7 @@ int acpiphp_check_bridge (struct acpiphp
 					up(&slot->crit_sect);
 					goto err_exit;
 				}
-				enabled++;
+				disabled++;
 			}
 		} else {
 			/* if disabled but present, enable */
@@ -1402,7 +1361,7 @@ int acpiphp_check_bridge (struct acpiphp
 					up(&slot->crit_sect);
 					goto err_exit;
 				}
-				disabled++;
+				enabled++;
 			}
 		}
 	}
@@ -1468,3 +1427,18 @@ u8 acpiphp_get_adapter_status (struct ac
 
 	return (sta == 0) ? 0 : 1;
 }
+
+
+/*
+ * pci address (seg/bus/dev)
+ */
+u32 acpiphp_get_address (struct acpiphp_slot *slot)
+{
+	u32 address;
+
+	address = ((slot->bridge->seg) << 16) |
+		  ((slot->bridge->bus) << 8) |
+		  slot->device;
+
+	return address;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/acpiphp_pci.c linux-2.4.27-rc4/drivers/hotplug/acpiphp_pci.c
--- linux-2.4.26/drivers/hotplug/acpiphp_pci.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/acpiphp_pci.c	2004-07-30 16:27:57.000000000 +0000
@@ -29,11 +29,11 @@
  *
  */
 
-#include <linux/config.h>
-#include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/module.h>
+
+#include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/init.h>
 #include "pci_hotplug.h"
 #include "acpiphp.h"
 
@@ -78,8 +78,8 @@ static int init_config_space (struct acp
 		if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
 			/* This is IO */
 
-			len = bar & 0xFFFFFFFC;
-			len = ~len + 1;
+			len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
+			len = len & ~(len - 1);
 
 			dbg("len in IO %x, BAR %d\n", len, count);
 
@@ -340,8 +340,8 @@ static int detect_used_resource (struct 
 		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
 			/* This is IO */
 			base = bar & 0xFFFFFFFC;
-			len &= 0xFFFFFFFC;
-			len = ~len + 1;
+			len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
+			len = len & ~(len - 1);
 
 			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
 
@@ -465,8 +465,8 @@ int acpiphp_init_func_resource (struct a
 		if (len & PCI_BASE_ADDRESS_SPACE_IO) {
 			/* This is IO */
 			base = bar & 0xFFFFFFFC;
-			len &= 0xFFFFFFFC;
-			len = ~len + 1;
+			len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);
+			len = len & ~(len - 1);
 
 			dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/acpiphp_res.c linux-2.4.27-rc4/drivers/hotplug/acpiphp_res.c
--- linux-2.4.26/drivers/hotplug/acpiphp_res.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/acpiphp_res.c	2004-07-30 16:28:22.000000000 +0000
@@ -29,7 +29,7 @@
  *
  */
 
-#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -39,7 +39,6 @@
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include <linux/init.h>
 
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -225,7 +224,7 @@ struct pci_resource *acpiphp_get_io_reso
 		}  /* End of too big on top end */
 
 		/* For IO make sure it's not in the ISA aliasing space */
-		if (node->base & 0x300L)
+		if ((node->base & 0x300L) && !(node->base & 0xfffff000))
 			continue;
 
 		/* If we got here, then it is the right size
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pci_hotplug.h linux-2.4.27-rc4/drivers/hotplug/pci_hotplug.h
--- linux-2.4.26/drivers/hotplug/pci_hotplug.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pci_hotplug.h	2004-07-30 16:27:29.000000000 +0000
@@ -36,15 +36,36 @@ 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,
 	PCI_SPEED_66MHz_PCIX_533	= 0x11,
-	PCI_SPEED_100MHz_PCIX_533	= 0X12,
+	PCI_SPEED_100MHz_PCIX_533	= 0x12,
 	PCI_SPEED_133MHz_PCIX_533	= 0x13,
 	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_core;
 
@@ -69,6 +90,9 @@ struct hotplug_slot_core;
  * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
  *	If this field is NULL, the value passed in the struct hotplug_slot_info
  *	will be used when this value is requested by a user.
+ * @get_address: Called to get pci address of a slot.
+ *	If this field is NULL, the value passed in the struct hotplug_slot_info
+ *	will be used when this value is requested by a user.
  * @get_max_bus_speed: Called to get the max bus speed for a slot.
  *	If this field is NULL, the value passed in the struct hotplug_slot_info
  *	will be used when this value is requested by a user.
@@ -91,6 +115,7 @@ struct hotplug_slot_ops {
 	int (*get_attention_status)	(struct hotplug_slot *slot, u8 *value);
 	int (*get_latch_status)		(struct hotplug_slot *slot, u8 *value);
 	int (*get_adapter_status)	(struct hotplug_slot *slot, u8 *value);
+	int (*get_address)		(struct hotplug_slot *slot, u32 *value);
 	int (*get_max_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 	int (*get_cur_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 };
@@ -101,6 +126,7 @@ struct hotplug_slot_ops {
  * @attention_status: if the attention light is enabled or not (1/0)
  * @latch_status: if the latch (if any) is open or closed (1/0)
  * @adapter_present: if there is a pci board present in the slot or not (1/0)
+ * @address: (domain << 16 | bus << 8 | dev)
  *
  * Used to notify the hotplug pci core of the status of a specific slot.
  */
@@ -109,6 +135,7 @@ struct hotplug_slot_info {
 	u8	attention_status;
 	u8	latch_status;
 	u8	adapter_status;
+	u32	address;
 	enum pci_bus_speed	max_bus_speed;
 	enum pci_bus_speed	cur_bus_speed;
 };
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pci_hotplug_core.c linux-2.4.27-rc4/drivers/hotplug/pci_hotplug_core.c
--- linux-2.4.26/drivers/hotplug/pci_hotplug_core.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pci_hotplug_core.c	2004-07-30 16:30:39.000000000 +0000
@@ -74,6 +74,7 @@ struct hotplug_slot_core {
 	struct dentry	*attention_dentry;
 	struct dentry	*latch_dentry;
 	struct dentry	*adapter_dentry;
+	struct dentry	*address_dentry;
 	struct dentry	*test_dentry;
 	struct dentry	*max_bus_speed_dentry;
 	struct dentry	*cur_bus_speed_dentry;
@@ -111,6 +112,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 */
 };
 
 static int pcihpfs_statfs (struct super_block *sb, struct statfs *buf)
@@ -312,6 +314,15 @@ static struct file_operations presence_f
 	llseek:		default_file_lseek,
 };
 
+/* file ops for the "address" files */
+static ssize_t address_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
+static struct file_operations address_file_operations = {
+	read:		address_read_file,
+	write:		default_write_file,
+	open:		default_open,
+	llseek:		default_file_lseek,
+};
+
 /* file ops for the "max bus speed" files */
 static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
 static struct file_operations max_bus_speed_file_operations = {
@@ -566,6 +577,7 @@ GET_STATUS(power_status, u8)
 GET_STATUS(attention_status, u8)
 GET_STATUS(latch_status, u8)
 GET_STATUS(adapter_status, u8)
+GET_STATUS(address, u32)
 GET_STATUS(max_bus_speed, enum pci_bus_speed)
 GET_STATUS(cur_bus_speed, enum pci_bus_speed)
 
@@ -859,6 +871,52 @@ exit:
 	return retval;
 }
 
+static ssize_t address_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
+{
+	struct hotplug_slot *slot = file->private_data;
+	unsigned char *page;
+	int retval;
+	int len;
+	u32 address;
+
+	dbg("count = %d, offset = %lld\n", count, *offset);
+
+	if (*offset < 0)
+		return -EINVAL;
+	if (count <= 0)
+		return 0;
+	if (*offset != 0)
+		return 0;
+
+	if (slot == NULL) {
+		dbg("slot == NULL???\n");
+		return -ENODEV;
+	}
+
+	page = (unsigned char *)__get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	retval = get_address (slot, &address);
+	if (retval)
+		goto exit;
+	len = sprintf (page, "%04x:%02x:%02x\n",
+		       (address >> 16) & 0xffff,
+		       (address >> 8) & 0xff,
+		       address & 0xff);
+
+	if (copy_to_user (buf, page, len)) {
+		retval = -EFAULT;
+		goto exit;
+	}
+	*offset += len;
+	retval = len;
+
+exit:
+	free_page((unsigned long)page);
+	return retval;
+}
+
 static char *unknown_speed = "Unknown bus speed";
 
 static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
@@ -1055,6 +1113,13 @@ static int fs_add_slot (struct hotplug_s
 						core->dir_dentry, slot,
 						&presence_file_operations);
 
+		if (slot->ops->get_address)
+			core->address_dentry = 
+				fs_create_file ("address",
+						S_IFREG | S_IRUGO,
+						core->dir_dentry, slot,
+						&address_file_operations);
+
 		if (slot->ops->get_max_bus_speed)
 			core->max_bus_speed_dentry = 
 				fs_create_file ("max_bus_speed",
@@ -1092,6 +1157,8 @@ static void fs_remove_slot (struct hotpl
 			fs_remove_file (core->latch_dentry);
 		if (core->adapter_dentry)
 			fs_remove_file (core->adapter_dentry);
+		if (core->address_dentry)
+			fs_remove_file (core->address_dentry);
 		if (core->max_bus_speed_dentry)
 			fs_remove_file (core->max_bus_speed_dentry);
 		if (core->cur_bus_speed_dentry)
@@ -1243,6 +1310,9 @@ int pci_hp_change_slot_info (const char 
 	if ((core->adapter_dentry) &&
 	    (temp->info->adapter_status != info->adapter_status))
 		update_dentry_inode_time (core->adapter_dentry);
+	if ((core->address_dentry) &&
+	    (temp->info->address != info->address))
+		update_dentry_inode_time (core->address_dentry);
 	if ((core->cur_bus_speed_dentry) &&
 	    (temp->info->cur_bus_speed != info->cur_bus_speed))
 		update_dentry_inode_time (core->cur_bus_speed_dentry);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehp.h linux-2.4.27-rc4/drivers/hotplug/pciehp.h
--- linux-2.4.26/drivers/hotplug/pciehp.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehp.h	2004-07-30 16:32:06.000000000 +0000
@@ -0,0 +1,383 @@
+/*
+ * 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.o"
+#else
+	#define MY_NAME	THIS_MODULE->name
+#endif
+
+extern int pciehp_poll_mode;
+extern int pciehp_poll_time;
+extern int pciehp_debug;
+
+extern int pciehp_msi_quirk;
+
+/*#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;  PCI-E 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"
+
+/* 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_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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehp_core.c linux-2.4.27-rc4/drivers/hotplug/pciehp_core.c
--- linux-2.4.26/drivers/hotplug/pciehp_core.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehp_core.c	2004-07-30 16:30:00.000000000 +0000
@@ -0,0 +1,703 @@
+/*
+ * 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/tqueue.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.5"
+#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.o"
+
+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;
+
+	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: adapter 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) {
+			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[] __devinitdata = {
+	{
+	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();
+	} 
+
+	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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehp_ctrl.c linux-2.4.27-rc4/drivers/hotplug/pciehp_ctrl.c
--- linux-2.4.26/drivers/hotplug/pciehp_ctrl.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehp_ctrl.c	2004-07-30 16:26:01.000000000 +0000
@@ -0,0 +1,2629 @@
+/*
+ * 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/tqueue.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
+		 */
+		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		taskInfo->event_type = INT_PRESENCE_ON;
+	} else {
+		/*
+		 * Not Present
+		 */
+		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		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);
+	
+	dbg("%s: after power on\n", __FUNCTION__);
+
+	p_slot->hpc_ops->green_led_blink(p_slot);
+			
+	/* Wait for the command to complete */
+	wait_for_ctrl_irq(ctrl);
+	dbg("%s: after green_led_blink", __FUNCTION__);
+
+	/* 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: before check link status", __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();
+
+	/* New name */
+	strcpy(current->comm, "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);
+	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 Attn 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;
+	
+	dbg("%s: exit\n", __FUNCTION__);
+
+	return 0;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehp_hpc.c linux-2.4.27-rc4/drivers/hotplug/pciehp_hpc.c
--- linux-2.4.26/drivers/hotplug/pciehp_hpc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehp_hpc.c	2004-07-30 16:27:43.000000000 +0000
@@ -0,0 +1,1504 @@
+/*
+ * 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 void 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__);
+	}
+
+	dbg("%s : Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
+	retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE);
+	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|CMD_CMPL_INTR_ENABLE);
+	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;
+	//atten_led_state = (slot_ctrl & PWR_LED_CTRL) >> 8;
+
+	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;
+			//slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
+			break;
+		case 1:		/* turn on */
+			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
+			//slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
+			break;
+		case 2:		/* turn blink */
+			slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
+			//slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200; 
+			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;
+	//slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0040;
+
+	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;
+	//slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x00c0;
+
+	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;
+	//slot_cmd = (slot_ctrl & ~ATTN_LED_CTRL) | 0x0080;
+
+	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 void 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) {
+		dbg("%s: dev_id == NULL\n", __FUNCTION__);
+		return;
+	}
+
+	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;
+	}
+	if (!php_ctlr) {
+		dbg("%s: php_ctlr == NULL\n", __FUNCTION__);
+		return;
+	}
+	
+	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;
+	}
+	/* dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); */
+
+	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;
+	
+	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;
+		}
+
+		dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
+		dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+		temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_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;
+		}
+		dbg("%s: hp_register_write_word SLOT_CTRL with value %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__);
+			return;
+		}
+		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
+		
+		/* Clear command complete interrupt caused by this write */
+		temp_word = 0x1f;
+		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;
+		}
+		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); 	
+	}
+
+	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 = 0x1F;
+	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;
+	}
+
+	/* 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;
+		}
+		dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
+		dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
+		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;
+		}	
+		dbg("%s: hp_register_write_word SLOT_CTRL with value %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__);
+			return;
+		}
+		dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status); 
+		
+		/* Clear command complete interrupt caused by this write */
+		temp_word = 0x1F;
+		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;
+		}
+		dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word); 	
+	}
+	return;
+}
+
+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));
+
+	dbg("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 & ~CMD_CMPL_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);
+	
+	temp_word = 0x1F; /* Clear all events */
+	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__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
+
+	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 
+		if (!pciehp_msi_quirk) {	
+			rc = pci_enable_msi(pdev);
+			if (rc) {
+				info("Can't get msi for the hotplug controller\n");
+				info("Use INTx for the hotplug controller\n");
+				dbg("%s: rc = %x\n", __FUNCTION__, rc);
+			} else
+				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;
+
+	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);
+	
+	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: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, 
+		SLOT_STATUS, slot_status);
+	
+	temp_word =  0x1F; /* Clear all events */
+	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__);
+		goto abort_free_ctlr;
+	}
+	dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, 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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehp_pci.c linux-2.4.27-rc4/drivers/hotplug/pciehp_pci.c
--- linux-2.4.26/drivers/hotplug/pciehp_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehp_pci.c	2004-07-30 16:29:51.000000000 +0000
@@ -0,0 +1,1052 @@
+/*
+ * 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/tqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "pciehp.h"
+#ifndef CONFIG_IA64
+#include "../../arch/i386/kernel/pci-i386.h"    /* horrible hack showing how processor dependant we are... */
+#endif
+
+static int is_pci_dev_in_use(struct pci_dev* dev) 
+{
+	/* 
+	 * dev->driver will be set if the device is in use by a new-style 
+	 * driver -- otherwise, check the device's regions to see if any
+	 * driver has claimed them
+	 */
+
+	int i, inuse=0;
+
+	if (dev->driver) return 1; /* Assume driver feels responsible */
+
+	for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
+		if (!pci_resource_start(dev, i))
+			continue;
+
+		if (pci_resource_flags(dev, i) & IORESOURCE_IO)
+			inuse = check_region(pci_resource_start(dev, i),
+					     pci_resource_len(dev, i));
+		else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
+			inuse = check_mem_region(pci_resource_start(dev, i),
+						 pci_resource_len(dev, i));
+	}
+
+	return inuse;
+
+}
+
+
+static int pci_hp_remove_device(struct pci_dev *dev)
+{
+	if (is_pci_dev_in_use(dev)) {
+		err("***Cannot safely power down device -- "
+		       "it appears to be in use***\n");
+		return -EBUSY;
+	}
+	dbg("%s: dev %p\n", __FUNCTION__, dev);
+	pci_remove_device(dev);
+	return 0;
+}
+
+
+static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) 
+{
+	struct pci_bus* bus = wrapped_bus->bus;
+	struct pci_dev* dev = wrapped_dev->dev;
+	struct pci_func *temp_func;
+	int i=0;
+
+	/* We need to fix up the hotplug function representation with the linux representation */
+	do {
+		temp_func = pciehp_slot_find(dev->bus->number, dev->devfn >> 3, i++);
+	} while (temp_func && (temp_func->function != (dev->devfn & 0x07)));
+
+	if (temp_func) {
+		temp_func->pci_dev = dev;
+	} else {
+		/* We did not even find a hotplug rep of the function, create it
+		 * This code might be taken out if we can guarantee the creation of functions
+		 * in parallel (hotplug and Linux at the same time).
+		 */
+		dbg("@@@@@@@@@@@ pciehp_slot_create in %s\n", __FUNCTION__);
+		temp_func = pciehp_slot_create(bus->number);
+		if (temp_func == NULL)
+			return -ENOMEM;
+		temp_func->pci_dev = dev;
+	}
+
+	/* Create /proc/bus/pci proc entry for this device and bus device is on */
+	/* Notify the drivers of the change */
+	if (temp_func->pci_dev) {
+		dbg("%s: PCI_ID=%04X:%04X\n", __FUNCTION__, temp_func->pci_dev->vendor,
+			temp_func->pci_dev->device); 
+		dbg("%s: PCI BUS %x DEVFN %x\n", __FUNCTION__, 
+			temp_func->pci_dev->bus->number, temp_func->pci_dev->devfn); 
+		dbg("%s: PCI_SLOT_NAME=%s\n", __FUNCTION__, 
+			temp_func->pci_dev->slot_name);
+		//pci_enable_device(temp_func->pci_dev);
+		//dbg("%s: after calling pci_enable_device, irq = %x\n", 
+		//	__FUNCTION__, temp_func->pci_dev->irq); 
+		pci_proc_attach_device(temp_func->pci_dev);
+		pci_announce_device_to_drivers(temp_func->pci_dev);
+	}
+
+	return 0;
+}
+
+
+static int unconfigure_visit_pci_dev_phase2 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) 
+{
+	struct pci_dev* dev = wrapped_dev->dev;
+
+	struct pci_func *temp_func;
+	int i=0;
+
+	dbg("%s: dev %p dev->bus->number %x bus->number %x\n", __FUNCTION__, wrapped_dev, 
+		dev->bus->number, wrapped_bus->bus->number);
+
+	/* We need to remove the hotplug function representation with the linux representation */
+	do {
+		temp_func = pciehp_slot_find(dev->bus->number, dev->devfn >> 3, i++);
+		if (temp_func) {
+			dbg("%s: temp_func->function = %d\n", __FUNCTION__, temp_func->function);
+		}
+	} while (temp_func && (temp_func->function != (dev->devfn & 0x07)));
+
+	/* Now, remove the Linux Representation */
+	if (dev) {
+		if (pci_hp_remove_device(dev) == 0) {
+			kfree(dev); /* Now, remove */
+		} else {
+			return -1; /* problems while freeing, abort visitation */
+		}
+	}
+
+	if (temp_func) {
+		temp_func->pci_dev = NULL;
+	} else {
+		dbg("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn);
+	}
+
+	return 0;
+}
+
+
+static int unconfigure_visit_pci_bus_phase2 (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev) 
+{
+	struct pci_bus* bus = wrapped_bus->bus;
+
+	/* The cleanup code for proc entries regarding buses should be in the kernel...*/
+	if (bus->procdir)
+		dbg("detach_pci_bus %s\n", bus->procdir->name);
+	pci_proc_detach_bus(bus);
+	/* The cleanup code should live in the kernel... */
+	bus->self->subordinate = NULL;
+	/* unlink from parent bus */
+	list_del(&bus->node);
+
+	/* Now, remove */
+	if (bus)
+		kfree(bus);
+
+	return 0;
+}
+
+
+static int unconfigure_visit_pci_dev_phase1 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) 
+{
+	struct pci_dev* dev = wrapped_dev->dev;
+	int rc;
+
+	dbg("attempting removal of driver for device (%x, %x, %x)\n", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	/* Now, remove the Linux Driver Representation */
+	if (dev->driver) {
+		if (dev->driver->remove) {
+			dev->driver->remove(dev);
+			dbg("driver was properly removed\n");
+		}
+		dev->driver = NULL;
+	}
+
+	rc = is_pci_dev_in_use(dev);
+	if (rc)
+		info("%s: device still in use\n", __FUNCTION__);
+	return rc;
+}
+
+
+static struct pci_visit configure_functions = {
+	.visit_pci_dev =	configure_visit_pci_dev,
+};
+
+
+static struct pci_visit unconfigure_functions_phase1 = {
+	.post_visit_pci_dev =	unconfigure_visit_pci_dev_phase1
+};
+
+static struct pci_visit unconfigure_functions_phase2 = {
+	.post_visit_pci_bus =	unconfigure_visit_pci_bus_phase2,               
+	.post_visit_pci_dev =	unconfigure_visit_pci_dev_phase2
+};
+
+
+int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)  
+{
+	unsigned char bus;
+	struct pci_dev dev0;
+	struct pci_bus *child;
+	struct pci_dev* temp;
+	int rc = 0;
+
+	struct pci_dev_wrapped wrapped_dev;
+	struct pci_bus_wrapped wrapped_bus;
+	memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
+	memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+
+	memset(&dev0, 0, sizeof(struct pci_dev));
+	
+	dbg("%s: func->pci_dev %p bus %x dev %x func %x\n", __FUNCTION__,
+		func->pci_dev, func->bus, func->device, func->function);
+	if (func->pci_dev == NULL)
+		func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7));
+	dbg("%s: func->pci_dev %p bus %x dev %x func %x\n", __FUNCTION__,
+		func->pci_dev, func->bus, func->device, func->function);
+	if (func->pci_dev != NULL) {
+		dbg("%s: pci_dev %p bus %x devfn %x\n", __FUNCTION__,
+			func->pci_dev, func->pci_dev->bus->number, func->pci_dev->devfn);
+	}
+	/* Still NULL ? Well then scan for it ! */
+	if (func->pci_dev == NULL) {
+		dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
+		dev0.bus = ctrl->pci_dev->subordinate;
+		dbg("%s: dev0.bus %p\n", __FUNCTION__, dev0.bus);
+		dev0.bus->number = func->bus;
+		dbg("%s: dev0.bus->number %x\n", __FUNCTION__, func->bus);
+		dev0.devfn = PCI_DEVFN(func->device, func->function);
+		dev0.sysdata = ctrl->pci_dev->sysdata;
+
+		/* This will generate pci_dev structures for all functions, 
+		 * but we will only call this case when lookup fails
+		 */
+		func->pci_dev = pci_scan_slot(&dev0);
+		dbg("%s: func->pci_dev %p\n", __FUNCTION__, func->pci_dev);
+		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);
+		dbg("%s: bridge device - func->pci_dev->bus %p func->pci_dev %p bus %x\n", 
+			__FUNCTION__, func->pci_dev->bus,func->pci_dev,bus);
+		pci_do_scan_bus(child);
+
+	}
+
+	temp = func->pci_dev;
+
+	if (temp) {
+		wrapped_dev.dev = temp;
+		wrapped_bus.bus = temp->bus;
+		rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
+	}
+	return rc;
+}
+
+
+int pciehp_unconfigure_device(struct pci_func* func) 
+{
+	int rc = 0;
+	int j;
+	struct pci_dev_wrapped wrapped_dev;
+	struct pci_bus_wrapped wrapped_bus;
+	
+	memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
+	memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+
+	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);
+		dbg("%s: temp %p\n", __FUNCTION__, temp);
+		if (temp) {
+			wrapped_dev.dev = temp;
+			wrapped_bus.bus = temp->bus;
+			rc = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus);
+			if (rc)
+				break;
+
+			rc = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus);
+			if (rc)
+				break;
+		}
+	}
+	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) && !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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehprm.h linux-2.4.27-rc4/drivers/hotplug/pciehprm.h
--- linux-2.4.26/drivers/hotplug/pciehprm.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehprm.h	2004-07-30 16:29:21.000000000 +0000
@@ -0,0 +1,54 @@
+/*
+ * 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);
+int pciehprm_get_interrupt(int seg, int bus, int device, int pin, int *irq);
+
+#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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehprm_acpi.c linux-2.4.27-rc4/drivers/hotplug/pciehprm_acpi.c
--- linux-2.4.26/drivers/hotplug/pciehprm_acpi.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehprm_acpi.c	2004-07-30 16:31:09.000000000 +0000
@@ -0,0 +1,1696 @@
+/*
+ * 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)
+		return;
+
+	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");
+	if (acpi_bridges_head)
+		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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehprm_nonacpi.c linux-2.4.27-rc4/drivers/hotplug/pciehprm_nonacpi.c
--- linux-2.4.26/drivers/hotplug/pciehprm_nonacpi.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehprm_nonacpi.c	2004-07-30 16:25:20.000000000 +0000
@@ -0,0 +1,497 @@
+/*
+ * 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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/pciehprm_nonacpi.h linux-2.4.27-rc4/drivers/hotplug/pciehprm_nonacpi.h
--- linux-2.4.26/drivers/hotplug/pciehprm_nonacpi.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/pciehprm_nonacpi.h	2004-07-30 16:28:00.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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchp.h linux-2.4.27-rc4/drivers/hotplug/shpchp.h
--- linux-2.4.26/drivers/hotplug/shpchp.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchp.h	2004-07-30 16:27:26.000000000 +0000
@@ -0,0 +1,464 @@
+/*
+ * 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.o"
+#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"
+
+/* 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 2 second */
+		schedule_timeout(2*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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchp_core.c linux-2.4.27-rc4/drivers/hotplug/shpchp_core.c
--- linux-2.4.26/drivers/hotplug/shpchp_core.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchp_core.c	2004-07-30 16:26:09.000000000 +0000
@@ -0,0 +1,700 @@
+/*
+ * 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/tqueue.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.o"
+
+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 */
+
+	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;
+	}
+
+	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[] __devinitdata = {
+	{
+	.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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchp_ctrl.c linux-2.4.27-rc4/drivers/hotplug/shpchp_ctrl.c
--- linux-2.4.26/drivers/hotplug/shpchp_ctrl.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchp_ctrl.c	2004-07-30 16:31:39.000000000 +0000
@@ -0,0 +1,3071 @@
+/*
+ * 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/tqueue.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;
+	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
+		 */
+		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		taskInfo->event_type = INT_PRESENCE_ON;
+	} else {
+		/*
+		 * Not Present
+		 */
+		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		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) {
+		dbg("%s: Is a bridge\n", __FUNCTION__);
+		return 1;
+	} else {
+		dbg("%s: Not a bridge\n", __FUNCTION__);
+		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)  {
+					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) {
+					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();
+
+	/* New name */
+	strcpy(current->comm, "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;
+	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);
+	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;
+				}
+				/* Button Pressed (No action on 1st press...) */
+				else if (ctrl->event_queue[loop].event_type == INT_BUTTON_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);
+				}
+				/***********POWER FAULT********************/
+				else if (ctrl->event_queue[loop].event_type == INT_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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchp_hpc.c linux-2.4.27-rc4/drivers/hotplug/shpchp_hpc.c
--- linux-2.4.26/drivers/hotplug/shpchp_hpc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchp_hpc.c	2004-07-30 16:28:06.000000000 +0000
@@ -0,0 +1,1615 @@
+/*
+ * 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		0x9
+#define PCIX_100MHZ_266		0x0a
+#define PCIX_133MHZ_266		0x0b
+#define PCIX_66MHZ_533		0x11
+#define PCIX_100MHZ_533		0x12
+#define PCIX_133MHZ_533		0x13
+
+/* 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 void 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) ? 0 : 1;	/* 0 -> close; 1 -> open */
+
+	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 9:
+			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 void 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;
+
+	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;
+		ctrl = (struct controller *)php_ctlr->callback_instance_id;
+	}
+
+	if (!ctrl)
+		return;
+
+	if (!php_ctlr || !php_ctlr->creg)
+		return;
+
+	/* Check to see if it was our interrupt */
+	intr_loc = readl(php_ctlr->creg + INTR_LOC);  
+
+	if (!intr_loc)
+		return;
+
+	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
+
+	if (!shpchp_poll_mode) {
+		/* 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;
+	}
+
+	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); 
+		}
+	}
+
+	if (!shpchp_poll_mode) {
+		/* 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;
+}
+
+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;
+		}
+		dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset);
+
+		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);
+	/* Ssetup 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) {
+			info("Can't get msi for the hotplug controller\n");
+			info("Use INTx for the hotplug controller\n");
+			dbg("%s: rc = %x\n", __FUNCTION__, rc);
+		} else
+			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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchp_pci.c linux-2.4.27-rc4/drivers/hotplug/shpchp_pci.c
--- linux-2.4.26/drivers/hotplug/shpchp_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchp_pci.c	2004-07-30 16:26:26.000000000 +0000
@@ -0,0 +1,1043 @@
+/*
+ * 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/tqueue.h>
+#include <linux/proc_fs.h>
+#include <linux/pci.h>
+#include "shpchp.h"
+#ifndef CONFIG_IA64
+#include "../../arch/i386/kernel/pci-i386.h"    /* horrible hack showing how processor dependant we are... */
+#endif
+
+static int is_pci_dev_in_use(struct pci_dev* dev) 
+{
+	/* 
+	 * dev->driver will be set if the device is in use by a new-style 
+	 * driver -- otherwise, check the device's regions to see if any
+	 * driver has claimed them
+	 */
+
+	int i, inuse=0;
+
+	if (dev->driver) return 1; /* Assume driver feels responsible */
+
+	for (i = 0; !dev->driver && !inuse && (i < 6); i++) {
+		if (!pci_resource_start(dev, i))
+			continue;
+
+		if (pci_resource_flags(dev, i) & IORESOURCE_IO)
+			inuse = check_region(pci_resource_start(dev, i),
+					     pci_resource_len(dev, i));
+		else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
+			inuse = check_mem_region(pci_resource_start(dev, i),
+						 pci_resource_len(dev, i));
+	}
+
+	return inuse;
+
+}
+
+
+static int pci_hp_remove_device(struct pci_dev *dev)
+{
+	if (is_pci_dev_in_use(dev)) {
+		err("***Cannot safely power down device -- "
+		       "it appears to be in use***\n");
+		return -EBUSY;
+	}
+	pci_remove_device(dev);
+	return 0;
+}
+
+
+static int configure_visit_pci_dev (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) 
+{
+	struct pci_bus* bus = wrapped_bus->bus;
+	struct pci_dev* dev = wrapped_dev->dev;
+	struct pci_func *temp_func;
+	int i=0;
+
+	dbg("%s: Enter\n", __FUNCTION__);
+	/* We need to fix up the hotplug function representation with the linux representation */
+	do {
+		temp_func = shpchp_slot_find(dev->bus->number, dev->devfn >> 3, i++);
+		dbg("%s: i %d temp_func %p, bus %x dev %x\n", __FUNCTION__, i, temp_func, 
+			dev->bus->number, dev->devfn >>3);
+	} while (temp_func && (temp_func->function != (dev->devfn & 0x07)));
+
+	if (temp_func) {
+		temp_func->pci_dev = dev;
+		dbg("%s: dev %p dev->irq %x\n", __FUNCTION__, dev, dev->irq);
+	} else {
+		/* We did not even find a hotplug rep of the function, create it
+		 * This code might be taken out if we can guarantee the creation of functions
+		 * in parallel (hotplug and Linux at the same time).
+		 */
+		dbg("@@@@@@@@@@@ shpchp_slot_create in %s\n", __FUNCTION__);
+		temp_func = shpchp_slot_create(bus->number);
+		if (temp_func == NULL)
+			return -ENOMEM;
+		temp_func->pci_dev = dev;
+	}
+
+	/* Create /proc/bus/pci proc entry for this device and bus device is on */
+	/* Notify the drivers of the change */
+	if (temp_func->pci_dev) {
+		dbg("%s: PCI_ID=%04X:%04X\n", __FUNCTION__, temp_func->pci_dev->vendor,
+			temp_func->pci_dev->device);
+		dbg("%s: PCI BUS %x DEVFN %x\n", __FUNCTION__, temp_func->pci_dev->bus->number,
+			temp_func->pci_dev->devfn);
+		dbg("%s: PCI_SLOT_NAME %s\n", __FUNCTION__, 
+			temp_func->pci_dev->slot_name);
+		pci_enable_device(temp_func->pci_dev);
+		pci_proc_attach_device(temp_func->pci_dev);
+		pci_announce_device_to_drivers(temp_func->pci_dev);
+	}
+
+	return 0;
+}
+
+
+static int unconfigure_visit_pci_dev_phase2 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) 
+{
+	struct pci_dev* dev = wrapped_dev->dev;
+
+	struct pci_func *temp_func;
+	int i=0;
+
+	/* We need to remove the hotplug function representation with the linux representation */
+	do {
+		temp_func = shpchp_slot_find(dev->bus->number, dev->devfn >> 3, i++);
+		if (temp_func) {
+			dbg("temp_func->function = %d\n", temp_func->function);
+		}
+	} while (temp_func && (temp_func->function != (dev->devfn & 0x07)));
+
+	/* Now, remove the Linux Representation */
+	if (dev) {
+		if (pci_hp_remove_device(dev) == 0) {
+			kfree(dev); /* Now, remove */
+		} else {
+			return -1; /* problems while freeing, abort visitation */
+		}
+	}
+
+	if (temp_func) {
+		temp_func->pci_dev = NULL;
+	} else {
+		dbg("No pci_func representation for bus, devfn = %d, %x\n", dev->bus->number, dev->devfn);
+	}
+
+	return 0;
+}
+
+
+static int unconfigure_visit_pci_bus_phase2 (struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_dev) 
+{
+	struct pci_bus* bus = wrapped_bus->bus;
+
+	/* The cleanup code for proc entries regarding buses should be in the kernel...*/
+	if (bus->procdir)
+		dbg("detach_pci_bus %s\n", bus->procdir->name);
+	pci_proc_detach_bus(bus);
+	/* The cleanup code should live in the kernel... */
+	bus->self->subordinate = NULL;
+	/* Unlink from parent bus */
+	list_del(&bus->node);
+
+	/* Now, remove */
+	if (bus)
+		kfree(bus);
+
+	return 0;
+}
+
+
+static int unconfigure_visit_pci_dev_phase1 (struct pci_dev_wrapped *wrapped_dev, struct pci_bus_wrapped *wrapped_bus) 
+{
+	struct pci_dev* dev = wrapped_dev->dev;
+	int rc;
+
+	dbg("attempting removal of driver for device (%x, %x, %x)\n", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	/* Now, remove the Linux Driver Representation */
+	if (dev->driver) {
+		if (dev->driver->remove) {
+			dev->driver->remove(dev);
+			dbg("driver was properly removed\n");
+		}
+		dev->driver = NULL;
+	}
+
+	rc = is_pci_dev_in_use(dev);
+	if (rc)
+		info("%s: device still in use\n", __FUNCTION__);
+	return rc;
+}
+
+
+static struct pci_visit configure_functions = {
+	.visit_pci_dev =	configure_visit_pci_dev,
+};
+
+
+static struct pci_visit unconfigure_functions_phase1 = {
+	.post_visit_pci_dev =	unconfigure_visit_pci_dev_phase1
+};
+
+static struct pci_visit unconfigure_functions_phase2 = {
+	.post_visit_pci_bus =	unconfigure_visit_pci_bus_phase2,               
+	.post_visit_pci_dev =	unconfigure_visit_pci_dev_phase2
+};
+
+
+int shpchp_configure_device (struct controller* ctrl, struct pci_func* func)  
+{
+	unsigned char bus;
+	struct pci_dev dev0;
+	struct pci_bus *child;
+	struct pci_dev* temp;
+	int rc = 0;
+
+	struct pci_dev_wrapped wrapped_dev;
+	struct pci_bus_wrapped wrapped_bus;
+	
+	dbg("%s: Enter\n", __FUNCTION__);
+	memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
+	memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+
+	memset(&dev0, 0, sizeof(struct pci_dev));
+
+	dbg("%s: func->pci_dev %p\n", __FUNCTION__, func->pci_dev);
+	if (func->pci_dev != NULL)
+		dbg("%s: func->pci_dev->irq %x\n", __FUNCTION__, func->pci_dev->irq);
+	if (func->pci_dev == NULL)
+		func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7));
+	dbg("%s: after pci_find_slot, func->pci_dev %p\n", __FUNCTION__, func->pci_dev);
+	if (func->pci_dev != NULL)
+		dbg("%s: after pci_find_slot, func->pci_dev->irq %x\n", __FUNCTION__, func->pci_dev->irq);
+
+	/* Still NULL ? Well then scan for it ! */
+	if (func->pci_dev == NULL) {
+		dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
+		dev0.bus = ctrl->pci_dev->subordinate;
+		dbg("%s: dev0.bus %p\n", __FUNCTION__, dev0.bus);
+		dev0.bus->number = func->bus;
+		dbg("%s: dev0.bus->number %x\n", __FUNCTION__, func->bus);
+		dev0.devfn = PCI_DEVFN(func->device, func->function);
+		dev0.sysdata = ctrl->pci_dev->sysdata;
+
+		/* this will generate pci_dev structures for all functions, 
+		 * but we will only call this case when lookup fails
+		 */
+		dbg("%s: dev0.irq %x\n", __FUNCTION__, dev0.irq);
+		func->pci_dev = pci_scan_slot(&dev0);
+		dbg("%s: func->pci_dev->irq %x\n", __FUNCTION__, 
+			func->pci_dev->irq);
+		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);
+		dbg("%s: calling pci_do_scan_bus\n", __FUNCTION__);
+		pci_do_scan_bus(child);
+
+	}
+
+	temp = func->pci_dev;
+	dbg("%s: func->pci_dev->irq %x\n", __FUNCTION__, func->pci_dev->irq);
+
+	if (temp) {
+		wrapped_dev.dev = temp;
+		wrapped_bus.bus = temp->bus;
+		rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
+	}
+		
+	dbg("%s: Exit\n", __FUNCTION__);
+	return rc;
+}
+
+
+int shpchp_unconfigure_device(struct pci_func* func) 
+{
+	int rc = 0;
+	int j;
+	struct pci_dev_wrapped wrapped_dev;
+	struct pci_bus_wrapped wrapped_bus;
+	
+	memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
+	memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
+
+	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) {
+			wrapped_dev.dev = temp;
+			wrapped_bus.bus = temp->bus;
+			rc = pci_visit_dev(&unconfigure_functions_phase1, &wrapped_dev, &wrapped_bus);
+			if (rc)
+				break;
+
+			rc = pci_visit_dev(&unconfigure_functions_phase2, &wrapped_dev, &wrapped_bus);
+			if (rc)
+				break;
+		}
+	}
+	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) && !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("%s: new_slot->config_space[%x] = %x\n", __FUNCTION__, 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]));
+				dbg("%s: new_slot->config_space[%x] = %x\n", __FUNCTION__,cloop, 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;
+
+	dbg("%s: \n", __FUNCTION__);
+
+	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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchprm.h linux-2.4.27-rc4/drivers/hotplug/shpchprm.h
--- linux-2.4.26/drivers/hotplug/shpchprm.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchprm.h	2004-07-30 16:25:57.000000000 +0000
@@ -0,0 +1,57 @@
+/*
+ * 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_interrupt(int seg, int bus, int device, int pin, int *irq);
+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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchprm_acpi.c linux-2.4.27-rc4/drivers/hotplug/shpchprm_acpi.c
--- linux-2.4.26/drivers/hotplug/shpchprm_acpi.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchprm_acpi.c	2004-07-30 16:32:23.000000000 +0000
@@ -0,0 +1,1696 @@
+/*
+ * 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;
+	};
+
+	/* 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)
+		return;
+
+	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");
+	if (acpi_bridges_head)
+		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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchprm_legacy.c linux-2.4.27-rc4/drivers/hotplug/shpchprm_legacy.c
--- linux-2.4.26/drivers/hotplug/shpchprm_legacy.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchprm_legacy.c	2004-07-30 16:30:39.000000000 +0000
@@ -0,0 +1,444 @@
+/*
+ * 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;
+}
+
+/*
+ * 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;
+			}
+		}
+
+		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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchprm_legacy.h linux-2.4.27-rc4/drivers/hotplug/shpchprm_legacy.h
--- linux-2.4.26/drivers/hotplug/shpchprm_legacy.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchprm_legacy.h	2004-07-30 16:26:24.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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchprm_nonacpi.c linux-2.4.27-rc4/drivers/hotplug/shpchprm_nonacpi.c
--- linux-2.4.26/drivers/hotplug/shpchprm_nonacpi.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchprm_nonacpi.c	2004-07-30 16:28:51.000000000 +0000
@@ -0,0 +1,430 @@
+/*
+ * 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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/hotplug/shpchprm_nonacpi.h linux-2.4.27-rc4/drivers/hotplug/shpchprm_nonacpi.h
--- linux-2.4.26/drivers/hotplug/shpchprm_nonacpi.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/hotplug/shpchprm_nonacpi.h	2004-07-30 16:31:57.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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/Config.in linux-2.4.27-rc4/drivers/ide/Config.in
--- linux-2.4.26/drivers/ide/Config.in	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/Config.in	2004-07-30 16:31:26.000000000 +0000
@@ -63,11 +63,11 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; the
 	    fi
 	    dep_tristate '    NS87415 chipset support' CONFIG_BLK_DEV_NS87415 $CONFIG_BLK_DEV_IDEDMA_PCI
 	    dep_tristate '    OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 $CONFIG_EXPERIMENTAL
-	    dep_tristate '    PROMISE PDC202{46|62|65|67} support' CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI
-	    dep_mbool     '      Special UDMA Feature' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI
-	    dep_tristate '    PROMISE PDC202{68|69|70|71|75|76|77} support' CONFIG_BLK_DEV_PDC202XX_NEW $CONFIG_BLK_DEV_IDEDMA_PCI
+	    dep_tristate '    Promise PDC202{46|62|65|67} support' CONFIG_BLK_DEV_PDC202XX_OLD $CONFIG_BLK_DEV_IDEDMA_PCI
+	    dep_mbool     '      Force (U)DMA burst transfers' CONFIG_PDC202XX_BURST $CONFIG_BLK_DEV_PDC202XX_OLD
+	    dep_tristate '    Promise PDC202{68|69|70|71|75|76|77} support' CONFIG_BLK_DEV_PDC202XX_NEW $CONFIG_BLK_DEV_IDEDMA_PCI
 	    if [ "$CONFIG_BLK_DEV_PDC202XX_OLD" = "y" -o "$CONFIG_BLK_DEV_PDC202XX_OLD" = "m" -o "$CONFIG_BLK_DEV_PDC202XX_NEW" = "y" -o "$CONFIG_BLK_DEV_PDC202XX_NEW" = "m" ]; then
-	        bool     '    Special FastTrak Feature' CONFIG_PDC202XX_FORCE
+	        bool     '    Ignore BIOS port disabled setting on FastTrak' CONFIG_PDC202XX_FORCE
 	    fi
 	    dep_tristate '    RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 $CONFIG_X86
 	    dep_tristate '    SCx200 chipset support' CONFIG_BLK_DEV_SC1200 $CONFIG_BLK_DEV_IDEDMA_PCI
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/ide-cd.c linux-2.4.27-rc4/drivers/ide/ide-cd.c
--- linux-2.4.26/drivers/ide/ide-cd.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/ide-cd.c	2004-07-30 16:28:00.000000000 +0000
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder@fnald0.fnal.gov>
  * Copyright (C) 1996-1998  Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998-2000  Jens Axboe <axboe@suse.de>
+ * Copyright (C) 1998-2004  Jens Axboe <axboe@suse.de>
+ * Copyright (C) 2004 Iomega Corp
  *
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
@@ -2683,7 +2684,7 @@ static struct cdrom_device_ops ide_cdrom
 				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
 				CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R |
 				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
-				CDC_GENERIC_PACKET,
+				CDC_GENERIC_PACKET | CDC_RAM,
 	generic_packet:		ide_cdrom_packet,
 };
 
@@ -2718,6 +2719,8 @@ static int ide_cdrom_register (ide_drive
 		devinfo->mask |= CDC_PLAY_AUDIO;
 	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
 		devinfo->mask |= CDC_CLOSE_TRAY;
+	if (!CDROM_CONFIG_FLAGS(drive)->ram)
+		devinfo->mask |= CDC_RAM;
 
 	devinfo->de = devfs_register(drive->de, "cd", DEVFS_FL_DEFAULT,
 				     HWIF(drive)->major, minor,
@@ -2766,7 +2769,7 @@ int ide_cdrom_probe_capabilities (ide_dr
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
 	struct atapi_capabilities_page cap;
-	int nslots = 1;
+	int nslots = 1, ram_write = 0;
 
 	if (CDROM_CONFIG_FLAGS(drive)->nec260) {
 		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;                       
@@ -2776,7 +2779,9 @@ int ide_cdrom_probe_capabilities (ide_dr
 
 	if (ide_cdrom_get_capabilities(drive, &cap))
 		return 0;
-
+	cdrom_is_random_writable(cdi, &ram_write);
+	if (ram_write) 
+		CDROM_CONFIG_FLAGS(drive)->ram = 1;
 	if (cap.lock == 0)
 		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
 	if (cap.eject)
@@ -2789,8 +2794,10 @@ int ide_cdrom_probe_capabilities (ide_dr
 		CDROM_CONFIG_FLAGS(drive)->test_write = 1;
 	if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
 		CDROM_CONFIG_FLAGS(drive)->dvd = 1;
-	if (cap.dvd_ram_write)
+	if (cap.dvd_ram_write) {
 		CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
+		CDROM_CONFIG_FLAGS(drive)->ram = 1;
+	}
 	if (cap.dvd_r_write)
 		CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
 	if (cap.audio_play)
@@ -3000,7 +3007,8 @@ int ide_cdrom_setup (ide_drive_t *drive)
 
 	nslots = ide_cdrom_probe_capabilities (drive);
 
-	if (CDROM_CONFIG_FLAGS(drive)->dvd_ram)
+	if ((CDROM_CONFIG_FLAGS(drive)->dvd_ram) ||
+	    (CDROM_CONFIG_FLAGS(drive)->ram))
 		set_device_ro(MKDEV(HWIF(drive)->major, minor), 0);
 
 #if 0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/ide-cd.h linux-2.4.27-rc4/drivers/ide/ide-cd.h
--- linux-2.4.26/drivers/ide/ide-cd.h	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/ide-cd.h	2004-07-30 16:31:27.000000000 +0000
@@ -2,7 +2,8 @@
  *  linux/drivers/ide/ide_cd.h
  *
  *  Copyright (C) 1996-98  Erik Andersen
- *  Copyright (C) 1998-2000 Jens Axboe
+ *  Copyright (C) 1998-2004 Jens Axboe
+ *  Copyright (C) 2004 Iomega Corp
  */
 #ifndef _IDE_CD_H
 #define _IDE_CD_H
@@ -75,6 +76,7 @@ struct ide_cd_config_flags {
 	__u8 dvd		: 1; /* Drive is a DVD-ROM */
 	__u8 dvd_r		: 1; /* Drive can write DVD-R */
 	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
+	__u8 ram		: 1; /* generic WRITE (dvd-ram/mrw) */
 	__u8 test_write		: 1; /* Drive can fake writes */
 	__u8 supp_disc_present	: 1; /* Changer can report exact contents
 					of slots. */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/ide-disk.c linux-2.4.27-rc4/drivers/ide/ide-disk.c
--- linux-2.4.26/drivers/ide/ide-disk.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/ide-disk.c	2004-07-30 16:24:28.000000000 +0000
@@ -1161,15 +1161,15 @@ static void init_idedisk_capacity (ide_d
 {
 	struct hd_driveid *id = drive->id;
 	unsigned long capacity = drive->cyl * drive->head * drive->sect;
-	unsigned long set_max = idedisk_read_native_max_address(drive);
+	int have_setmax = idedisk_supports_host_protected_area(drive);
+	unsigned long set_max =
+		(have_setmax ? idedisk_read_native_max_address(drive) : 0);
 	unsigned long long capacity_2 = capacity;
 	unsigned long long set_max_ext;
 
 	drive->capacity48 = 0;
 	drive->select.b.lba = 0;
 
-	(void) idedisk_supports_host_protected_area(drive);
-
 	if (id->cfs_enable_2 & 0x0400) {
 		capacity_2 = id->lba_capacity_2;
 		drive->head		= drive->bios_head = 255;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/ide.c linux-2.4.27-rc4/drivers/ide/ide.c
--- linux-2.4.26/drivers/ide/ide.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/ide.c	2004-07-30 16:31:52.000000000 +0000
@@ -2993,7 +2993,24 @@ static int ide_notify_reboot (struct not
 
 			/* set the drive to standby */
 			printk("%s ", drive->name);
+#ifdef	CONFIG_ALPHA
+			/* On Alpha, halt(8) doesn't actually turn the machine
+			   off, it puts you into the sort of firmware monitor.
+			   Typically, it's used to boot another kernel image,
+			   so it's not much different from reboot(8).
+			   Therefore, we don't need to spin down the disk in
+			   this case, especially since Alpha firmware doesn't
+			   handle disks in standby mode properly.
+			   On the other hand, it's reasonably safe to turn
+			   the power off when the shutdown process reaches
+			   the firmware prompt, as the firmware initialization
+			   takes rather long time - at least 10 seconds,
+			   which should be sufficient for the disk to expire
+			   its write cache. */
+			if (event == SYS_POWER_OFF)
+#else
 			if (event != SYS_RESTART)
+#endif
 				if (DRIVER(drive)->standby(drive))
 					continue;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/aec62xx.c linux-2.4.27-rc4/drivers/ide/pci/aec62xx.c
--- linux-2.4.26/drivers/ide/pci/aec62xx.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/aec62xx.c	2004-07-30 16:31:15.000000000 +0000
@@ -356,13 +356,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		aec62xx_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 static int aec62xx_irq_timeout (ide_drive_t *drive)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/amd74xx.c linux-2.4.27-rc4/drivers/ide/pci/amd74xx.c
--- linux-2.4.26/drivers/ide/pci/amd74xx.c	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/amd74xx.c	2004-07-30 16:29:12.000000000 +0000
@@ -1,7 +1,8 @@
 /*
  * Version 2.13
  *
- * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s IDE driver for Linux.
+ * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
+ * IDE driver for Linux.
  *
  * Copyright (c) 2000-2002 Vojtech Pavlik
  *
@@ -68,6 +69,12 @@ static struct amd_ide_chip {
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,	0x50, AMD_UDMA_133 },
 	{ 0 }
 };
 
@@ -464,6 +471,12 @@ static struct pci_device_id amd74xx_pci_
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
 	{ 0, },
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/amd74xx.h linux-2.4.27-rc4/drivers/ide/pci/amd74xx.h
--- linux-2.4.26/drivers/ide/pci/amd74xx.h	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/amd74xx.h	2004-07-30 16:31:22.000000000 +0000
@@ -112,7 +112,7 @@ static ide_pci_device_t amd74xx_chipsets
 	{	/* 7 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,
-		.name		= "NFORCE2S",
+		.name		= "NFORCE2-U400R",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -123,7 +123,7 @@ static ide_pci_device_t amd74xx_chipsets
 	{	/* 8 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,
-		.name		= "NFORCE2S-SATA",
+		.name		= "NFORCE2-U400R-SATA",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -134,7 +134,7 @@ static ide_pci_device_t amd74xx_chipsets
 	{	/* 9 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,
-		.name		= "NFORCE3",
+		.name		= "NFORCE3-150",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -145,7 +145,7 @@ static ide_pci_device_t amd74xx_chipsets
 	{	/* 10 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,
-		.name		= "NFORCE3S",
+		.name		= "NFORCE3-250",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -156,7 +156,7 @@ static ide_pci_device_t amd74xx_chipsets
 	{	/* 11 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,
-		.name		= "NFORCE3S-SATA",
+		.name		= "NFORCE3-250-SATA",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
@@ -167,7 +167,73 @@ static ide_pci_device_t amd74xx_chipsets
 	{	/* 12 */
 		.vendor		= PCI_VENDOR_ID_NVIDIA,
 		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,
-		.name		= "NFORCE3S-SATA2",
+		.name		= "NFORCE3-250-SATA2",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 13 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE,
+		.name		= "NFORCE-CK804",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 14 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA,
+		.name		= "NFORCE-CK804-SATA",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 15 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2,
+		.name		= "NFORCE-CK804-SATA2",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 16 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,
+		.name		= "NFORCE-MCP04",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 17 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA,
+		.name		= "NFORCE-MCP04-SATA",
+		.init_chipset	= init_chipset_amd74xx,
+		.init_hwif	= init_hwif_amd74xx,
+		.channels	= 2,
+		.autodma	= AUTODMA,
+		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},
+		.bootable	= ON_BOARD,
+	},
+	{	/* 18 */
+		.vendor		= PCI_VENDOR_ID_NVIDIA,
+		.device		= PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2,
+		.name		= "NFORCE-MCP04-SATA2",
 		.init_chipset	= init_chipset_amd74xx,
 		.init_hwif	= init_hwif_amd74xx,
 		.channels	= 2,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/cmd64x.c linux-2.4.27-rc4/drivers/ide/pci/cmd64x.c
--- linux-2.4.26/drivers/ide/pci/cmd64x.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/cmd64x.c	2004-07-30 16:31:22.000000000 +0000
@@ -485,13 +485,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		config_chipset_for_pio(drive, 1);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 static int cmd64x_alt_dma_status (struct pci_dev *dev)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/generic.c linux-2.4.27-rc4/drivers/ide/pci/generic.c
--- linux-2.4.26/drivers/ide/pci/generic.c	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/generic.c	2004-07-30 16:30:52.000000000 +0000
@@ -141,6 +141,8 @@ static struct pci_device_id generic_pci_
 	{ PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561,          PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7},
 	{ PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558,         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8},
 	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO,	   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9},
+	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10},
+	{ PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11},
 	{ 0, },
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/generic.h linux-2.4.27-rc4/drivers/ide/pci/generic.h
--- linux-2.4.26/drivers/ide/pci/generic.h	2004-04-14 13:05:29.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/generic.h	2004-07-30 16:26:05.000000000 +0000
@@ -130,16 +130,33 @@ static ide_pci_device_t generic_chipsets
 	},{	/* 9 */
 		.vendor		= PCI_VENDOR_ID_TOSHIBA,
 		.device		= PCI_DEVICE_ID_TOSHIBA_PICCOLO,
-		.name		= "Piccolo",
+		.name		= "Piccolo0102",
+		.init_chipset	= init_chipset_generic,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.bootable	= ON_BOARD,
+	},{	/* 10 */
+		.vendor		= PCI_VENDOR_ID_TOSHIBA,
+		.device		= PCI_DEVICE_ID_TOSHIBA_PICCOLO_1,
+		.name		= "Piccolo0103",
+		.init_chipset	= init_chipset_generic,
+		.init_hwif	= init_hwif_generic,
+		.init_dma	= init_dma_generic,
+		.channels	= 2,
+		.autodma	= NOAUTODMA,
+		.bootable	= ON_BOARD,
+	},{	/* 11 */
+		.vendor		= PCI_VENDOR_ID_TOSHIBA,
+		.device		= PCI_DEVICE_ID_TOSHIBA_PICCOLO_2,
+		.name		= "Piccolo0105",
 		.init_chipset	= init_chipset_generic,
-		.init_iops	= NULL,
 		.init_hwif	= init_hwif_generic,
 		.init_dma	= init_dma_generic,
 		.channels	= 2,
 		.autodma	= NOAUTODMA,
-		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 		.bootable	= ON_BOARD,
-		.extra		= 0,
 	},{
 		.vendor		= 0,
 		.device		= 0,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/hpt34x.c linux-2.4.27-rc4/drivers/ide/pci/hpt34x.c
--- linux-2.4.26/drivers/ide/pci/hpt34x.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/hpt34x.c	2004-07-30 16:25:33.000000000 +0000
@@ -216,17 +216,19 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+#ifndef CONFIG_HPT34X_AUTODMA
+		return hwif->ide_dma_off_quietly(drive);
+#else
+		return hwif->ide_dma_on(drive);
+#endif
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		hpt34x_tune_drive(drive, 255);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-
-#ifndef CONFIG_HPT34X_AUTODMA
-	return hwif->ide_dma_off_quietly(drive);
-#endif /* CONFIG_HPT34X_AUTODMA */
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/hpt366.c linux-2.4.27-rc4/drivers/ide/pci/hpt366.c
--- linux-2.4.26/drivers/ide/pci/hpt366.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/hpt366.c	2004-07-30 16:25:59.000000000 +0000
@@ -123,7 +123,7 @@ static int hpt366_get_info (char *buffer
 				"                             %s\n",
 			(c0 & 0x80) ? "no" : "yes",
 			(c1 & 0x80) ? "no" : "yes");
-
+#if 0
 		if (hpt_minimum_revision(dev, 3)) {
 			u8 cbl;
 			cbl = inb(iobase + 0x7b);
@@ -136,7 +136,7 @@ static int hpt366_get_info (char *buffer
 				(cbl & 0x01) ? 33 : 66);
 			p += sprintf(p, "\n");
 		}
-
+#endif
 		p += sprintf(p, "--------------- drive0 --------- drive1 "
 				"------- drive0 ---------- drive1 -------\n");
 		p += sprintf(p, "DMA capable:    %s              %s" 
@@ -567,13 +567,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		hpt3xx_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/it8172.c linux-2.4.27-rc4/drivers/ide/pci/it8172.c
--- linux-2.4.26/drivers/ide/pci/it8172.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/it8172.c	2004-07-30 16:29:26.000000000 +0000
@@ -228,13 +228,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		it8172_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 static unsigned int __init init_chipset_it8172 (struct pci_dev *dev, const char *name)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/pdc202xx_new.c linux-2.4.27-rc4/drivers/ide/pci/pdc202xx_new.c
--- linux-2.4.26/drivers/ide/pci/pdc202xx_new.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/pdc202xx_new.c	2004-07-30 16:25:31.000000000 +0000
@@ -415,13 +415,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 static int pdcnew_quirkproc (ide_drive_t *drive)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/pdc202xx_old.c linux-2.4.27-rc4/drivers/ide/pci/pdc202xx_old.c
--- linux-2.4.26/drivers/ide/pci/pdc202xx_old.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/pdc202xx_old.c	2004-07-30 16:28:53.000000000 +0000
@@ -516,13 +516,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 static int pdc202xx_quirkproc (ide_drive_t *drive)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/piix.c linux-2.4.27-rc4/drivers/ide/pci/piix.c
--- linux-2.4.26/drivers/ide/pci/piix.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/piix.c	2004-07-30 16:31:30.000000000 +0000
@@ -593,13 +593,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		hwif->tuneproc(drive, 255);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 /**
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/serverworks.c linux-2.4.27-rc4/drivers/ide/pci/serverworks.c
--- linux-2.4.26/drivers/ide/pci/serverworks.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/serverworks.c	2004-07-30 16:29:05.000000000 +0000
@@ -473,7 +473,9 @@ static int svwks_config_drive_xfer_rate 
 				int dma = config_chipset_for_dma(drive);
 				if ((id->field_valid & 2) && !dma)
 					goto try_dma_modes;
-			}
+			} else
+				/* UDMA disabled by mask, try other DMA modes */
+				goto try_dma_modes;
 		} else if (id->field_valid & 2) {
 try_dma_modes:
 			if ((id->dma_mword & hwif->mwdma_mask) ||
@@ -490,6 +492,7 @@ try_dma_modes:
 		} else {
 			goto no_dma_set;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
@@ -497,7 +500,8 @@ no_dma_set:
 		//	hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 /* This can go soon */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/siimage.c linux-2.4.27-rc4/drivers/ide/pci/siimage.c
--- linux-2.4.26/drivers/ide/pci/siimage.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/siimage.c	2004-07-30 16:30:39.000000000 +0000
@@ -516,13 +516,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		config_chipset_for_pio(drive, 1);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/sis5513.c linux-2.4.27-rc4/drivers/ide/pci/sis5513.c
--- linux-2.4.26/drivers/ide/pci/sis5513.c	2003-08-25 11:44:41.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/sis5513.c	2004-07-30 16:27:31.000000000 +0000
@@ -697,13 +697,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		sis5513_tune_drive(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 
 /* initiates/aborts (U)DMA read/write operations on a drive. */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ide/pci/slc90e66.c linux-2.4.27-rc4/drivers/ide/pci/slc90e66.c
--- linux-2.4.26/drivers/ide/pci/slc90e66.c	2003-06-13 14:51:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ide/pci/slc90e66.c	2004-07-30 16:25:02.000000000 +0000
@@ -302,13 +302,15 @@ try_dma_modes:
 		} else {
 			goto fast_ata_pio;
 		}
+		return hwif->ide_dma_on(drive);
 	} else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
 no_dma_set:
 		hwif->tuneproc(drive, 5);
 		return hwif->ide_dma_off_quietly(drive);
 	}
-	return hwif->ide_dma_on(drive);
+	/* IORDY not supported */
+	return 0;
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ieee1394/pcilynx.c linux-2.4.27-rc4/drivers/ieee1394/pcilynx.c
--- linux-2.4.26/drivers/ieee1394/pcilynx.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ieee1394/pcilynx.c	2004-07-30 16:27:25.000000000 +0000
@@ -1464,7 +1464,7 @@ static void remove_card(struct pci_dev *
                 reg_write(lynx, PCI_INT_ENABLE, 0);
                 free_irq(lynx->dev->irq, lynx);
 
-		/* Disable IRM Contender */
+		/* Disable IRM Contender and LCtrl */
 		if (lynx->phyic.reg_1394a)
 			set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4));
 
@@ -1792,12 +1792,12 @@ static int __devinit add_card(struct pci
                 reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
                 reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); 
         } else {
-                /* set the contender bit in the extended PHY register
+                /* set the contender and LCtrl bit in the extended PHY register
                  * set. (Should check that bis 0,1,2 (=0xE0) is set
                  * in register 2?)
                  */
                 i = get_phy_reg(lynx, 4);
-                if (i != -1) set_phy_reg(lynx, 4, i | 0x40);
+                if (i != -1) set_phy_reg(lynx, 4, i | 0xc0);
         }
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ieee1394/sbp2.c linux-2.4.27-rc4/drivers/ieee1394/sbp2.c
--- linux-2.4.26/drivers/ieee1394/sbp2.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ieee1394/sbp2.c	2004-07-30 16:25:50.000000000 +0000
@@ -113,8 +113,8 @@ static int sbp2_max_speed = IEEE1394_SPE
  * badly behaved sbp2 devices.
  */
 MODULE_PARM(sbp2_serialize_io,"i");
-MODULE_PARM_DESC(sbp2_serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 0)");
-static int sbp2_serialize_io = 0;	/* serialize I/O - available for debugging purposes */
+MODULE_PARM_DESC(sbp2_serialize_io, "Serialize all I/O coming down from the scsi drivers (default = 1)");
+static int sbp2_serialize_io = 1;	/* serialize I/O - available for debugging purposes */
 
 /*
  * Bump up sbp2_max_sectors if you'd like to support very large sized
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/ieee1394/video1394.c linux-2.4.27-rc4/drivers/ieee1394/video1394.c
--- linux-2.4.26/drivers/ieee1394/video1394.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/ieee1394/video1394.c	2004-07-30 16:26:03.000000000 +0000
@@ -21,6 +21,9 @@
 /* jds -- add private data to file to keep track of iso contexts associated
    with each open -- so release won't kill all iso transfers */
 
+/* Damien Douxchamps: Fix failure when the number of DMA pages per frame is
+   one */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -405,33 +408,43 @@ static void initialize_dma_ir_prg(struct
 				(unsigned long)d->dma.kvirt));
 	ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
 					1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-	/* the second descriptor will read PAGE_SIZE-4 bytes */
-	ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-		DMA_CTL_BRANCH | (PAGE_SIZE-4));
-	ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
-					(unsigned long)d->dma.kvirt));
-	ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-					2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+	/* if there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */
+ 	if (d->nb_cmd>2) {
+  	        /* the second descriptor will read PAGE_SIZE-4 bytes */
+	        ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+					        DMA_CTL_BRANCH | (PAGE_SIZE-4));
+		ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
+						(unsigned long)d->dma.kvirt));
+		ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					   2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	
-	for (i=2;i<d->nb_cmd-1;i++) {
+		for (i=2;i<d->nb_cmd-1;i++) {
+		        ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+							DMA_CTL_BRANCH | PAGE_SIZE);
+			ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+							(buf+(i-1)*PAGE_SIZE) -
+							(unsigned long)d->dma.kvirt));
+
+			ir_prg[i].branchAddress =
+			             cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+				     (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+		}
+
+		/* the last descriptor will generate an interrupt */
 		ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
-			DMA_CTL_BRANCH | PAGE_SIZE);
+					        DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
 		ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
 					        (buf+(i-1)*PAGE_SIZE) -
-						(unsigned long)d->dma.kvirt));
-
-		ir_prg[i].branchAddress =
-			cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-				(i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
+					        (unsigned long)d->dma.kvirt));
+	}
+	else { 
+	       /* only one DMA page is used. Read d->left_size immediately and */
+	       /* generate an interrupt as this is also the last page */
+	       ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
+		                           DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4));
+	       ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+		  			       (buf + 4) - (unsigned long)d->dma.kvirt));
 	}
-
-	/* the last descriptor will generate an interrupt */
-	ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
-		DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-	ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-					(buf+(i-1)*PAGE_SIZE) -
-					(unsigned long)d->dma.kvirt));
 }
 	
 static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/isdn/hisax/nj_s.c linux-2.4.27-rc4/drivers/isdn/hisax/nj_s.c
--- linux-2.4.26/drivers/isdn/hisax/nj_s.c	2002-11-28 23:53:13.000000000 +0000
+++ linux-2.4.27-rc4/drivers/isdn/hisax/nj_s.c	2004-07-30 16:26:52.000000000 +0000
@@ -130,6 +130,7 @@ NETjet_S_card_msg(struct IsdnCardState *
 			release_io_netjet(cs);
 			return(0);
 		case CARD_INIT:
+			reset_netjet_s(cs);
 			inittiger(cs);
 			clear_pending_isac_ints(cs);
 			initisac(cs);
@@ -262,7 +263,6 @@ setup_netjet_s(struct IsdnCard *card)
 	} else {
 		request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn");
 	}
-	reset_netjet_s(cs);
 	cs->readisac  = &NETjet_ReadIC;
 	cs->writeisac = &NETjet_WriteIC;
 	cs->readisacfifo  = &NETjet_ReadICfifo;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/isdn/sc/command.c linux-2.4.27-rc4/drivers/isdn/sc/command.c
--- linux-2.4.26/drivers/isdn/sc/command.c	2001-12-21 17:41:54.000000000 +0000
+++ linux-2.4.27-rc4/drivers/isdn/sc/command.c	2004-07-30 16:27:11.000000000 +0000
@@ -95,7 +95,7 @@ int get_card_from_id(int driver)
 		if(adapter[i]->driverId == driver)
 			return i;
 	}
-	return -NODEV;
+	return -ENODEV;
 }
 
 /* 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/md/raid5.c linux-2.4.27-rc4/drivers/md/raid5.c
--- linux-2.4.26/drivers/md/raid5.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/md/raid5.c	2004-07-30 16:26:23.000000000 +0000
@@ -950,7 +950,7 @@ static void handle_stripe(struct stripe_
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
 	 */
-	if (to_read || (syncing && (uptodate+failed < disks))) {
+	if (to_read || (syncing && (uptodate < disks))) {
 		for (i=disks; i--;) {
 			bh = sh->bh_cache[i];
 			if (!buffer_locked(bh) && !buffer_uptodate(bh) &&
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/media/video/cpia.c linux-2.4.27-rc4/drivers/media/video/cpia.c
--- linux-2.4.26/drivers/media/video/cpia.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/media/video/cpia.c	2004-07-30 16:29:54.000000000 +0000
@@ -2443,7 +2443,7 @@ static int reset_camera(struct cam_data 
 		goto_high_power(cam);
 		do_command(cam, CPIA_COMMAND_DiscardFrame, 0, 0, 0, 0);
 		if (goto_low_power(cam))
-			return -NODEV;
+			return -ENODEV;
 	}
 	
 	/* procedure described in developer's guide p3-28 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/media/video/videodev.c linux-2.4.27-rc4/drivers/media/video/videodev.c
--- linux-2.4.26/drivers/media/video/videodev.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/media/video/videodev.c	2004-07-30 16:25:47.000000000 +0000
@@ -553,7 +553,14 @@ int video_register_device(struct video_d
 
 	/* pick a minor number */
 	down(&videodev_lock);
-	if (-1 == nr) {
+	if (nr >= 0  &&  nr < end-base) {
+		/* use the one the driver asked for */
+		i = base+nr;
+		if (NULL != video_device[i]) {
+			up(&videodev_lock);
+			return -ENFILE;
+		}
+	} else {
 		/* use first free */
 		for(i=base;i<end;i++)
 			if (NULL == video_device[i])
@@ -562,13 +569,6 @@ int video_register_device(struct video_d
 			up(&videodev_lock);
 			return -ENFILE;
 		}
-	} else {
-		/* use the one the driver asked for */
-		i = base+nr;
-		if (NULL != video_device[i]) {
-			up(&videodev_lock);
-			return -ENFILE;
-		}
 	}
 	video_device[i]=vfd;
 	vfd->minor=i;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/isense.c linux-2.4.27-rc4/drivers/message/fusion/isense.c
--- linux-2.4.26/drivers/message/fusion/isense.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/isense.c	2004-07-30 16:28:37.000000000 +0000
@@ -66,7 +66,7 @@
 #endif
 
 #define MODULEAUTHOR "Steven J. Ralston"
-#define COPYRIGHT "Copyright (c) 2001-2002 " MODULEAUTHOR
+#define COPYRIGHT "Copyright (c) 2001-2004 " MODULEAUTHOR
 #include "mptbase.h"
 
 #include "isense.h"
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi.h	2004-07-30 16:25:50.000000000 +0000
@@ -2,11 +2,11 @@
  *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI.H
+ *           Name:  mpi.h
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    MPI.H Version:  01.02.10
+ *    mpi.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -66,7 +66,7 @@
 *****************************************************************************/
 
 #define MPI_VERSION_MAJOR                   (0x01)
-#define MPI_VERSION_MINOR                   (0x02)
+#define MPI_VERSION_MINOR                   (0x05)
 #define MPI_VERSION_MAJOR_MASK              (0xFF00)
 #define MPI_VERSION_MAJOR_SHIFT             (8)
 #define MPI_VERSION_MINOR_MASK              (0x00FF)
@@ -77,10 +77,12 @@
 #define MPI_VERSION_01_00                   (0x0100)
 #define MPI_VERSION_01_01                   (0x0101)
 #define MPI_VERSION_01_02                   (0x0102)
+#define MPI_VERSION_01_03                   (0x0103)
+#define MPI_VERSION_01_05                   (0x0105)
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0C)
+#define MPI_HEADER_VERSION_UNIT             (0x00)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
@@ -175,6 +177,8 @@
 #define MPI_REPLY_POST_FIFO_OFFSET          (0x00000044)
 #define MPI_REPLY_FREE_FIFO_OFFSET          (0x00000044)
 
+#define MPI_HI_PRI_REQUEST_QUEUE_OFFSET     (0x00000048)
+
 
 
 /*****************************************************************************
@@ -234,10 +238,6 @@
 #define MPI_FUNCTION_TARGET_ASSIST                  (0x0B)
 #define MPI_FUNCTION_TARGET_STATUS_SEND             (0x0C)
 #define MPI_FUNCTION_TARGET_MODE_ABORT              (0x0D)
-#define MPI_FUNCTION_TARGET_FC_BUF_POST_LINK_SRVC   (0x0E) /* obsolete name */
-#define MPI_FUNCTION_TARGET_FC_RSP_LINK_SRVC        (0x0F) /* obsolete name */
-#define MPI_FUNCTION_TARGET_FC_EX_SEND_LINK_SRVC    (0x10) /* obsolete name */
-#define MPI_FUNCTION_TARGET_FC_ABORT                (0x11) /* obsolete name */
 #define MPI_FUNCTION_FC_LINK_SRVC_BUF_POST          (0x0E)
 #define MPI_FUNCTION_FC_LINK_SRVC_RSP               (0x0F)
 #define MPI_FUNCTION_FC_EX_LINK_SRVC_SEND           (0x10)
@@ -255,16 +255,46 @@
 
 #define MPI_FUNCTION_MAILBOX                        (0x19)
 
+#define MPI_FUNCTION_SMP_PASSTHROUGH                (0x1A)
+#define MPI_FUNCTION_SAS_IO_UNIT_CONTROL            (0x1B)
+
+#define MPI_DIAG_BUFFER_POST                        (0x1D)
+#define MPI_DIAG_RELEASE                            (0x1E)
+
+#define MPI_FUNCTION_SCSI_IO_32                     (0x1F)
+
 #define MPI_FUNCTION_LAN_SEND                       (0x20)
 #define MPI_FUNCTION_LAN_RECEIVE                    (0x21)
 #define MPI_FUNCTION_LAN_RESET                      (0x22)
 
+#define MPI_FUNCTION_INBAND_BUFFER_POST             (0x28)
+#define MPI_FUNCTION_INBAND_SEND                    (0x29)
+#define MPI_FUNCTION_INBAND_RSP                     (0x2A)
+#define MPI_FUNCTION_INBAND_ABORT                   (0x2B)
+
 #define MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET         (0x40)
 #define MPI_FUNCTION_IO_UNIT_RESET                  (0x41)
 #define MPI_FUNCTION_HANDSHAKE                      (0x42)
 #define MPI_FUNCTION_REPLY_FRAME_REMOVAL            (0x43)
 
 
+/* standard version format */
+typedef struct _MPI_VERSION_STRUCT
+{
+    U8                      Dev;                        /* 00h */
+    U8                      Unit;                       /* 01h */
+    U8                      Minor;                      /* 02h */
+    U8                      Major;                      /* 03h */
+} MPI_VERSION_STRUCT, MPI_POINTER PTR_MPI_VERSION_STRUCT,
+  MpiVersionStruct_t, MPI_POINTER pMpiVersionStruct;
+
+typedef union _MPI_VERSION_FORMAT
+{
+    MPI_VERSION_STRUCT      Struct;
+    U32                     Word;
+} MPI_VERSION_FORMAT, MPI_POINTER PTR_MPI_VERSION_FORMAT,
+  MpiVersionFormat_t, MPI_POINTER pMpiVersionFormat_t;
+
 
 /*****************************************************************************
 *
@@ -577,44 +607,54 @@ typedef struct _MSG_DEFAULT_REPLY
 /*  Common IOCStatus values for all replies                                 */
 /****************************************************************************/
 
-#define MPI_IOCSTATUS_SUCCESS                  (0x0000)
-#define MPI_IOCSTATUS_INVALID_FUNCTION         (0x0001)
-#define MPI_IOCSTATUS_BUSY                     (0x0002)
-#define MPI_IOCSTATUS_INVALID_SGL              (0x0003)
-#define MPI_IOCSTATUS_INTERNAL_ERROR           (0x0004)
-#define MPI_IOCSTATUS_RESERVED                 (0x0005)
-#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES   (0x0006)
-#define MPI_IOCSTATUS_INVALID_FIELD            (0x0007)
-#define MPI_IOCSTATUS_INVALID_STATE            (0x0008)
+#define MPI_IOCSTATUS_SUCCESS                   (0x0000)
+#define MPI_IOCSTATUS_INVALID_FUNCTION          (0x0001)
+#define MPI_IOCSTATUS_BUSY                      (0x0002)
+#define MPI_IOCSTATUS_INVALID_SGL               (0x0003)
+#define MPI_IOCSTATUS_INTERNAL_ERROR            (0x0004)
+#define MPI_IOCSTATUS_RESERVED                  (0x0005)
+#define MPI_IOCSTATUS_INSUFFICIENT_RESOURCES    (0x0006)
+#define MPI_IOCSTATUS_INVALID_FIELD             (0x0007)
+#define MPI_IOCSTATUS_INVALID_STATE             (0x0008)
+#define MPI_IOCSTATUS_OP_STATE_NOT_SUPPORTED    (0x0009)
 
 /****************************************************************************/
 /*  Config IOCStatus values                                                 */
 /****************************************************************************/
 
-#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION    (0x0020)
-#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE      (0x0021)
-#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE      (0x0022)
-#define MPI_IOCSTATUS_CONFIG_INVALID_DATA      (0x0023)
-#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS       (0x0024)
-#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT       (0x0025)
+#define MPI_IOCSTATUS_CONFIG_INVALID_ACTION     (0x0020)
+#define MPI_IOCSTATUS_CONFIG_INVALID_TYPE       (0x0021)
+#define MPI_IOCSTATUS_CONFIG_INVALID_PAGE       (0x0022)
+#define MPI_IOCSTATUS_CONFIG_INVALID_DATA       (0x0023)
+#define MPI_IOCSTATUS_CONFIG_NO_DEFAULTS        (0x0024)
+#define MPI_IOCSTATUS_CONFIG_CANT_COMMIT        (0x0025)
 
 /****************************************************************************/
 /*  SCSIIO Reply (SPI & FCP) initiator values                               */
 /****************************************************************************/
 
-#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR     (0x0040)
-#define MPI_IOCSTATUS_SCSI_INVALID_BUS         (0x0041)
-#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID    (0x0042)
-#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE    (0x0043)
-#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN        (0x0044)
-#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN       (0x0045)
-#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR       (0x0046)
-#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR      (0x0047)
-#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED     (0x0048)
-#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH   (0x0049)
-#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED    (0x004A)
-#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED      (0x004B)
-#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED      (0x004C)
+#define MPI_IOCSTATUS_SCSI_RECOVERED_ERROR      (0x0040)
+#define MPI_IOCSTATUS_SCSI_INVALID_BUS          (0x0041)
+#define MPI_IOCSTATUS_SCSI_INVALID_TARGETID     (0x0042)
+#define MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE     (0x0043)
+#define MPI_IOCSTATUS_SCSI_DATA_OVERRUN         (0x0044)
+#define MPI_IOCSTATUS_SCSI_DATA_UNDERRUN        (0x0045)
+#define MPI_IOCSTATUS_SCSI_IO_DATA_ERROR        (0x0046)
+#define MPI_IOCSTATUS_SCSI_PROTOCOL_ERROR       (0x0047)
+#define MPI_IOCSTATUS_SCSI_TASK_TERMINATED      (0x0048)
+#define MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH    (0x0049)
+#define MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED     (0x004A)
+#define MPI_IOCSTATUS_SCSI_IOC_TERMINATED       (0x004B)
+#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED       (0x004C)
+
+/****************************************************************************/
+/*  For use by SCSI Initiator and SCSI Target end-to-end data protection    */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_EEDP_CRC_ERROR            (0x004D)
+#define MPI_IOCSTATUS_EEDP_LBA_TAG_ERROR        (0x004E)
+#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR        (0x004F)
+
 
 /****************************************************************************/
 /*  SCSI (SPI & FCP) target values                                          */
@@ -631,7 +671,7 @@ typedef struct _MSG_DEFAULT_REPLY
 #define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT   (0x006B)
 
 /****************************************************************************/
-/*  Additional FCP target values                                            */
+/*  Additional FCP target values (obsolete)                                 */
 /****************************************************************************/
 
 #define MPI_IOCSTATUS_TARGET_FC_ABORTED         (0x0066)    /* obsolete */
@@ -662,6 +702,25 @@ typedef struct _MSG_DEFAULT_REPLY
 #define MPI_IOCSTATUS_LAN_PARTIAL_PACKET        (0x0086)
 #define MPI_IOCSTATUS_LAN_CANCELED              (0x0087)
 
+/****************************************************************************/
+/*  Serial Attached SCSI values                                                              */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED    (0x0090)
+
+/****************************************************************************/
+/*  Inband values                                                           */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_INBAND_ABORTED            (0x0098)
+#define MPI_IOCSTATUS_INBAND_NO_CONNECTION      (0x0099)
+
+/****************************************************************************/
+/*  Diagnostic Tools values                                                 */
+/****************************************************************************/
+
+#define MPI_IOCSTATUS_DIAGNOSTIC_RELEASED       (0x00A0)
+
 
 /****************************************************************************/
 /*  IOCStatus flag to indicate that log info is available                   */
@@ -675,9 +734,12 @@ typedef struct _MSG_DEFAULT_REPLY
 /****************************************************************************/
 
 #define MPI_IOCLOGINFO_TYPE_MASK                (0xF0000000)
+#define MPI_IOCLOGINFO_TYPE_SHIFT               (28)
 #define MPI_IOCLOGINFO_TYPE_NONE                (0x0)
 #define MPI_IOCLOGINFO_TYPE_SCSI                (0x1)
 #define MPI_IOCLOGINFO_TYPE_FC                  (0x2)
+#define MPI_IOCLOGINFO_TYPE_SAS                 (0x3)
+#define MPI_IOCLOGINFO_TYPE_ISCSI               (0x4)
 #define MPI_IOCLOGINFO_LOG_DATA_MASK            (0x0FFFFFFF)
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_cnfg.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_cnfg.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_cnfg.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_cnfg.h	2004-07-30 16:29:03.000000000 +0000
@@ -2,11 +2,11 @@
  *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_CNFG.H
+ *           Name:  mpi_cnfg.h
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    MPI_CNFG.H Version:  01.02.12
+ *    mpi_cnfg.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -176,6 +176,19 @@ typedef union _CONFIG_PAGE_HEADER_UNION
 } ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion,
   fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION;
 
+typedef struct _CONFIG_EXTENDED_PAGE_HEADER
+{
+    U8                  PageVersion;                /* 00h */
+    U8                  Reserved1;                  /* 01h */
+    U8                  PageNumber;                 /* 02h */
+    U8                  PageType;                   /* 03h */
+    U16                 ExtPageLength;              /* 04h */
+    U8                  ExtPageType;                /* 06h */
+    U8                  Reserved2;                  /* 07h */
+} fCONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER,
+  ConfigExtendedPageHeader_t, MPI_POINTER pConfigExtendedPageHeader_t;
+
+
 
 /****************************************************************************
 *   PageType field values
@@ -197,12 +210,23 @@ typedef union _CONFIG_PAGE_HEADER_UNION
 #define MPI_CONFIG_PAGETYPE_RAID_VOLUME             (0x08)
 #define MPI_CONFIG_PAGETYPE_MANUFACTURING           (0x09)
 #define MPI_CONFIG_PAGETYPE_RAID_PHYSDISK           (0x0A)
+#define MPI_CONFIG_PAGETYPE_INBAND                  (0x0B)
+#define MPI_CONFIG_PAGETYPE_EXTENDED                (0x0F)
 #define MPI_CONFIG_PAGETYPE_MASK                    (0x0F)
 
 #define MPI_CONFIG_TYPENUM_MASK                     (0x0FFF)
 
 
 /****************************************************************************
+*   ExtPageType field values
+****************************************************************************/
+#define MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT          (0x10)
+#define MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER         (0x11)
+#define MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE           (0x12)
+#define MPI_CONFIG_EXTPAGETYPE_SAS_PHY              (0x13)
+
+
+/****************************************************************************
 *   PageAddress field values
 ****************************************************************************/
 #define MPI_SCSI_PORT_PGAD_PORT_MASK                (0x000000FF)
@@ -236,6 +260,24 @@ typedef union _CONFIG_PAGE_HEADER_UNION
 #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK          (0x000000FF)
 #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT         (0)
 
+#define MPI_SAS_DEVICE_PGAD_FORM_MASK               (0xF0000000)
+#define MPI_SAS_DEVICE_PGAD_FORM_SHIFT              (28)
+#define MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE    (0x00000000)
+#define MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID      (0x00000001)
+#define MPI_SAS_DEVICE_PGAD_FORM_HANDLE             (0x00000002)
+#define MPI_SAS_DEVICE_PGAD_GNH_HANDLE_MASK         (0x0000FFFF)
+#define MPI_SAS_DEVICE_PGAD_GNH_HANDLE_SHIFT        (0)
+#define MPI_SAS_DEVICE_PGAD_BT_BUS_MASK             (0x0000FF00)
+#define MPI_SAS_DEVICE_PGAD_BT_BUS_SHIFT            (8)
+#define MPI_SAS_DEVICE_PGAD_BT_TID_MASK             (0x000000FF)
+#define MPI_SAS_DEVICE_PGAD_BT_TID_SHIFT            (0)
+#define MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK           (0x0000FFFF)
+#define MPI_SAS_DEVICE_PGAD_H_HANDLE_SHIFT          (0)
+
+#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK            (0x00FF0000)
+#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT           (16)
+#define MPI_SAS_PHY_PGAD_DEVHANDLE_MASK             (0x0000FFFF)
+#define MPI_SAS_PHY_PGAD_DEVHANDLE_SHIFT            (0)
 
 
 /****************************************************************************
@@ -247,7 +289,8 @@ typedef struct _MSG_CONFIG
     U8                      Reserved;                   /* 01h */
     U8                      ChainOffset;                /* 02h */
     U8                      Function;                   /* 03h */
-    U8                      Reserved1[3];               /* 04h */
+    U16                     ExtPageLength;              /* 04h */
+    U8                      ExtPageType;                /* 06h */
     U8                      MsgFlags;                   /* 07h */
     U32                     MsgContext;                 /* 08h */
     U8                      Reserved2[8];               /* 0Ch */
@@ -277,7 +320,8 @@ typedef struct _MSG_CONFIG_REPLY
     U8                      Reserved;                   /* 01h */
     U8                      MsgLength;                  /* 02h */
     U8                      Function;                   /* 03h */
-    U8                      Reserved1[3];               /* 04h */
+    U16                     ExtPageLength;              /* 04h */
+    U8                      ExtPageType;                /* 06h */
     U8                      MsgFlags;                   /* 07h */
     U32                     MsgContext;                 /* 08h */
     U8                      Reserved2[2];               /* 0Ch */
@@ -299,29 +343,21 @@ typedef struct _MSG_CONFIG_REPLY
 *   Manufacturing Config pages
 ****************************************************************************/
 #define MPI_MANUFACTPAGE_VENDORID_LSILOGIC          (0x1000)
-#define MPI_MANUFACTPAGE_VENDORID_TREBIA            (0x1783)
-
+/* Fibre Channel */
 #define MPI_MANUFACTPAGE_DEVICEID_FC909             (0x0621)
 #define MPI_MANUFACTPAGE_DEVICEID_FC919             (0x0624)
 #define MPI_MANUFACTPAGE_DEVICEID_FC929             (0x0622)
 #define MPI_MANUFACTPAGE_DEVICEID_FC919X            (0x0628)
 #define MPI_MANUFACTPAGE_DEVICEID_FC929X            (0x0626)
-
+/* SCSI */
 #define MPI_MANUFACTPAGE_DEVID_53C1030              (0x0030)
 #define MPI_MANUFACTPAGE_DEVID_53C1030ZC            (0x0031)
 #define MPI_MANUFACTPAGE_DEVID_1030_53C1035         (0x0032)
 #define MPI_MANUFACTPAGE_DEVID_1030ZC_53C1035       (0x0033)
 #define MPI_MANUFACTPAGE_DEVID_53C1035              (0x0040)
 #define MPI_MANUFACTPAGE_DEVID_53C1035ZC            (0x0041)
-
-#define MPI_MANUFACTPAGE_DEVID_SA2010               (0x0804)
-#define MPI_MANUFACTPAGE_DEVID_SA2010ZC             (0x0805)
-#define MPI_MANUFACTPAGE_DEVID_SA2020               (0x0806)
-#define MPI_MANUFACTPAGE_DEVID_SA2020ZC             (0x0807)
-
-#define MPI_MANUFACTPAGE_DEVID_SNP1000              (0x0010)
-#define MPI_MANUFACTPAGE_DEVID_SNP500               (0x0020)
-
+/* SAS */
+#define MPI_MANUFACTPAGE_DEVID_SAS1064              (0x0050)
 
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -405,8 +441,8 @@ typedef struct _CONFIG_PAGE_MANUFACTURIN
     U8                              InfoOffset1;        /* 0Ah */
     U8                              InfoSize1;          /* 0Bh */
     U8                              InquirySize;        /* 0Ch */
-    U8                              Reserved2;          /* 0Dh */
-    U16                             Reserved3;          /* 0Eh */
+    U8                              Flags;              /* 0Dh */
+    U16                             Reserved2;          /* 0Eh */
     U8                              InquiryData[56];    /* 10h */
     U32                             ISVolumeSettings;   /* 48h */
     U32                             IMEVolumeSettings;  /* 4Ch */
@@ -414,7 +450,30 @@ typedef struct _CONFIG_PAGE_MANUFACTURIN
 } fCONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
 
-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x00)
+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x01)
+
+/* defines for the Flags field */
+#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_5
+{
+    fCONFIG_PAGE_HEADER              Header;             /* 00h */
+    U64                             BaseWWID;           /* 04h */
+} fCONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
+  ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t;
+
+#define MPI_MANUFACTURING5_PAGEVERSION                  (0x00)
+
+
+typedef struct _CONFIG_PAGE_MANUFACTURING_6
+{
+    fCONFIG_PAGE_HEADER              Header;             /* 00h */
+    U32                             ProductSpecificInfo;/* 04h */
+} fCONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6,
+  ManufacturingPage6_t, MPI_POINTER pManufacturingPage6_t;
+
+#define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
 
 
 /****************************************************************************
@@ -438,17 +497,18 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
 } fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
   IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
 
-#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x00)
+#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x01)
 
 /* IO Unit Page 1 Flags defines */
-
 #define MPI_IOUNITPAGE1_MULTI_FUNCTION                  (0x00000000)
 #define MPI_IOUNITPAGE1_SINGLE_FUNCTION                 (0x00000001)
 #define MPI_IOUNITPAGE1_MULTI_PATHING                   (0x00000002)
 #define MPI_IOUNITPAGE1_SINGLE_PATHING                  (0x00000000)
 #define MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID         (0x00000004)
+#define MPI_IOUNITPAGE1_DISABLE_QUEUE_FULL_HANDLING     (0x00000020)
 #define MPI_IOUNITPAGE1_DISABLE_IR                      (0x00000040)
 #define MPI_IOUNITPAGE1_FORCE_32                        (0x00000080)
+#define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE        (0x00000100)
 
 
 typedef struct _MPI_ADAPTER_INFO
@@ -478,6 +538,11 @@ typedef struct _CONFIG_PAGE_IO_UNIT_2
 #define MPI_IOUNITPAGE2_FLAGS_COLOR_VIDEO_DISABLE       (0x00000008)
 #define MPI_IOUNITPAGE2_FLAGS_DONT_HOOK_INT_40          (0x00000010)
 
+#define MPI_IOUNITPAGE2_FLAGS_DEV_LIST_DISPLAY_MASK     (0x000000E0)
+#define MPI_IOUNITPAGE2_FLAGS_INSTALLED_DEV_DISPLAY     (0x00000000)
+#define MPI_IOUNITPAGE2_FLAGS_ADAPTER_DISPLAY           (0x00000020)
+#define MPI_IOUNITPAGE2_FLAGS_ADAPTER_DEV_DISPLAY       (0x00000040)
+
 
 /*
  * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
@@ -540,6 +605,12 @@ typedef struct _CONFIG_PAGE_IOC_1
 
 #define MPI_IOCPAGE1_PAGEVERSION                        (0x01)
 
+/* defines for the Flags field */
+#define MPI_IOCPAGE1_EEDP_HOST_SUPPORTS_DIF             (0x08000000)
+#define MPI_IOCPAGE1_EEDP_MODE_MASK                     (0x07000000)
+#define MPI_IOCPAGE1_EEDP_MODE_OFF                      (0x00000000)
+#define MPI_IOCPAGE1_EEDP_MODE_T10                      (0x01000000)
+#define MPI_IOCPAGE1_EEDP_MODE_LSI_1                    (0x02000000)
 #define MPI_IOCPAGE1_REPLY_COALESCING                   (0x00000001)
 
 #define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN                 (0xFF)
@@ -680,7 +751,7 @@ typedef struct _IOC_5_HOT_SPARE
 
 typedef struct _CONFIG_PAGE_IOC_5
 {
-    fCONFIG_PAGE_HEADER         Header;                         /* 00h */
+    fCONFIG_PAGE_HEADER          Header;                         /* 00h */
     U32                         Reserved1;                      /* 04h */
     U8                          NumHotSpares;                   /* 08h */
     U8                          Reserved2;                      /* 09h */
@@ -692,6 +763,57 @@ typedef struct _CONFIG_PAGE_IOC_5
 #define MPI_IOCPAGE5_PAGEVERSION                        (0x00)
 
 
+/****************************************************************************
+*   BIOS Port Config Pages
+****************************************************************************/
+
+typedef struct _CONFIG_PAGE_BIOS_1
+{
+    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    U32                     BiosOptions;                /* 04h */
+    U32                     IOCSettings;                /* 08h */
+    U32                     Reserved1;                  /* 0Ch */
+    U32                     DeviceSettings;             /* 10h */
+    U16                     NumberOfDevices;            /* 14h */
+    U16                     Reserved2;                  /* 16h */
+    U16                     IOTimeoutBlockDevicesNonRM; /* 18h */
+    U16                     IOTimeoutSequential;        /* 1Ah */
+    U16                     IOTimeoutOther;             /* 1Ch */
+    U16                     IOTimeoutBlockDevicesRM;    /* 1Eh */
+} fCONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
+  BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
+
+#define MPI_BIOSPAGE1_PAGEVERSION                       (0x00)
+
+/* values for the BiosOptions field */
+#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE                (0x00000400)
+#define MPI_BIOSPAGE1_OPTIONS_FC_ENABLE                 (0x00000200)
+#define MPI_BIOSPAGE1_OPTIONS_SAS_ENABLE                (0x00000100)
+#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS              (0x00000001)
+
+/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_SPINUP_DELAY          (0x00000F00)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_SPINUP_DELAY         (8)
+
+#define MPI_BIOSPAGE1_IOCSET_MASK_RM_SETTING            (0x000000C0)
+#define MPI_BIOSPAGE1_IOCSET_NONE_RM_SETTING            (0x00000000)
+#define MPI_BIOSPAGE1_IOCSET_BOOT_RM_SETTING            (0x00000040)
+#define MPI_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING           (0x00000080)
+
+#define MPI_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT       (0x00000030)
+#define MPI_BIOSPAGE1_IOCSET_NO_SUPPORT                 (0x00000000)
+#define MPI_BIOSPAGE1_IOCSET_BIOS_SUPPORT               (0x00000010)
+#define MPI_BIOSPAGE1_IOCSET_OS_SUPPORT                 (0x00000020)
+#define MPI_BIOSPAGE1_IOCSET_ALL_SUPPORT                (0x00000030)
+
+#define MPI_BIOSPAGE1_IOCSET_ALTERNATE_CHS              (0x00000008)
+
+/* values for the DeviceSettings field */
+#define MPI_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN            (0x00000008)
+#define MPI_BIOSPAGE1_DEVSET_DISABLE_RM_LUN             (0x00000004)
+#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
+#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN          (0x00000001)
+
 
 /****************************************************************************
 *   SCSI Port Config Pages
@@ -711,7 +833,27 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
 #define MPI_SCSIPORTPAGE0_CAP_DT                        (0x00000002)
 #define MPI_SCSIPORTPAGE0_CAP_QAS                       (0x00000004)
 #define MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK      (0x0000FF00)
+#define MPI_SCSIPORTPAGE0_SYNC_ASYNC                    (0x00)
+#define MPI_SCSIPORTPAGE0_SYNC_5                        (0x32)
+#define MPI_SCSIPORTPAGE0_SYNC_10                       (0x19)
+#define MPI_SCSIPORTPAGE0_SYNC_20                       (0x0C)
+#define MPI_SCSIPORTPAGE0_SYNC_33_33                    (0x0B)
+#define MPI_SCSIPORTPAGE0_SYNC_40                       (0x0A)
+#define MPI_SCSIPORTPAGE0_SYNC_80                       (0x09)
+#define MPI_SCSIPORTPAGE0_SYNC_160                      (0x08)
+#define MPI_SCSIPORTPAGE0_SYNC_UNKNOWN                  (0xFF)
+
+#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD     (8)
+#define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap)      \
+    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \
+    >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD          \
+    )
 #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK      (0x00FF0000)
+#define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET     (16)
+#define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap)      \
+    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
+    >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET          \
+    )
 #define MPI_SCSIPORTPAGE0_CAP_WIDE                      (0x20000000)
 #define MPI_SCSIPORTPAGE0_CAP_AIP                       (0x80000000)
 
@@ -736,11 +878,12 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_1
 } fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1,
   SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t;
 
-#define MPI_SCSIPORTPAGE1_PAGEVERSION                   (0x02)
+#define MPI_SCSIPORTPAGE1_PAGEVERSION                   (0x03)
 
 /* Configuration values */
 #define MPI_SCSIPORTPAGE1_CFG_PORT_SCSI_ID_MASK         (0x000000FF)
 #define MPI_SCSIPORTPAGE1_CFG_PORT_RESPONSE_ID_MASK     (0xFFFF0000)
+#define MPI_SCSIPORTPAGE1_CFG_SHIFT_PORT_RESPONSE_ID    (16)
 
 /* TargetConfig values */
 #define MPI_SCSIPORTPAGE1_TARGCONFIG_TARG_ONLY        (0x01)
@@ -777,6 +920,7 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_2
 #define MPI_SCSIPORTPAGE2_PORT_FLAGS_BASIC_DV_ONLY          (0x00000020)
 #define MPI_SCSIPORTPAGE2_PORT_FLAGS_OFF_DV                 (0x00000060)
 
+
 /* PortSettings values */
 #define MPI_SCSIPORTPAGE2_PORT_HOST_ID_MASK                 (0x0000000F)
 #define MPI_SCSIPORTPAGE2_PORT_MASK_INIT_HBA                (0x00000030)
@@ -785,7 +929,11 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_2
 #define MPI_SCSIPORTPAGE2_PORT_OS_INIT_HBA                  (0x00000020)
 #define MPI_SCSIPORTPAGE2_PORT_BIOS_OS_INIT_HBA             (0x00000030)
 #define MPI_SCSIPORTPAGE2_PORT_REMOVABLE_MEDIA              (0x000000C0)
+#define MPI_SCSIPORTPAGE2_PORT_RM_NONE                      (0x00000000)
+#define MPI_SCSIPORTPAGE2_PORT_RM_BOOT_ONLY                 (0x00000040)
+#define MPI_SCSIPORTPAGE2_PORT_RM_WITH_MEDIA                (0x00000080)
 #define MPI_SCSIPORTPAGE2_PORT_SPINUP_DELAY_MASK            (0x00000F00)
+#define MPI_SCSIPORTPAGE2_PORT_SHIFT_SPINUP_DELAY           (8)
 #define MPI_SCSIPORTPAGE2_PORT_MASK_NEGO_MASTER_SETTINGS    (0x00003000)
 #define MPI_SCSIPORTPAGE2_PORT_NEGO_MASTER_SETTINGS         (0x00000000)
 #define MPI_SCSIPORTPAGE2_PORT_NONE_MASTER_SETTINGS         (0x00001000)
@@ -822,7 +970,9 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_
 #define MPI_SCSIDEVPAGE0_NP_RTI                         (0x00000040)
 #define MPI_SCSIDEVPAGE0_NP_PCOMP_EN                    (0x00000080)
 #define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_PERIOD_MASK        (0x0000FF00)
+#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD           (8)
 #define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK        (0x00FF0000)
+#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET           (16)
 #define MPI_SCSIDEVPAGE0_NP_WIDE                        (0x20000000)
 #define MPI_SCSIDEVPAGE0_NP_AIP                         (0x80000000)
 
@@ -852,7 +1002,9 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_
 #define MPI_SCSIDEVPAGE1_RP_RTI                         (0x00000040)
 #define MPI_SCSIDEVPAGE1_RP_PCOMP_EN                    (0x00000080)
 #define MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK        (0x0000FF00)
+#define MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD       (8)
 #define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK        (0x00FF0000)
+#define MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET       (16)
 #define MPI_SCSIDEVPAGE1_RP_WIDE                        (0x20000000)
 #define MPI_SCSIDEVPAGE1_RP_AIP                         (0x80000000)
 
@@ -998,13 +1150,19 @@ typedef struct _CONFIG_PAGE_FC_PORT_0
 #define MPI_FCPORTPAGE0_SUPPORT_CLASS_2                 (0x00000002)
 #define MPI_FCPORTPAGE0_SUPPORT_CLASS_3                 (0x00000004)
 
-#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED             (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1  1 GBit/sec  */
-#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED             (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2  2 GBit/sec  */
-#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED            (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */
+#define MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN            (0x00000000) /* (SNIA)HBA_PORTSPEED_UNKNOWN 0   Unknown - transceiver incapable of reporting */
+#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED             (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT   1   1 GBit/sec */
+#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED             (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT   2   2 GBit/sec */
+#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED            (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT  4  10 GBit/sec */
+#define MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED             (0x00000008) /* (SNIA)HBA_PORTSPEED_4GBIT   8   4 GBit/sec */
 
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN            MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN
 #define MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT             MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED
 #define MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT             MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED
 #define MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT            MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT             MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_NOT_NEGOTIATED    (0x00008000)        /* (SNIA)HBA_PORTSPEED_NOT_NEGOTIATED (1<<15) Speed not established */
+
 
 
 typedef struct _CONFIG_PAGE_FC_PORT_1
@@ -1019,11 +1177,12 @@ typedef struct _CONFIG_PAGE_FC_PORT_1
     U8                      AltConnector;               /* 1Bh */
     U8                      NumRequestedAliases;        /* 1Ch */
     U8                      RR_TOV;                     /* 1Dh */
-    U16                     Reserved2;                  /* 1Eh */
+    U8                      InitiatorDeviceTimeout;     /* 1Eh */
+    U8                      InitiatorIoPendTimeout;     /* 1Fh */
 } fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1,
   FCPortPage1_t, MPI_POINTER pFCPortPage1_t;
 
-#define MPI_FCPORTPAGE1_PAGEVERSION                     (0x05)
+#define MPI_FCPORTPAGE1_PAGEVERSION                     (0x06)
 
 #define MPI_FCPORTPAGE1_FLAGS_EXT_FCP_STATUS_EN         (0x08000000)
 #define MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY     (0x04000000)
@@ -1031,6 +1190,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_1
 #define MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS     (0x01000000)
 #define MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID          (0x00800000)
 #define MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE              (0x00400000)
+#define MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK        (0x00200000)
 #define MPI_FCPORTPAGE1_FLAGS_MASK_RR_TOV_UNITS         (0x00000070)
 #define MPI_FCPORTPAGE1_FLAGS_SUPPRESS_PROT_REG         (0x00000008)
 #define MPI_FCPORTPAGE1_FLAGS_PLOGI_ON_LOGO             (0x00000004)
@@ -1066,6 +1226,8 @@ typedef struct _CONFIG_PAGE_FC_PORT_1
 
 #define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN                (0x00)
 
+#define MPI_FCPORTPAGE1_INITIATOR_DEV_TIMEOUT_MASK      (0x7F)
+
 
 typedef struct _CONFIG_PAGE_FC_PORT_2
 {
@@ -1627,5 +1789,317 @@ typedef struct _CONFIG_PAGE_LAN_1
 #define MPI_LAN_PAGE1_DEV_STATE_RESET                   (0x00)
 #define MPI_LAN_PAGE1_DEV_STATE_OPERATIONAL             (0x01)
 
+
+/****************************************************************************
+*   Inband Config Pages
+****************************************************************************/
+
+typedef struct _CONFIG_PAGE_INBAND_0
+{
+    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    MPI_VERSION_FORMAT      InbandVersion;              /* 04h */
+    U16                     MaximumBuffers;             /* 08h */
+    U16                     Reserved1;                  /* 0Ah */
+} fCONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0,
+  InbandPage0_t, MPI_POINTER pInbandPage0_t;
+
+#define MPI_INBAND_PAGEVERSION          (0x00)
+
+
+
+/****************************************************************************
+*   SAS IO Unit Config Pages
+****************************************************************************/
+
+typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA
+{
+    U8          Port;                   /* 00h */
+    U8          PortFlags;              /* 01h */
+    U8          PhyFlags;               /* 02h */
+    U8          NegotiatedLinkRate;     /* 03h */
+    U32         ControllerPhyDeviceInfo;/* 04h */
+    U16         AttachedDeviceHandle;   /* 08h */
+    U16         ControllerDevHandle;    /* 0Ah */
+    U32         Reserved2;              /* 0Ch */
+} MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA,
+  SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI_SAS_IOUNIT0_PHY_MAX
+#define MPI_SAS_IOUNIT0_PHY_MAX         (1)
+#endif
+
+typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
+{
+    fCONFIG_EXTENDED_PAGE_HEADER     Header;                             /* 00h */
+    U32                             Reserved1;                          /* 08h */
+    U8                              NumPhys;                            /* 0Ch */
+    U8                              Reserved2;                          /* 0Dh */
+    U16                             Reserved3;                          /* 0Eh */
+    MPI_SAS_IO_UNIT0_PHY_DATA       PhyData[MPI_SAS_IOUNIT0_PHY_MAX];   /* 10h */
+} fCONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
+  SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
+
+#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x00)
+
+/* values for SAS IO Unit Page 0 PortFlags */
+#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS    (0x08)
+#define MPI_SAS_IOUNIT0_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
+#define MPI_SAS_IOUNIT0_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
+#define MPI_SAS_IOUNIT0_PORT_FLAGS_WAIT_FOR_PORTENABLE      (0x02)
+#define MPI_SAS_IOUNIT0_PORT_FLAGS_AUTO_PORT_CONFIG         (0x01)
+
+/* values for SAS IO Unit Page 0 PhyFlags */
+#define MPI_SAS_IOUNIT0_PHY_FLAGS_PHY_DISABLED              (0x04)
+#define MPI_SAS_IOUNIT0_PHY_FLAGS_TX_INVERT                 (0x02)
+#define MPI_SAS_IOUNIT0_PHY_FLAGS_RX_INVERT                 (0x01)
+
+/* values for SAS IO Unit Page 0 NegotiatedLinkRate */
+#define MPI_SAS_IOUNIT0_RATE_UNKNOWN                        (0x00)
+#define MPI_SAS_IOUNIT0_RATE_PHY_DISABLED                   (0x01)
+#define MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION       (0x02)
+#define MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE              (0x03)
+#define MPI_SAS_IOUNIT0_RATE_1_5                            (0x08)
+#define MPI_SAS_IOUNIT0_RATE_3_0                            (0x09)
+
+/* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
+
+
+typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
+{
+    U8          Port;                   /* 00h */
+    U8          PortFlags;              /* 01h */
+    U8          PhyFlags;               /* 02h */
+    U8          MaxMinLinkRate;         /* 03h */
+    U32         ControllerPhyDeviceInfo;/* 04h */
+    U32         Reserved1;              /* 08h */
+} MPI_SAS_IO_UNIT1_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT1_PHY_DATA,
+  SasIOUnit1PhyData, MPI_POINTER pSasIOUnit1PhyData;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI_SAS_IOUNIT1_PHY_MAX
+#define MPI_SAS_IOUNIT1_PHY_MAX         (1)
+#endif
+
+typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
+{
+    fCONFIG_EXTENDED_PAGE_HEADER Header;                             /* 00h */
+    U32                         Reserved1;                          /* 08h */
+    U8                          NumPhys;                            /* 0Ch */
+    U8                          Reserved2;                          /* 0Dh */
+    U16                         Reserved3;                          /* 0Eh */
+    MPI_SAS_IO_UNIT1_PHY_DATA   PhyData[MPI_SAS_IOUNIT1_PHY_MAX];   /* 10h */
+} fCONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
+  SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
+
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x00)
+
+/* values for SAS IO Unit Page 0 PortFlags */
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_WAIT_FOR_PORTENABLE      (0x02)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG         (0x01)
+
+/* values for SAS IO Unit Page 0 PhyFlags */
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE               (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT                 (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT                 (0x01)
+
+/* values for SAS IO Unit Page 0 MaxMinLinkRate */
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                       (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                        (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                        (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                       (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                        (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                        (0x09)
+
+/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
+
+
+typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
+{
+    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U32                                 Reserved1;              /* 08h */
+    U16                                 MaxPersistentIDs;       /* 0Ch */
+    U16                                 NumPersistentIDsUsed;   /* 0Eh */
+    U8                                  Status;                 /* 10h */
+    U8                                  Flags;                  /* 11h */
+    U16                                 Reserved2;              /* 12h */
+} fCONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
+  SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
+
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x00)
+
+/* values for SAS IO Unit Page 2 Status field */
+#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
+#define MPI_SAS_IOUNIT2_STATUS_FULL_PERSISTENT_MAPPINGS     (0x01)
+
+/* values for SAS IO Unit Page 2 Flags field */
+#define MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS   (0x01)
+
+
+typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
+{
+    fCONFIG_EXTENDED_PAGE_HEADER Header;                         /* 00h */
+    U32                         Reserved1;                      /* 08h */
+    U32                         MaxInvalidDwordCount;           /* 0Ch */
+    U32                         InvalidDwordCountTime;          /* 10h */
+    U32                         MaxRunningDisparityErrorCount;  /* 14h */
+    U32                         RunningDisparityErrorTime;      /* 18h */
+    U32                         MaxLossDwordSynchCount;         /* 1Ch */
+    U32                         LossDwordSynchCountTime;        /* 20h */
+    U32                         MaxPhyResetProblemCount;        /* 24h */
+    U32                         PhyResetProblemTime;            /* 28h */
+} fCONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3,
+  SasIOUnitPage3_t, MPI_POINTER pSasIOUnitPage3_t;
+
+#define MPI_SASIOUNITPAGE3_PAGEVERSION      (0x00)
+
+
+typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
+{
+    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U32                                 Reserved1;              /* 08h */
+    U64                                 SASAddress;             /* 0Ch */
+    U32                                 Reserved2;              /* 14h */
+    U16                                 DevHandle;              /* 18h */
+    U16                                 ParentDevHandle;        /* 1Ah */
+    U16                                 ExpanderChangeCount;    /* 1Ch */
+    U16                                 ExpanderRouteIndexes;   /* 1Eh */
+    U8                                  NumPhys;                /* 20h */
+    U8                                  SASLevel;               /* 21h */
+    U8                                  Flags;                  /* 22h */
+    U8                                  Reserved3;              /* 23h */
+} fCONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
+  SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
+
+#define MPI_SASEXPANDER0_PAGEVERSION        (0x00)
+
+/* values for SAS Expander Page 0 Flags field */
+#define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
+#define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS      (0x01)
+
+
+typedef struct _CONFIG_PAGE_SAS_DEVICE_0
+{
+    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U32                                 Reserved1;              /* 08h */
+    U64                                 SASAddress;             /* 0Ch */
+    U32                                 Reserved2;              /* 14h */
+    U16                                 DevHandle;              /* 18h */
+    U8                                  TargetID;               /* 1Ah */
+    U8                                  Bus;                    /* 1Bh */
+    U32                                 DeviceInfo;             /* 1Ch */
+    U16                                 Flags;                  /* 20h */
+    U8                                  PhysicalPort;           /* 22h */
+    U8                                  Reserved3;              /* 23h */
+} fCONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
+  SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t;
+
+#define MPI_SASDEVICE0_PAGEVERSION          (0x00)
+
+/* values for SAS Device Page 0 Flags field */
+#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT    (0x04)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED         (0x02)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT        (0x01)
+
+/* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */
+
+
+typedef struct _CONFIG_PAGE_SAS_DEVICE_1
+{
+    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U32                                 Reserved1;              /* 08h */
+    U64                                 SASAddress;             /* 0Ch */
+    U32                                 Reserved2;              /* 14h */
+    U16                                 DevHandle;              /* 18h */
+    U8                                  TargetID;               /* 1Ah */
+    U8                                  Bus;                    /* 1Bh */
+    U8                                  InitialRegDeviceFIS[20];/* 1Ch */
+} fCONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1,
+  SasDevicePage1_t, MPI_POINTER pSasDevicePage1_t;
+
+#define MPI_SASDEVICE1_PAGEVERSION          (0x00)
+
+
+typedef struct _CONFIG_PAGE_SAS_PHY_0
+{
+    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U32                                 Reserved1;              /* 08h */
+    U64                                 SASAddress;             /* 0Ch */
+    U16                                 AttachedDevHandle;      /* 14h */
+    U8                                  AttachedPhyIdentifier;  /* 16h */
+    U8                                  Reserved2;              /* 17h */
+    U32                                 AttachedDeviceInfo;     /* 18h */
+    U8                                  ProgrammedLinkRate;     /* 20h */
+    U8                                  HwLinkRate;             /* 21h */
+    U8                                  ChangeCount;            /* 22h */
+    U8                                  Reserved3;              /* 23h */
+    U32                                 PhyInfo;                /* 24h */
+} fCONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
+  SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
+
+#define MPI_SASPHY0_PAGEVERSION             (0x00)
+
+/* values for SAS PHY Page 0 ProgrammedLinkRate field */
+#define MPI_SAS_PHY0_PRATE_MAX_RATE_MASK                        (0xF0)
+#define MPI_SAS_PHY0_PRATE_MAX_RATE_NOT_PROGRAMMABLE            (0x00)
+#define MPI_SAS_PHY0_PRATE_MAX_RATE_1_5                         (0x80)
+#define MPI_SAS_PHY0_PRATE_MAX_RATE_3_0                         (0x90)
+#define MPI_SAS_PHY0_PRATE_MIN_RATE_MASK                        (0x0F)
+#define MPI_SAS_PHY0_PRATE_MIN_RATE_NOT_PROGRAMMABLE            (0x00)
+#define MPI_SAS_PHY0_PRATE_MIN_RATE_1_5                         (0x08)
+#define MPI_SAS_PHY0_PRATE_MIN_RATE_3_0                         (0x09)
+
+/* values for SAS PHY Page 0 HwLinkRate field */
+#define MPI_SAS_PHY0_HWRATE_MAX_RATE_MASK                       (0xF0)
+#define MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5                        (0x80)
+#define MPI_SAS_PHY0_HWRATE_MAX_RATE_3_0                        (0x90)
+#define MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK                       (0x0F)
+#define MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5                        (0x08)
+#define MPI_SAS_PHY0_HWRATE_MIN_RATE_3_0                        (0x09)
+
+/* values for SAS PHY Page 0 PhyInfo field */
+#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_ACTIVE                   (0x00004000)
+#define MPI_SAS_PHY0_PHYINFO_SATA_PORT_SELECTOR                 (0x00002000)
+#define MPI_SAS_PHY0_PHYINFO_VIRTUAL_PHY                        (0x00001000)
+
+#define MPI_SAS_PHY0_PHYINFO_MASK_PARTIAL_PATHWAY_TIME          (0x00000F00)
+#define MPI_SAS_PHY0_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME         (8)
+
+#define MPI_SAS_PHY0_PHYINFO_MASK_ROUTING_ATTRIBUTE             (0x000000F0)
+#define MPI_SAS_PHY0_PHYINFO_DIRECT_ROUTING                     (0x00000000)
+#define MPI_SAS_PHY0_PHYINFO_SUBTRACTIVE_ROUTING                (0x00000010)
+#define MPI_SAS_PHY0_PHYINFO_TABLE_ROUTING                      (0x00000020)
+
+#define MPI_SAS_PHY0_PHYINFO_MASK_LINK_RATE                     (0x0000000F)
+#define MPI_SAS_PHY0_PHYINFO_UNKNOWN_LINK_RATE                  (0x00000000)
+#define MPI_SAS_PHY0_PHYINFO_PHY_DISABLED                       (0x00000001)
+#define MPI_SAS_PHY0_PHYINFO_NEGOTIATION_FAILED                 (0x00000002)
+#define MPI_SAS_PHY0_PHYINFO_SATA_OOB_COMPLETE                  (0x00000003)
+#define MPI_SAS_PHY0_PHYINFO_RATE_1_5                           (0x00000008)
+#define MPI_SAS_PHY0_PHYINFO_RATE_3_0                           (0x00000009)
+
+
+typedef struct _CONFIG_PAGE_SAS_PHY_1
+{
+    fCONFIG_EXTENDED_PAGE_HEADER Header;                     /* 00h */
+    U32                         Reserved1;                  /* 08h */
+    U32                         InvalidDwordCount;          /* 0Ch */
+    U32                         RunningDisparityErrorCount; /* 10h */
+    U32                         LossDwordSynchCount;        /* 14h */
+    U32                         PhyResetProblemCount;       /* 18h */
+} fCONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1,
+  SasPhyPage1_t, MPI_POINTER pSasPhyPage1_t;
+
+#define MPI_SASPHY1_PAGEVERSION             (0x00)
+
+
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_fc.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_fc.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_fc.h	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_fc.h	2004-07-30 16:26:04.000000000 +0000
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2002 LSI Logic Corporation.
+ *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_FC.H
+ *           Name:  mpi_fc.h
  *          Title:  MPI Fibre Channel messages and structures
  *  Creation Date:  June 12, 2000
  *
- *    MPI_FC.H Version:  01.02.03
+ *    mpi_fc.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -45,7 +45,7 @@
 
 /*****************************************************************************
 *
-*        F C    T a r g e t    M o d e    M e s s a g e s
+*        F C    D i r e c t    A c c e s s     M e s s a g e s
 *
 *****************************************************************************/
 
@@ -334,6 +334,7 @@ typedef struct _MSG_FC_PRIMITIVE_SEND_RE
   FcPrimitiveSendRequest_t, MPI_POINTER pFcPrimitiveSendRequest_t;
 
 #define MPI_FC_PRIM_SEND_FLAGS_PORT_MASK       (0x01)
+#define MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK   (0x02)
 #define MPI_FC_PRIM_SEND_FLAGS_RESET_LINK      (0x04)
 #define MPI_FC_PRIM_SEND_FLAGS_STOP_SEND       (0x08)
 #define MPI_FC_PRIM_SEND_FLAGS_SEND_ONCE       (0x10)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_inb.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_inb.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_inb.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_inb.h	2004-07-30 16:24:42.000000000 +0000
@@ -0,0 +1,220 @@
+/*
+ *  Copyright (c) 2003 LSI Logic Corporation.
+ *
+ *
+ *           Name:  mpi_inb.h
+ *          Title:  MPI Inband structures and definitions
+ *  Creation Date:  September 30, 2003
+ *
+ *    mpi_inb.h Version:  01.03.xx
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  ??-??-??  01.03.01  Original release.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_INB_H
+#define MPI_INB_H
+
+/******************************************************************************
+*
+*        I n b a n d    M e s s a g e s
+*
+*******************************************************************************/
+
+
+/****************************************************************************/
+/* Inband Buffer Post Request                                               */
+/****************************************************************************/
+
+typedef struct _MSG_INBAND_BUFFER_POST_REQUEST
+{
+    U8                      Reserved1;          /* 00h */
+    U8                      BufferCount;        /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved4;          /* 0Ch */
+    SGE_TRANS_SIMPLE_UNION  SGL;                /* 10h */
+} MSG_INBAND_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REQUEST,
+  MpiInbandBufferPostRequest_t , MPI_POINTER pMpiInbandBufferPostRequest_t;
+
+
+typedef struct _WWN_FC_FORMAT
+{
+    U64                     NodeName;           /* 00h */
+    U64                     PortName;           /* 08h */
+} WWN_FC_FORMAT, MPI_POINTER PTR_WWN_FC_FORMAT,
+  WwnFcFormat_t, MPI_POINTER pWwnFcFormat_t;
+
+typedef struct _WWN_SAS_FORMAT
+{
+    U64                     WorldWideID;        /* 00h */
+    U32                     Reserved1;          /* 08h */
+    U32                     Reserved2;          /* 0Ch */
+} WWN_SAS_FORMAT, MPI_POINTER PTR_WWN_SAS_FORMAT,
+  WwnSasFormat_t, MPI_POINTER pWwnSasFormat_t;
+
+typedef union _WWN_INBAND_FORMAT
+{
+    WWN_FC_FORMAT           Fc;
+    WWN_SAS_FORMAT          Sas;
+} WWN_INBAND_FORMAT, MPI_POINTER PTR_WWN_INBAND_FORMAT,
+  WwnInbandFormat, MPI_POINTER pWwnInbandFormat;
+
+
+/* Inband Buffer Post reply message */
+
+typedef struct _MSG_INBAND_BUFFER_POST_REPLY
+{
+    U16                     Reserved1;          /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved4;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     TransferLength;     /* 14h */
+    U32                     TransactionContext; /* 18h */
+    WWN_INBAND_FORMAT       Wwn;                /* 1Ch */
+    U32                     IOCIdentifier[4];   /* 2Ch */
+} MSG_INBAND_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_INBAND_BUFFER_POST_REPLY,
+  MpiInbandBufferPostReply_t, MPI_POINTER pMpiInbandBufferPostReply_t;
+
+
+/****************************************************************************/
+/* Inband Send Request                                                      */
+/****************************************************************************/
+
+typedef struct _MSG_INBAND_SEND_REQUEST
+{
+    U16                     Reserved1;          /* 00h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved4;          /* 0Ch */
+    WWN_INBAND_FORMAT       Wwn;                /* 10h */
+    U32                     Reserved5;          /* 20h */
+    SGE_IO_UNION            SGL;                /* 24h */
+} MSG_INBAND_SEND_REQUEST, MPI_POINTER PTR_MSG_INBAND_SEND_REQUEST,
+  MpiInbandSendRequest_t , MPI_POINTER pMpiInbandSendRequest_t;
+
+
+/* Inband Send reply message */
+
+typedef struct _MSG_INBAND_SEND_REPLY
+{
+    U16                     Reserved1;          /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved4;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     ResponseLength;     /* 14h */
+} MSG_INBAND_SEND_REPLY, MPI_POINTER PTR_MSG_INBAND_SEND_REPLY,
+  MpiInbandSendReply_t, MPI_POINTER pMpiInbandSendReply_t;
+
+
+/****************************************************************************/
+/* Inband Response Request                                                  */
+/****************************************************************************/
+
+typedef struct _MSG_INBAND_RSP_REQUEST
+{
+    U16                     Reserved1;          /* 00h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved4;          /* 0Ch */
+    WWN_INBAND_FORMAT       Wwn;                /* 10h */
+    U32                     IOCIdentifier[4];   /* 20h */
+    U32                     ResponseLength;     /* 30h */
+    SGE_IO_UNION            SGL;                /* 34h */
+} MSG_INBAND_RSP_REQUEST, MPI_POINTER PTR_MSG_INBAND_RSP_REQUEST,
+  MpiInbandRspRequest_t , MPI_POINTER pMpiInbandRspRequest_t;
+
+
+/* Inband Response reply message */
+
+typedef struct _MSG_INBAND_RSP_REPLY
+{
+    U16                     Reserved1;          /* 00h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved4;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+} MSG_INBAND_RSP_REPLY, MPI_POINTER PTR_MSG_INBAND_RSP_REPLY,
+  MpiInbandRspReply_t, MPI_POINTER pMpiInbandRspReply_t;
+
+
+/****************************************************************************/
+/* Inband Abort Request                                                     */
+/****************************************************************************/
+
+typedef struct _MSG_INBAND_ABORT_REQUEST
+{
+    U8                      Reserved1;          /* 00h */
+    U8                      AbortType;          /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved4;          /* 0Ch */
+    U32                     ContextToAbort;     /* 10h */
+} MSG_INBAND_ABORT_REQUEST, MPI_POINTER PTR_MSG_INBAND_ABORT_REQUEST,
+  MpiInbandAbortRequest_t , MPI_POINTER pMpiInbandAbortRequest_t;
+
+#define MPI_INBAND_ABORT_TYPE_ALL_BUFFERS       (0x00)
+#define MPI_INBAND_ABORT_TYPE_EXACT_BUFFER      (0x01)
+#define MPI_INBAND_ABORT_TYPE_SEND_REQUEST      (0x02)
+#define MPI_INBAND_ABORT_TYPE_RESPONSE_REQUEST  (0x03)
+
+
+/* Inband Abort reply message */
+
+typedef struct _MSG_INBAND_ABORT_REPLY
+{
+    U8                      Reserved1;          /* 00h */
+    U8                      AbortType;          /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved4;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+} MSG_INBAND_ABORT_REPLY, MPI_POINTER PTR_MSG_INBAND_ABORT_REPLY,
+  MpiInbandAbortReply_t, MPI_POINTER pMpiInbandAbortReply_t;
+
+
+#endif
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_init.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_init.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_init.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_init.h	2004-07-30 16:25:15.000000000 +0000
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2002 LSI Logic Corporation.
+ *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_INIT.H
+ *           Name:  mpi_init.h
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    MPI_INIT.H Version:  01.02.07
+ *    mpi_init.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -47,7 +47,7 @@
 *****************************************************************************/
 
 /****************************************************************************/
-/*  SCSI IO messages and assocaited structures                              */
+/*  SCSI IO messages and associated structures                              */
 /****************************************************************************/
 
 typedef struct _MSG_SCSI_IO_REQUEST
@@ -80,6 +80,16 @@ typedef struct _MSG_SCSI_IO_REQUEST
 #define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST           (0x00)
 #define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC            (0x02)
 #define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR  (0x04)
+#define MPI_SCSIIO_MSGFLGS_EEDP_TYPE_MASK           (0xE0)
+#define MPI_SCSIIO_MSGFLGS_EEDP_NONE                (0x00)
+#define MPI_SCSIIO_MSGFLGS_EEDP_RDPROTECT_T10       (0x20)
+#define MPI_SCSIIO_MSGFLGS_EEDP_VRPROTECT_T10       (0x40)
+#define MPI_SCSIIO_MSGFLGS_EEDP_WRPROTECT_T10       (0x60)
+#define MPI_SCSIIO_MSGFLGS_EEDP_520_READ_MODE1      (0x20)
+#define MPI_SCSIIO_MSGFLGS_EEDP_520_WRITE_MODE1     (0x40)
+#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_READ_MODE1      (0x60)
+#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_WRITE_MODE1     (0x80)
+
 
 /* SCSI IO LUN fields */
 
@@ -182,6 +192,33 @@ typedef struct _MSG_SCSI_IO_REPLY
 
 
 /****************************************************************************/
+/*  SCSI IO 32 Request message structure                                    */
+/****************************************************************************/
+
+typedef struct _MSG_SCSI_IO32_REQUEST
+{
+    U8                      TargetID;           /* 00h */
+    U8                      Bus;                /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U8                      CDBLength;          /* 04h */
+    U8                      SenseBufferLength;  /* 05h */
+    U8                      Reserved;           /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U8                      LUN[8];             /* 0Ch */
+    U32                     Control;            /* 14h */
+    U8                      CDB[32];            /* 18h */
+    U32                     DataLength;         /* 38h */
+    U32                     SenseBufferLowAddr; /* 3Ch */
+    SGE_IO_UNION            SGL;                /* 40h */
+} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
+  SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
+
+/* SCSI IO 32 uses the same defines as above for SCSI IO */
+
+
+/****************************************************************************/
 /*  SCSI Task Management messages                                           */
 /****************************************************************************/
 
@@ -209,6 +246,7 @@ typedef struct _MSG_SCSI_TASK_MGMT
 #define MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET          (0x03)
 #define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS             (0x04)
 #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET    (0x05)
+#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET        (0x06)
 
 /* MsgFlags bits */
 #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_ioc.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_ioc.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_ioc.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_ioc.h	2004-07-30 16:27:14.000000000 +0000
@@ -2,11 +2,11 @@
  *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_IOC.H
+ *           Name:  mpi_ioc.h
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    MPI_IOC.H Version:  01.02.08
+ *    mpi_ioc.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -89,19 +89,21 @@ typedef struct _MSG_IOC_INIT
     U8                      Reserved1[2];               /* 0Eh */
     U32                     HostMfaHighAddr;            /* 10h */
     U32                     SenseBufferHighAddr;        /* 14h */
+    U32                     ReplyFifoHostSignalingAddr; /* 18h */
 } MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT,
   IOCInit_t, MPI_POINTER pIOCInit_t;
 
 /* WhoInit values */
-#define MPI_WHOINIT_NO_ONE                      (0x00)
-#define MPI_WHOINIT_SYSTEM_BIOS                 (0x01)
-#define MPI_WHOINIT_ROM_BIOS                    (0x02)
-#define MPI_WHOINIT_PCI_PEER                    (0x03)
-#define MPI_WHOINIT_HOST_DRIVER                 (0x04)
-#define MPI_WHOINIT_MANUFACTURER                (0x05)
+#define MPI_WHOINIT_NO_ONE                          (0x00)
+#define MPI_WHOINIT_SYSTEM_BIOS                     (0x01)
+#define MPI_WHOINIT_ROM_BIOS                        (0x02)
+#define MPI_WHOINIT_PCI_PEER                        (0x03)
+#define MPI_WHOINIT_HOST_DRIVER                     (0x04)
+#define MPI_WHOINIT_MANUFACTURER                    (0x05)
 
 /* Flags values */
-#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE      (0x01)
+#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE          (0x01)
+#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL    (0x02)
 
 typedef struct _MSG_IOC_INIT_REPLY
 {
@@ -181,8 +183,10 @@ typedef struct _MSG_IOC_FACTS_REPLY
     U8                      MaxDevices;                 /* 2Eh */
     U8                      MaxBuses;                   /* 2Fh */
     U32                     FWImageSize;                /* 30h */
-    U32                     Reserved4;                  /* 34h */
+    U32                     IOCCapabilities;            /* 34h */
     MPI_FW_VERSION          FWVersion;                  /* 38h */
+    U16                     HighPriorityQueueDepth;     /* 3Ch */
+    U16                     Reserved2;                  /* 3Eh */
 } MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY,
   IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t;
 
@@ -194,12 +198,22 @@ typedef struct _MSG_IOC_FACTS_REPLY
 
 #define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL    (0x0001)
 #define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID     (0x0002)
+#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL        (0x0004)
+#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL   (0x0008)
 
 #define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT         (0x01)
 
 #define MPI_IOCFACTS_EVENTSTATE_DISABLED            (0x00)
 #define MPI_IOCFACTS_EVENTSTATE_ENABLED             (0x01)
 
+#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q          (0x00000001)
+#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL   (0x00000002)
+#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004)
+#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER   (0x00000008)
+#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER     (0x00000010)
+#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER     (0x00000020)
+#define MPI_IOCFACTS_CAPABILITY_EEDP                (0x00000040)
+
 
 
 /*****************************************************************************
@@ -255,6 +269,8 @@ typedef struct _MSG_PORT_FACTS_REPLY
 #define MPI_PORTFACTS_PORTTYPE_INACTIVE         (0x00)
 #define MPI_PORTFACTS_PORTTYPE_SCSI             (0x01)
 #define MPI_PORTFACTS_PORTTYPE_FC               (0x10)
+#define MPI_PORTFACTS_PORTTYPE_ISCSI            (0x20)
+#define MPI_PORTFACTS_PORTTYPE_SAS              (0x30)
 
 /* ProtocolFlags values */
 
@@ -388,6 +404,10 @@ typedef struct _MSG_EVENT_ACK_REPLY
 #define MPI_EVENT_INTEGRATED_RAID           (0x0000000B)
 #define MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE (0x0000000C)
 #define MPI_EVENT_ON_BUS_TIMER_EXPIRED      (0x0000000D)
+#define MPI_EVENT_QUEUE_FULL                (0x0000000E)
+#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE  (0x0000000F)
+#define MPI_EVENT_SAS_SES                   (0x00000010)
+#define MPI_EVENT_PERSISTENT_TABLE_FULL     (0x00000011)
 
 /* AckRequired field values */
 
@@ -435,6 +455,39 @@ typedef struct _EVENT_DATA_SCSI_DEVICE_S
 #define MPI_EVENT_SCSI_DEV_STAT_RC_NOT_RESPONDING       (0x04)
 #define MPI_EVENT_SCSI_DEV_STAT_RC_SMART_DATA           (0x05)
 
+/* SAS Device Status Change Event data */
+
+typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
+{
+    U8                      TargetID;                   /* 00h */
+    U8                      Bus;                        /* 01h */
+    U8                      ReasonCode;                 /* 02h */
+    U8                      Reserved;                   /* 03h */
+    U8                      ASC;                        /* 04h */
+    U8                      ASCQ;                       /* 05h */
+    U16                     DevHandle;                  /* 06h */
+    U32                     DeviceInfo;                 /* 08h */
+} EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+  MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+  MpiEventDataSasDeviceStatusChange_t,
+  MPI_POINTER pMpiEventDataSasDeviceStatusChange_t;
+
+/* MPI SAS Device Status Change Event data ReasonCode values */
+#define MPI_EVENT_SAS_DEV_STAT_RC_ADDED                 (0x03)
+#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING        (0x04)
+#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA            (0x05)
+#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED      (0x06)
+
+/* SCSI Event data for Queue Full event */
+
+typedef struct _EVENT_DATA_QUEUE_FULL
+{
+    U8                      TargetID;                   /* 00h */
+    U8                      Bus;                        /* 01h */
+    U16                     CurrentDepth;               /* 02h */
+} EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL,
+  EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t;
+
 /* MPI Link Status Change Event data */
 
 typedef struct _EVENT_DATA_LINK_STATUS
@@ -540,6 +593,7 @@ typedef struct _MSG_FW_DOWNLOAD
 #define MPI_FW_DOWNLOAD_ITYPE_FW            (0x01)
 #define MPI_FW_DOWNLOAD_ITYPE_BIOS          (0x02)
 #define MPI_FW_DOWNLOAD_ITYPE_NVDATA        (0x03)
+#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER    (0x04)
 
 
 typedef struct _FWDownloadTCSGE
@@ -592,6 +646,7 @@ typedef struct _MSG_FW_UPLOAD
 #define MPI_FW_UPLOAD_ITYPE_FW_FLASH        (0x01)
 #define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH      (0x02)
 #define MPI_FW_UPLOAD_ITYPE_NVDATA          (0x03)
+#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER      (0x04)
 
 typedef struct _FWUploadTCSGE
 {
@@ -655,6 +710,7 @@ typedef struct _MPI_FW_HEADER
 #define MPI_FW_HEADER_PID_TYPE_MASK             (0xF000)
 #define MPI_FW_HEADER_PID_TYPE_SCSI             (0x0000)
 #define MPI_FW_HEADER_PID_TYPE_FC               (0x1000)
+#define MPI_FW_HEADER_PID_TYPE_SAS              (0x2000)
 
 #define MPI_FW_HEADER_SIGNATURE_0               (0x5AEAA55A)
 #define MPI_FW_HEADER_SIGNATURE_1               (0xA55AEAA5)
@@ -669,6 +725,7 @@ typedef struct _MPI_FW_HEADER
 #define MPI_FW_HEADER_PID_PROD_CTX_SCSI                 (0x0600)
 
 #define MPI_FW_HEADER_PID_FAMILY_MASK           (0x00FF)
+/* SCSI */
 #define MPI_FW_HEADER_PID_FAMILY_1030A0_SCSI    (0x0001)
 #define MPI_FW_HEADER_PID_FAMILY_1030B0_SCSI    (0x0002)
 #define MPI_FW_HEADER_PID_FAMILY_1030B1_SCSI    (0x0003)
@@ -681,9 +738,15 @@ typedef struct _MPI_FW_HEADER
 #define MPI_FW_HEADER_PID_FAMILY_1035B0_SCSI    (0x000A)
 #define MPI_FW_HEADER_PID_FAMILY_1030TA0_SCSI   (0x000B)
 #define MPI_FW_HEADER_PID_FAMILY_1020TA0_SCSI   (0x000C)
+/* Fibre Channel */
 #define MPI_FW_HEADER_PID_FAMILY_909_FC         (0x0000)
 #define MPI_FW_HEADER_PID_FAMILY_919_FC         (0x0001)
 #define MPI_FW_HEADER_PID_FAMILY_919X_FC        (0x0002)
+#define MPI_FW_HEADER_PID_FAMILY_919XL_FC       (0x0003)
+#define MPI_FW_HEADER_PID_FAMILY_949_FC         (0x0004)
+#define MPI_FW_HEADER_PID_FAMILY_959_FC         (0x0005)
+/* SAS */
+#define MPI_FW_HEADER_PID_FAMILY_1064_SAS       (0x0001)
 
 typedef struct _MPI_EXT_IMAGE_HEADER
 {
@@ -702,5 +765,6 @@ typedef struct _MPI_EXT_IMAGE_HEADER
 #define MPI_EXT_IMAGE_TYPE_UNSPECIFIED          (0x00)
 #define MPI_EXT_IMAGE_TYPE_FW                   (0x01)
 #define MPI_EXT_IMAGE_TYPE_NVDATA               (0x03)
+#define MPI_EXT_IMAGE_TYPE_BOOTLOADER           (0x04)
 
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_lan.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_lan.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_lan.h	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_lan.h	2004-07-30 16:28:43.000000000 +0000
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2002 LSI Logic Corporation.
+ *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_LAN.H
+ *           Name:  mpi_lan.h
  *          Title:  MPI LAN messages and structures
  *  Creation Date:  June 30, 2000
  *
- *    MPI_LAN.H Version:  01.02.01
+ *    mpi_lan.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_raid.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_raid.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_raid.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_raid.h	2004-07-30 16:29:57.000000000 +0000
@@ -2,11 +2,11 @@
  *  Copyright (c) 2001-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_RAID.H
+ *           Name:  mpi_raid.h
  *          Title:  MPI RAID message and structures
  *  Creation Date:  February 27, 2001
  *
- *    MPI_RAID.H Version:  01.02.09
+ *    mpi_raid.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -43,7 +43,7 @@
 
 
 /****************************************************************************/
-/* RAID Volume Request                                                      */
+/* RAID Action Request                                                      */
 /****************************************************************************/
 
 typedef struct _MSG_RAID_ACTION
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_sas.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_sas.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_sas.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_sas.h	2004-07-30 16:29:25.000000000 +0000
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (c) 2003 LSI Logic Corporation.
+ *
+ *
+ *           Name:  mpi_sas.h
+ *          Title:  MPI Serial Attached SCSI structures and definitions
+ *  Creation Date:  April 23, 2003
+ *
+ *    mpi_sas.h Version:  01.05.xx
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Date      Version   Description
+ *  --------  --------  ------------------------------------------------------
+ *  xx-yy-zz  01.05.01  Original release.
+ *  --------------------------------------------------------------------------
+ */
+
+#ifndef MPI_SAS_H
+#define MPI_SAS_H
+
+/*****************************************************************************
+*
+*        S e r i a l    A t t a c h e d    S C S I     M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/* Serial Management Protocol Passthrough Request                           */
+/****************************************************************************/
+
+typedef struct _MSG_SMP_PASSTHROUGH_REQUEST
+{
+    U8                      PassthroughFlags;   /* 00h */
+    U8                      PhysicalPort;       /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     RequestDataLength;  /* 04h */
+    U8                      ConnectionRate;     /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved1;          /* 0Ch */
+    U64                     SASAddress;         /* 10h */
+    U32                     Reserved2;          /* 18h */
+    U32                     Reserved3;          /* 1Ch */
+    SGE_SIMPLE_UNION        SGL;                /* 20h */
+} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST,
+  SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t;
+
+#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE       (0x80)
+
+#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED  (0x00)
+#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5         (0x08)
+#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0         (0x09)
+
+
+/* Serial Management Protocol Passthrough Reply */
+typedef struct _MSG_SMP_PASSTHROUGH_REPLY
+{
+    U8                      PassthroughFlags;   /* 00h */
+    U8                      PhysicalPort;       /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     ResponseDataLength; /* 04h */
+    U8                      Reserved1;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U8                      Reserved2;          /* 0Ch */
+    U8                      SASStatus;          /* 0Dh */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     Reserved3;          /* 14h */
+    U8                      ResponseData[4];    /* 18h */
+} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY,
+  SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t;
+
+#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE     (0x80)
+
+/* values for the SASStatus field */
+#define MPI_SASSTATUS_SUCCESS                           (0x00)
+#define MPI_SASSTATUS_UNKNOWN_ERROR                     (0x01)
+#define MPI_SASSTATUS_INVALID_FRAME                     (0x02)
+#define MPI_SASSTATUS_UTC_BAD_DEST                      (0x03)
+#define MPI_SASSTATUS_UTC_BREAK_RECEIVED                (0x04)
+#define MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED    (0x05)
+#define MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST            (0x06)
+#define MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED        (0x07)
+#define MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY            (0x08)
+#define MPI_SASSTATUS_UTC_WRONG_DESTINATION             (0x09)
+#define MPI_SASSTATUS_SHORT_INFORMATION_UNIT            (0x0A)
+#define MPI_SASSTATUS_LONG_INFORMATION_UNIT             (0x0B)
+#define MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA     (0x0C)
+#define MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR     (0x0D)
+#define MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED             (0x0E)
+#define MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH        (0x0F)
+#define MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA           (0x10)
+#define MPI_SASSTATUS_DATA_OFFSET_ERROR                 (0x11)
+#define MPI_SASSTATUS_SDSF_NAK_RECEIVED                 (0x12)
+#define MPI_SASSTATUS_SDSF_CONNECTION_FAILED            (0x13)
+#define MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT        (0x14)
+
+
+/*
+ * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
+ * data and SAS IO Unit Configuration pages.
+ */
+#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE        (0x00002000)
+#define MPI_SAS_DEVICE_INFO_LSI_DEVICE          (0x00001000)
+#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH       (0x00000800)
+#define MPI_SAS_DEVICE_INFO_SSP_TARGET          (0x00000400)
+#define MPI_SAS_DEVICE_INFO_STP_TARGET          (0x00000200)
+#define MPI_SAS_DEVICE_INFO_SMP_TARGET          (0x00000100)
+#define MPI_SAS_DEVICE_INFO_SATA_DEVICE         (0x00000080)
+#define MPI_SAS_DEVICE_INFO_SSP_INITIATOR       (0x00000040)
+#define MPI_SAS_DEVICE_INFO_STP_INITIATOR       (0x00000020)
+#define MPI_SAS_DEVICE_INFO_SMP_INITIATOR       (0x00000010)
+#define MPI_SAS_DEVICE_INFO_SATA_HOST           (0x00000008)
+
+#define MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE    (0x00000007)
+#define MPI_SAS_DEVICE_INFO_NO_DEVICE           (0x00000000)
+#define MPI_SAS_DEVICE_INFO_END_DEVICE          (0x00000001)
+#define MPI_SAS_DEVICE_INFO_EDGE_EXPANDER       (0x00000002)
+#define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER     (0x00000003)
+
+
+/****************************************************************************/
+/* SAS IO Unit Control Request                                              */
+/****************************************************************************/
+
+typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
+{
+    U8                      Operation;          /* 00h */
+    U8                      Reserved1;          /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U8                      TargetID;           /* 0Ch */
+    U8                      Bus;                /* 0Dh */
+    U8                      PhyNum;             /* 0Eh */
+    U8                      Reserved4;          /* 0Fh */
+    U32                     Reserved5;          /* 10h */
+    U64                     SASAddress;         /* 14h */
+    U32                     Reserved6;          /* 1Ch */
+} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
+  SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
+
+/* values for the ... field */
+#define MPI_SAS_OP_CLEAR_NOT_PRESENT             (0x01)
+#define MPI_SAS_OP_CLEAR_ALL                     (0x02)
+#define MPI_SAS_OP_MAP                           (0x03)
+#define MPI_SAS_OP_MOVE                          (0x04)
+#define MPI_SAS_OP_CLEAR                         (0x05)
+#define MPI_SAS_OP_PHY_LINK_RESET                (0x06)
+#define MPI_SAS_OP_PHY_HARD_RESET                (0x07)
+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG           (0x08)
+
+
+/* SAS IO Unit Control Reply */
+typedef struct _MSG_SAS_IOUNIT_CONTROL_REPLY
+{
+    U8                      Operation;          /* 00h */
+    U8                      Reserved1;          /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     Reserved2;          /* 04h */
+    U8                      Reserved3;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U16                     Reserved4;          /* 0Ch */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+} MSG_SAS_IOUNIT_CONTROL_REPLY, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REPLY,
+  SasIoUnitControlReply_t, MPI_POINTER pSasIoUnitControlReply_t;
+
+#endif
+
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_targ.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_targ.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_targ.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_targ.h	2004-07-30 16:26:03.000000000 +0000
@@ -2,11 +2,11 @@
  *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_TARG.H
+ *           Name:  mpi_targ.h
  *          Title:  MPI Target mode messages and structures
  *  Creation Date:  June 22, 2000
  *
- *    MPI_TARG.H Version:  01.02.09
+ *    mpi_targ.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_tool.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_tool.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_tool.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_tool.h	2004-07-30 16:29:45.000000000 +0000
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2001 LSI Logic Corporation.
+ *  Copyright (c) 2001-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_TOOL.H
+ *           Name:  mpi_tool.h
  *          Title:  MPI Toolbox structures and definitions
  *  Creation Date:  July 30, 2001
  *
- *    MPI Version:  01.02.02
+ *    mpi_tool.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
@@ -24,6 +24,8 @@
 #define MPI_TOOLBOX_CLEAN_TOOL                      (0x00)
 #define MPI_TOOLBOX_MEMORY_MOVE_TOOL                (0x01)
 #define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL           (0x02)
+#define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL           (0x03)
+#define MPI_TOOLBOX_FC_MANAGEMENT_TOOL              (0x04)
 
 
 /****************************************************************************/
@@ -68,6 +70,12 @@ typedef struct _MSG_TOOLBOX_CLEAN_REQUES
 #define MPI_TOOLBOX_CLEAN_NVSRAM                    (0x00000001)
 #define MPI_TOOLBOX_CLEAN_SEEPROM                   (0x00000002)
 #define MPI_TOOLBOX_CLEAN_FLASH                     (0x00000004)
+#define MPI_TOOLBOX_CLEAN_BOOTLOADER                (0x04000000)
+#define MPI_TOOLBOX_CLEAN_FW_BACKUP                 (0x08000000)
+#define MPI_TOOLBOX_CLEAN_FW_CURRENT                (0x10000000)
+#define MPI_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES       (0x20000000)
+#define MPI_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES    (0x40000000)
+#define MPI_TOOLBOX_CLEAN_BOOT_SERVICES             (0x80000000)
 
 
 /****************************************************************************/
@@ -124,6 +132,174 @@ typedef struct _DIAG_DATA_UPLOAD_HEADER
 #define MPI_TB_DIAG_FORMAT_FC_TRACE_1               (0x04)
 
 
+/****************************************************************************/
+/* Toolbox ISTWI Read Write request                                         */
+/****************************************************************************/
+
+typedef struct _MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST
+{
+    U8                      Tool;                       /* 00h */
+    U8                      Reserved;                   /* 01h */
+    U8                      ChainOffset;                /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved1;                  /* 04h */
+    U8                      Reserved2;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U8                      Flags;                      /* 0Ch */
+    U8                      BusNum;                     /* 0Dh */
+    U16                     Reserved3;                  /* 0Eh */
+    U8                      NumAddressBytes;            /* 10h */
+    U8                      Reserved4;                  /* 11h */
+    U16                     DataLength;                 /* 12h */
+    U8                      DeviceAddr;                 /* 14h */
+    U8                      Addr1;                      /* 15h */
+    U8                      Addr2;                      /* 16h */
+    U8                      Addr3;                      /* 17h */
+    U32                     Reserved5;                  /* 18h */
+    SGE_SIMPLE_UNION        SGL;                        /* 1Ch */
+} MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_ISTWI_READ_WRITE_REQUEST,
+  ToolboxIstwiReadWriteRequest_t, MPI_POINTER pToolboxIstwiReadWriteRequest_t;
+
+#define MPI_TB_ISTWI_FLAGS_WRITE                    (0x00)
+#define MPI_TB_ISTWI_FLAGS_READ                     (0x01)
+
+
+/****************************************************************************/
+/* Toolbox FC Management request                                            */
+/****************************************************************************/
+
+/* ActionInfo for Bus and TargetId */
+typedef struct _MPI_TB_FC_MANAGE_BUS_TID_AI
+{
+    U16                     Reserved;                   /* 00h */
+    U8                      Bus;                        /* 02h */
+    U8                      TargetId;                   /* 03h */
+} MPI_TB_FC_MANAGE_BUS_TID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_BUS_TID_AI,
+  MpiTbFcManageBusTidAi_t, MPI_POINTER pMpiTbFcManageBusTidAi_t;
+
+/* ActionInfo for port identifier */
+typedef struct _MPI_TB_FC_MANAGE_PID_AI
+{
+    U32                     PortIdentifier;             /* 00h */
+} MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI,
+  MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t;
+
+/* union of ActionInfo */
+typedef union _MPI_TB_FC_MANAGE_AI_UNION
+{
+    MPI_TB_FC_MANAGE_BUS_TID_AI     BusTid;
+    MPI_TB_FC_MANAGE_PID_AI         Port;
+} MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION,
+  MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t;
+
+typedef struct _MSG_TOOLBOX_FC_MANAGE_REQUEST
+{
+    U8                          Tool;                   /* 00h */
+    U8                          Reserved;               /* 01h */
+    U8                          ChainOffset;            /* 02h */
+    U8                          Function;               /* 03h */
+    U16                         Reserved1;              /* 04h */
+    U8                          Reserved2;              /* 06h */
+    U8                          MsgFlags;               /* 07h */
+    U32                         MsgContext;             /* 08h */
+    U8                          Action;                 /* 0Ch */
+    U8                          Reserved3;              /* 0Dh */
+    U16                         Reserved4;              /* 0Eh */
+    MPI_TB_FC_MANAGE_AI_UNION   ActionInfo;             /* 10h */
+} MSG_TOOLBOX_FC_MANAGE_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_FC_MANAGE_REQUEST,
+  ToolboxFcManageRequest_t, MPI_POINTER pToolboxFcManageRequest_t;
+
+/* defines for the Action field */
+#define MPI_TB_FC_MANAGE_ACTION_DISC_ALL            (0x00)
+#define MPI_TB_FC_MANAGE_ACTION_DISC_PID            (0x01)
+#define MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID        (0x02)
+
+
+/****************************************************************************/
+/* Diagnostic Buffer Post request                                           */
+/****************************************************************************/
+
+typedef struct _MSG_DIAG_BUFFER_POST_REQUEST
+{
+    U8                      TraceLevel;                 /* 00h */
+    U8                      BufferType;                 /* 01h */
+    U8                      ChainOffset;                /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved1;                  /* 04h */
+    U8                      Reserved2;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U32                     ExtendedType;               /* 0Ch */
+    U32                     BufferLength;               /* 10h */
+    U32                     ProductSpecific[4];         /* 14h */
+    U32                     Reserved3;                  /* 18h */
+    SGE_SIMPLE_UNION        SGL;                        /* 28h */
+} MSG_DIAG_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REQUEST,
+  DiagBufferPostRequest_t, MPI_POINTER pDiagBufferPostRequest_t;
+
+#define MPI_DIAG_BUF_TYPE_TRACE                     (0x00)
+#define MPI_DIAG_BUF_TYPE_SNAPSHOT                  (0x01)
+#define MPI_DIAG_BUF_TYPE_EXTENDED                  (0x02)
+
+#define MPI_DIAG_EXTENDED_QTAG                      (0x00000001)
+
+
+/* Diagnostic Buffer Post reply */
+typedef struct _MSG_DIAG_BUFFER_POST_REPLY
+{
+    U8                      Reserved1;                  /* 00h */
+    U8                      BufferType;                 /* 01h */
+    U8                      MsgLength;                  /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved2;                  /* 04h */
+    U8                      Reserved3;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U16                     Reserved4;                  /* 0Ch */
+    U16                     IOCStatus;                  /* 0Eh */
+    U32                     IOCLogInfo;                 /* 10h */
+    U32                     TransferLength;             /* 14h */
+} MSG_DIAG_BUFFER_POST_REPLY, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REPLY,
+  DiagBufferPostReply_t, MPI_POINTER pDiagBufferPostReply_t;
+
+
+/****************************************************************************/
+/* Diagnostic Release request                                               */
+/****************************************************************************/
+
+typedef struct _MSG_DIAG_RELEASE_REQUEST
+{
+    U8                      Reserved1;                  /* 00h */
+    U8                      BufferType;                 /* 01h */
+    U8                      ChainOffset;                /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved2;                  /* 04h */
+    U8                      Reserved3;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+} MSG_DIAG_RELEASE_REQUEST, MPI_POINTER PTR_MSG_DIAG_RELEASE_REQUEST,
+  DiagReleaseRequest_t, MPI_POINTER pDiagReleaseRequest_t;
+
+
+/* Diagnostic Release reply */
+typedef struct _MSG_DIAG_RELEASE_REPLY
+{
+    U8                      Reserved1;                  /* 00h */
+    U8                      BufferType;                 /* 01h */
+    U8                      MsgLength;                  /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved2;                  /* 04h */
+    U8                      Reserved3;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U16                     Reserved4;                  /* 0Ch */
+    U16                     IOCStatus;                  /* 0Eh */
+    U32                     IOCLogInfo;                 /* 10h */
+} MSG_DIAG_RELEASE_REPLY, MPI_POINTER PTR_MSG_DIAG_RELEASE_REPLY,
+  DiagReleaseReply_t, MPI_POINTER pDiagReleaseReply_t;
+
+
 #endif
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/lsi/mpi_type.h linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_type.h
--- linux-2.4.26/drivers/message/fusion/lsi/mpi_type.h	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/lsi/mpi_type.h	2004-07-30 16:29:27.000000000 +0000
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2002 LSI Logic Corporation.
+ *  Copyright (c) 2000-2003 LSI Logic Corporation.
  *
  *
- *           Name:  MPI_TYPE.H
+ *           Name:  mpi_type.h
  *          Title:  MPI Basic type definitions
  *  Creation Date:  June 6, 2000
  *
- *    MPI Version:  01.02.01
+ *    mpi_type.h Version:  01.05.xx
  *
  *  Version History
  *  ---------------
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptbase.c linux-2.4.27-rc4/drivers/message/fusion/mptbase.c
--- linux-2.4.26/drivers/message/fusion/mptbase.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptbase.c	2004-07-30 16:26:36.000000000 +0000
@@ -209,7 +209,6 @@ static int	GetFcPortPage0(MPT_ADAPTER *i
 static int	GetIoUnitPage2(MPT_ADAPTER *ioc);
 static int	mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
 static int	mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum);
-static int	mpt_findImVolumes(MPT_ADAPTER *ioc);
 static void 	mpt_read_ioc_pg_1(MPT_ADAPTER *ioc);
 static void 	mpt_read_ioc_pg_4(MPT_ADAPTER *ioc);
 static void	mpt_timer_expired(unsigned long data);
@@ -567,7 +566,8 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRA
 	} else if (func == MPI_FUNCTION_EVENT_ACK) {
 		dprintk((MYIOC_s_INFO_FMT "mpt_base_reply, EventAck reply received\n",
 				ioc->name));
-	} else if (func == MPI_FUNCTION_CONFIG) {
+	} else if (func == MPI_FUNCTION_CONFIG ||
+		   func == MPI_FUNCTION_TOOLBOX) {
 		CONFIGPARMS *pCfg;
 		unsigned long flags;
 
@@ -904,6 +904,8 @@ mpt_put_msg_frame(int handle, int iocid,
 
 		mf_dma_addr = iocp->req_frames_low_dma + req_offset;
 		CHIPREG_WRITE32(&iocp->chip->RequestFifo, mf_dma_addr);
+	} else {
+		printk (KERN_ERR "mpt_put_msg_frame: Invalid iocid=%d\n", iocid);
 	}
 }
 
@@ -1053,7 +1055,7 @@ mpt_send_handshake_request(int handle, i
 				 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
 
 		/* Wait for IOC doorbell int */
-		if ((ii = WaitForDoorbellInt(iocp, 2, sleepFlag)) < 0) {
+		if ((ii = WaitForDoorbellInt(iocp, 5, sleepFlag)) < 0) {
 			return ii;
 		}
 
@@ -1066,7 +1068,7 @@ mpt_send_handshake_request(int handle, i
 
 		CHIPREG_WRITE32(&iocp->chip->IntStatus, 0);
 
-		if ((r = WaitForDoorbellAck(iocp, 2, sleepFlag)) < 0) {
+		if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
 			return -2;
 		}
 
@@ -1080,7 +1082,7 @@ mpt_send_handshake_request(int handle, i
 				(req_as_bytes[(ii*4) + 2] << 16) |
 				(req_as_bytes[(ii*4) + 3] << 24));
 			CHIPREG_WRITE32(&iocp->chip->Doorbell, word);
-			if ((r = WaitForDoorbellAck(iocp, 2, sleepFlag)) < 0) {
+			if ((r = WaitForDoorbellAck(iocp, 5, sleepFlag)) < 0) {
 				r = -3;
 				break;
 			}
@@ -1279,6 +1281,8 @@ mpt_adapter_install(struct pci_dev *pdev
 	int		 ii;
 	int		 r = -ENODEV;
 	u64		 mask = 0xffffffffffffffffULL;
+	u8		 revision;
+	u8		 pcixcmd;
 
 	if (pci_enable_device(pdev))
 		return r;
@@ -1418,46 +1422,45 @@ mpt_adapter_install(struct pci_dev *pdev
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC929X) {
 		ioc->chip_type = FC929X;
-		ioc->prod_name = "LSIFC929X";
-		{
+		pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+		if (revision < XL_929) {
+			ioc->prod_name = "LSIFC929X";
 			/* 929X Chip Fix. Set Split transactions level
-			 * for PCIX. Set MOST bits to zero.
-			 */
-			u8 pcixcmd;
+		 	* for PCIX. Set MOST bits to zero.
+		 	*/
 			pci_read_config_byte(pdev, 0x6a, &pcixcmd);
 			pcixcmd &= 0x8F;
 			pci_write_config_byte(pdev, 0x6a, pcixcmd);
+		} else {
+			ioc->prod_name = "LSIFC929XL";
+			/* 929XL Chip Fix. Set MMRBC to 0x08.
+		 	*/
+			pci_read_config_byte(pdev, 0x6a, &pcixcmd);
+			pcixcmd |= 0x08;
+			pci_write_config_byte(pdev, 0x6a, pcixcmd);
 		}
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC919X) {
 		ioc->chip_type = FC919X;
 		ioc->prod_name = "LSIFC919X";
-		{
-			/* 919X Chip Fix. Set Split transactions level
-			 * for PCIX. Set MOST bits to zero.
-			 */
-			u8 pcixcmd;
-			pci_read_config_byte(pdev, 0x6a, &pcixcmd);
-			pcixcmd &= 0x8F;
-			pci_write_config_byte(pdev, 0x6a, pcixcmd);
-		}
+		/* 919X Chip Fix. Set Split transactions level
+		 * for PCIX. Set MOST bits to zero.
+		 */
+		pci_read_config_byte(pdev, 0x6a, &pcixcmd);
+		pcixcmd &= 0x8F;
+		pci_write_config_byte(pdev, 0x6a, pcixcmd);
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
 		ioc->chip_type = C1030;
 		ioc->prod_name = "LSI53C1030";
-		{
-			u8 revision;
-
-			/* 1030 Chip Fix. Disable Split transactions
-			 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
-			 */
-			pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
-			if (revision < 0x08) {
-				u8 pcixcmd;
-				pci_read_config_byte(pdev, 0x6a, &pcixcmd);
-				pcixcmd &= 0x8F;
-				pci_write_config_byte(pdev, 0x6a, pcixcmd);
-			}
+		/* 1030 Chip Fix. Disable Split transactions
+		 * for PCIX. Set MOST bits to zero if Rev < C0( = 8).
+		 */
+		pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+		if (revision < C0_1030) {
+			pci_read_config_byte(pdev, 0x6a, &pcixcmd);
+			pcixcmd &= 0x8F;
+			pci_write_config_byte(pdev, 0x6a, pcixcmd);
 		}
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
@@ -1610,11 +1613,17 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 					ioc->alt_ioc->name, r);
 	}
 
+	for (ii=0; ii<5; ii++) {
 	/* Get IOC facts! Allow 1 retry */
-	if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0)
-		r = GetIocFacts(ioc, sleepFlag, reason);
+	if ((r = GetIocFacts(ioc, sleepFlag, reason)) != 0) {
+		dinitprintk((MYIOC_s_INFO_FMT "ii=%d IocFacts failed r=%x\n", ioc->name, ii, r));
+	} else
+		break;
+	}
+	
 
 	if (r) {
+		dinitprintk((MYIOC_s_INFO_FMT "Retry IocFacts failed r=%x\n", ioc->name, r));
 		ret = -2;
 	} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
 		MptDisplayIocCapabilities(ioc);
@@ -1622,11 +1631,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 
 	if (alt_ioc_ready) {
 		if ((r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) {
+			dinitprintk((MYIOC_s_INFO_FMT "Initial Alt IocFacts failed r=%x\n", ioc->name, r));
 			/* Retry - alt IOC was initialized once
 			 */
 			r = GetIocFacts(ioc->alt_ioc, sleepFlag, reason);
 		}
 		if (r) {
+			dinitprintk((MYIOC_s_INFO_FMT "Retry Alt IocFacts failed r=%x\n", ioc->name, r));
 			alt_ioc_ready = 0;
 			reset_alt_ioc_active = 0;
 		} else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) {
@@ -1862,15 +1873,8 @@ mpt_adapter_disable(MPT_ADAPTER *this, i
 		u32 state;
 		int ret;
 
-		/* Disable the FW */
-		state = mpt_GetIocState(this, 1);
-		if (state == MPI_IOC_STATE_OPERATIONAL) {
-			SendIocReset(this, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, NO_SLEEP);
-		}
-
 		if (this->cached_fw != NULL) {
 			ddlprintk((KERN_INFO MYNAM ": Pushing FW onto adapter\n"));
-
 			if ((ret = mpt_downloadboot(this, NO_SLEEP)) < 0) {
 				printk(KERN_WARNING MYNAM
 					": firmware downloadboot failure (%d)!\n", ret);
@@ -1921,25 +1925,11 @@ mpt_adapter_disable(MPT_ADAPTER *this, i
 		}
 
 		if (freeup && this->cached_fw != NULL) {
-			int ii = 0;
-
-			while ((ii < this->num_fw_frags) && (this->cached_fw[ii]!= NULL)) {
-				sz = this->cached_fw[ii]->size;
-				pci_free_consistent(this->pcidev, sz,
-					this->cached_fw[ii]->fw, this->cached_fw[ii]->fw_dma);
-				this->cached_fw[ii]->fw = NULL;
-				this->alloc_total -= sz;
-
-				kfree(this->cached_fw[ii]);
-				this->cached_fw[ii] = NULL;
-				this->alloc_total -= sizeof(fw_image_t);
-
-				ii++;
-			}
 
-			kfree(this->cached_fw);
+			sz = this->facts.FWImageSize;
+			pci_free_consistent(this->pcidev, sz,
+				this->cached_fw, this->cached_fw_dma);
 			this->cached_fw = NULL;
-			sz = this->num_fw_frags * sizeof(void *);
 			this->alloc_total -= sz;
 		}
 
@@ -1981,11 +1971,6 @@ mpt_adapter_dispose(MPT_ADAPTER *this)
 
 		sz_first = this->alloc_total;
 
-		if (this->alt_ioc != NULL) {
-			this->alt_ioc->alt_ioc = NULL;
-			this->alt_ioc = NULL;
-		}
-
 		mpt_adapter_disable(this, 1);
 
 		if (this->pci_irq != -1) {
@@ -2101,13 +2086,14 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
 		if ((int)ioc->chip_type <= (int)FC929)
 			return 0;
 		else {
+			return 0;
 			/* Workaround from broken 1030 FW.
 			 * Force a diagnostic reset if fails.
 			 */
-			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
+/*			if ((r = SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag)) == 0)
 				return 0;
 			else
-				statefault = 4;
+				statefault = 4; */
 		}
 	}
 
@@ -2126,7 +2112,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force
 	 *	Hmmm...  Did it get left operational?
 	 */
 	if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_OPERATIONAL) {
-		dprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
+		dinitprintk((MYIOC_s_WARN_FMT "IOC operational unexpected\n",
 				ioc->name));
 
 		/* Check WhoInit.
@@ -2270,13 +2256,13 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 	get_facts.Function = MPI_FUNCTION_IOC_FACTS;
 	/* Assert: All other get_facts fields are zero! */
 
-	dprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
+	dinitprintk((MYIOC_s_INFO_FMT "Sending get IocFacts request\n", ioc->name));
 
 	/* No non-zero fields in the get_facts request are greater than
 	 * 1 byte in size, so we can just fire it off as is.
 	 */
 	r = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_facts,
-			reply_sz, (u16*)facts, 3 /*seconds*/, sleepFlag);
+			reply_sz, (u16*)facts, 5 /*seconds*/, sleepFlag);
 	if (r != 0)
 		return r;
 
@@ -2370,8 +2356,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepF
 				return r;
 		}
 	} else {
-		printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply!\n",
-				ioc->name);
+		printk(MYIOC_s_ERR_FMT "Invalid IOC facts reply, msgLength=%d offsetof=%d!\n",
+				ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t, RequestFrameSize)/sizeof(u32)));
 		return -66;
 	}
 
@@ -2425,7 +2411,7 @@ GetPortFacts(MPT_ADAPTER *ioc, int portn
 	 * 1 byte in size, so we can just fire it off as is.
 	 */
 	ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&get_pfacts,
-				reply_sz, (u16*)pfacts, 3 /*seconds*/, sleepFlag);
+				reply_sz, (u16*)pfacts, 5 /*seconds*/, sleepFlag);
 	if (ii != 0)
 		return ii;
 
@@ -2511,7 +2497,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
 		ioc_init.SenseBufferHighAddr = cpu_to_le32(0);
 	}
 
-	dprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
+	dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n",
 			ioc->name, &ioc_init));
 
 	r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init,
@@ -2523,6 +2509,9 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepF
 	 * since we don't even look at it's contents.
 	 */
 
+	dhsprintk((MYIOC_s_INFO_FMT "Sending PortEnable (req @ %p)\n",
+			ioc->name, &ioc_init));
+
 	if ((r = SendPortEnable(ioc, 0, sleepFlag)) != 0)
 		return r;
 
@@ -2589,7 +2578,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int por
 /*	port_enable.MsgFlags = 0;		*/
 /*	port_enable.MsgContext = 0;		*/
 
-	dprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
+	dinitprintk((MYIOC_s_INFO_FMT "Sending Port(%d)Enable (req @ %p)\n",
 			ioc->name, portnum, &port_enable));
 
 	/* RAID FW may take a long time to enable
@@ -2617,86 +2606,14 @@ SendPortEnable(MPT_ADAPTER *ioc, int por
  * Outputs: frags - number of fragments needed
  * Return NULL if failed.
  */
-void *
-mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz)
+void
+mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
 {
-	fw_image_t	**cached_fw;
-	u8		*mem;
-	dma_addr_t	fw_dma;
-	int		alloc_total = 0;
-	int		bytes_left, bytes, num_frags;
-	int		sz, ii;
-
 	/* cached_fw
 	 */
-	sz = ioc->num_fw_frags * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL)
-		return NULL;
-
-	memset(mem, 0, sz);
-	cached_fw = (fw_image_t **)mem;
-	alloc_total += sz;
-
-	/* malloc fragment memory
-	 * fw_image_t struct and dma for fw data
-	 */
-	bytes_left = size;
-	ii = 0;
-	num_frags = 0;
-	bytes = bytes_left;
-	while((bytes_left) && (num_frags < ioc->num_fw_frags)) {
-		if (cached_fw[ii] == NULL) {
-			mem = kmalloc(sizeof(fw_image_t), GFP_ATOMIC);
-			if (mem == NULL)
-				break;
-
-			memset(mem, 0, sizeof(fw_image_t));
-			cached_fw[ii] = (fw_image_t *)mem;
-			alloc_total += sizeof(fw_image_t);
-		}
-
-		mem = pci_alloc_consistent(ioc->pcidev, bytes, &fw_dma);
-		if (mem == NULL) {
-			if (bytes > 0x10000)
-				bytes = 0x10000;
-			else if (bytes > 0x8000)
-				bytes = 0x8000;
-			else if (bytes > 0x4000)
-				bytes = 0x4000;
-			else if (bytes > 0x2000)
-				bytes = 0x2000;
-			else if (bytes > 0x1000)
-				bytes = 0x1000;
-			else
-				break;
-
-			continue;
-		}
-
-		cached_fw[ii]->fw = mem;
-		cached_fw[ii]->fw_dma = fw_dma;
-		cached_fw[ii]->size = bytes;
-		memset(mem, 0, bytes);
-		alloc_total += bytes;
-
-		bytes_left -= bytes;
-
-		num_frags++;
-		ii++;
-	}
-
-	if (bytes_left ) {
-		/* Major Failure.
-		 */
-		mpt_free_fw_memory(ioc, cached_fw);
-		return NULL;
-	}
-
-	*frags = num_frags;
-	*alloc_sz = alloc_total;
 
-	return (void *) cached_fw;
+	if ( (ioc->cached_fw = pci_alloc_consistent(ioc->pcidev, size, &ioc->cached_fw_dma) ) )
+		ioc->alloc_total += size;
 }
 
 /*
@@ -2704,45 +2621,14 @@ mpt_alloc_fw_memory(MPT_ADAPTER *ioc, in
  * Else, delete a secondary image in same format.
  */
 void
-mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img)
+mpt_free_fw_memory(MPT_ADAPTER *ioc)
 {
-	fw_image_t **cached_fw;
-	int ii;
 	int sz;
-	int alloc_freed = 0;
-
-	if (alt_img != NULL)
-		cached_fw = alt_img;
-	else
-		cached_fw = ioc->cached_fw;
-
-	if (cached_fw == NULL)
-		return;
 
-	ii = 0;
-	while ((ii < ioc->num_fw_frags) && (cached_fw[ii]!= NULL)) {
-		sz = cached_fw[ii]->size;
-		if (sz > 0) {
-			pci_free_consistent(ioc->pcidev, sz,
-						cached_fw[ii]->fw, cached_fw[ii]->fw_dma);
-		}
-		cached_fw[ii]->fw = NULL;
-		alloc_freed += sz;
-
-		kfree(cached_fw[ii]);
-		cached_fw[ii] = NULL;
-		alloc_freed += sizeof(fw_image_t);
-
-		ii++;
-	}
-
-	kfree(cached_fw);
-	cached_fw = NULL;
-	sz = ioc->num_fw_frags * sizeof(void *);
-	alloc_freed += sz;
-
-	if (alt_img == NULL)
-		ioc->alloc_total -= alloc_freed;
+	sz = ioc->facts.FWImageSize;
+	pci_free_consistent(ioc->pcidev, sz,
+			ioc->cached_fw, ioc->cached_fw_dma);
+	ioc->cached_fw = NULL;
 
 	return;
 }
@@ -2771,9 +2657,9 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 	FWUploadReply_t		*preply;
 	FWUploadTCSGE_t		*ptcsge;
 	int			 sgeoffset;
+	u32			 flagsLength;
 	int			 ii, sz, reply_sz;
 	int			 cmdStatus, freeMem = 0;
-	int			 num_frags, alloc_sz;
 
 	/* If the image size is 0 or if the pointer is
 	 * not NULL (error), we are done.
@@ -2781,24 +2667,21 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 	if (((sz = ioc->facts.FWImageSize) == 0) || ioc->cached_fw)
 		return 0;
 
-	ioc->num_fw_frags = ioc->req_sz - sizeof(FWUpload_t) + sizeof(dma_addr_t) + sizeof(u32) -1;
-	ioc->num_fw_frags /= sizeof(dma_addr_t) + sizeof(u32);
+	if ( sz & 0x01 )
+		sz += 1;
+	if ( sz & 0x02 )
+		sz += 2;
 
-	ioc->cached_fw = (fw_image_t **) mpt_alloc_fw_memory(ioc,
-			ioc->facts.FWImageSize, &num_frags, &alloc_sz);
+	mpt_alloc_fw_memory(ioc, sz);
 
 	if (ioc->cached_fw == NULL) {
 		/* Major Failure.
 		 */
-		mpt_free_fw_memory(ioc, NULL);
-		ioc->cached_fw = NULL;
-		
 		return -ENOMEM;
 	}
-	ioc->alloc_total += alloc_sz;
 
-	ddlprintk((KERN_INFO MYNAM ": FW Image  @ %p, sz=%d bytes\n",
-		 (void *)(ulong)ioc->cached_fw, ioc->facts.FWImageSize));
+	dinitprintk((KERN_WARNING MYNAM ": FW Image  @ %p[%p], sz=%d[%x] bytes\n",
+		 ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz));
 
 	prequest = (FWUpload_t *)&request;
 	preply = (FWUploadReply_t *)&reply;
@@ -2811,39 +2694,27 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 
 	prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM;
 	prequest->Function = MPI_FUNCTION_FW_UPLOAD;
-	prequest->MsgContext = 0;		/* anything */
 
 	ptcsge = (FWUploadTCSGE_t *) &prequest->SGL;
-	ptcsge->Reserved = 0;
-	ptcsge->ContextSize = 0;
 	ptcsge->DetailsLength = 12;
 	ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT;
-	ptcsge->Reserved1 = 0;
-	ptcsge->ImageOffset = 0;
 	ptcsge->ImageSize = cpu_to_le32(sz);
 
 	sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t);
 
-	for (ii = 0; ii < (num_frags-1); ii++) {
-		mpt_add_sge(&request[sgeoffset], MPT_SGE_FLAGS_SIMPLE_ELEMENT |	
-			MPT_SGE_FLAGS_ADDRESSING | MPT_TRANSFER_IOC_TO_HOST |
-			(u32) ioc->cached_fw[ii]->size, ioc->cached_fw[ii]->fw_dma);
-
-		sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-	}
-
-	mpt_add_sge(&request[sgeoffset],
-			MPT_SGE_FLAGS_SSIMPLE_READ |(u32) ioc->cached_fw[ii]->size,
-			ioc->cached_fw[ii]->fw_dma);
+	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz;
+	mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma);
 
 	sgeoffset += sizeof(u32) + sizeof(dma_addr_t);
-
-	dprintk((MYIOC_s_INFO_FMT "Sending FW Upload (req @ %p) size %d \n",
-			ioc->name, prequest, sgeoffset));
+	dinitprintk((KERN_WARNING MYNAM "Sending FW Upload (req @ %p) sgeoffset=%d \n",
+			prequest, sgeoffset));
+	DBG_DUMP_FW_REQUEST_FRAME(prequest)
 
 	ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest,
 				reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag);
 
+	dinitprintk((KERN_WARNING MYNAM "FW Upload completed rc=%x \n", ii));
+
 	cmdStatus = -EFAULT;
 	if (ii == 0) {
 		/* Handshake transfer was complete and successful.
@@ -2857,7 +2728,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 				cmdStatus = 0;
 		}
 	}
-	ddlprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
+	dinitprintk((MYIOC_s_INFO_FMT ": do_upload status %d \n",
 			ioc->name, cmdStatus));
 
 	/* Check to see if we have a copy of this image in
@@ -2877,8 +2748,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 
 		ddlprintk((MYIOC_s_INFO_FMT ": do_upload freeing %s image \n",
 			ioc->name, cmdStatus ? "incomplete" : "duplicate"));
-		mpt_free_fw_memory(ioc, NULL);
-		ioc->cached_fw = NULL;
+		mpt_free_fw_memory(ioc);
 	}
 
 	return cmdStatus;
@@ -2901,241 +2771,141 @@ mpt_do_upload(MPT_ADAPTER *ioc, int slee
 static int
 mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
 {
-	MpiFwHeader_t		*FwHdr;
-	MpiExtImageHeader_t 	*ExtHdr;
-	fw_image_t		**pCached;
-	int			 fw_sz;
+	MpiFwHeader_t		*pFwHeader;
+	MpiExtImageHeader_t	*pExtImage;
+	u32			 fwSize;
 	u32			 diag0val;
 #ifdef MPT_DEBUG
 	u32			 diag1val = 0;
 #endif
 	int			 count = 0;
-	u32			*ptru32;
+	u32			*ptrFw;
 	u32			 diagRwData;
 	u32			 nextImage;
 	u32			 ext_offset;
 	u32			 load_addr;
-	int			 max_idx, fw_idx, ext_idx;
-	int			 left_u32s;
-
-	ddlprintk((MYIOC_s_INFO_FMT "DbGb0: downloadboot entered.\n",
-				ioc->name));
-#ifdef MPT_DEBUG
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-	ddlprintk((MYIOC_s_INFO_FMT "DbGb1: diag0=%08x, diag1=%08x\n",
-				ioc->name, diag0val, diag1val));
-#endif
+	u32 			 ioc_state;
+	int			 fw_idx;
+	int			 r;
 
-	ddlprintk((MYIOC_s_INFO_FMT "fw size 0x%x, ioc FW Ptr %p\n",
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n",
 				ioc->name, ioc->facts.FWImageSize, ioc->cached_fw));
-	if (ioc->alt_ioc)
-		ddlprintk((MYIOC_s_INFO_FMT "alt ioc FW Ptr %p\n",
-				ioc->name, ioc->alt_ioc->cached_fw));
 
 	/* Get dma_addr and data transfer size.
 	 */
-	if ((fw_sz = ioc->facts.FWImageSize) == 0)
+	if ( ioc->facts.FWImageSize == 0 )
 		return -1;
 
 	/* Get the DMA from ioc or ioc->alt_ioc */
-	if (ioc->cached_fw != NULL)
-		pCached = (fw_image_t **)ioc->cached_fw;
-	else if (ioc->alt_ioc && (ioc->alt_ioc->cached_fw != NULL))
-		pCached = (fw_image_t **)ioc->alt_ioc->cached_fw;
-
-	ddlprintk((MYIOC_s_INFO_FMT "DbGb2: FW Image @ %p\n",
-			ioc->name, pCached));
-	if (!pCached)
+	if (ioc->cached_fw == NULL)
 		return -2;
 
-	/* Write magic sequence to WriteSequence register
-	 * until enter diagnostic mode
-	 */
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	while ((diag0val & MPI_DIAG_DRWE) == 0) {
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+	diag0val |= (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM);
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 
-		/* wait 100 msec */
+	/* wait 100 msec */
+	if (sleepFlag == CAN_SLEEP) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(100 * HZ / 1000);
+	} else {
+		mdelay (100);
+	}
+
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
+
+	for (count = 0; count < 30; count ++) {
+		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+		if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
+			ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
+				ioc->name, count));
+			break;
+		}
+		/* wait 1 sec */
 		if (sleepFlag == CAN_SLEEP) {
 			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(100 * HZ / 1000);
+			schedule_timeout(HZ);
 		} else {
-			mdelay (100);
-		}
-
-		count++;
-		if (count > 20) {
-			printk(MYIOC_s_ERR_FMT "Enable Diagnostic mode FAILED! (%02xh)\n",
-					ioc->name, diag0val);
-			return -EFAULT;
-
+			mdelay (1000);
 		}
-
-		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-#ifdef MPT_DEBUG
-		if (ioc->alt_ioc)
-			diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
-		ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
-				ioc->name, diag0val, diag1val));
-#endif
-		ddlprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
-				ioc->name, diag0val));
 	}
 
-	/* Set the DiagRwEn and Disable ARM bits */
-	diag0val |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM);
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+	if ( count == 30 ) {
+		ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n",
+		ioc->name, diag0val));
+		return -3;
+	}
 
-#ifdef MPT_DEBUG
-	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
+	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
 
-	ddlprintk((MYIOC_s_INFO_FMT "DbGb3: diag0=%08x, diag1=%08x\n",
-			ioc->name, diag0val, diag1val));
-#endif
+	/* Set the DiagRwEn and Disable ARM bits */
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (diag0val | MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
 
-	/* max_idx = 1 + maximum valid buffer index
-	 */
-	max_idx = 0;
-	while (pCached[max_idx])
-		max_idx++;
-
-	fw_idx = 0;
-	FwHdr = (MpiFwHeader_t *) pCached[fw_idx]->fw;
-	ptru32 = (u32 *) FwHdr;
-	count = (FwHdr->ImageSize + 3)/4;
-	nextImage = FwHdr->NextImageHeaderOffset;
+	pFwHeader = (MpiFwHeader_t *) ioc->cached_fw;
+	fwSize = (pFwHeader->ImageSize + 3)/4;
+	ptrFw = (u32 *) pFwHeader;
 
 	/* Write the LoadStartAddress to the DiagRw Address Register
 	 * using Programmed IO
 	 */
-	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->LoadStartAddress);
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
 	ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
-		ioc->name, FwHdr->LoadStartAddress));
+		ioc->name, pFwHeader->LoadStartAddress));
 
-	ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x u32's @ %p\n",
-				ioc->name, count, ptru32));
-	left_u32s = pCached[fw_idx]->size/4;
-	while (count--) {
-		if (left_u32s == 0) {
-			fw_idx++;
-			if (fw_idx >= max_idx) {
-				/* FIXME
-				ERROR CASE
-				*/
-				;
-			}
-			ptru32 = (u32 *) pCached[fw_idx]->fw;
-			left_u32s = pCached[fw_idx]->size / 4;
-		}
-		left_u32s--;
-		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
-		ptru32++;
+	ddlprintk((MYIOC_s_INFO_FMT "Write FW Image: 0x%x bytes @ %p\n",
+				ioc->name, fwSize*4, ptrFw));
+	while (fwSize--) {
+		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
 	}
 
-	/* left_u32s, fw_idx and ptru32 are all valid
-	 */
+	nextImage = pFwHeader->NextImageHeaderOffset;
 	while (nextImage) {
-		ext_idx = 0;
-		ext_offset = nextImage;
-		while (ext_offset > pCached[ext_idx]->size) {
-			ext_idx++;
-			if (ext_idx >= max_idx) {
-				/* FIXME
-				ERROR CASE
-				*/
-				;
-			}
-			ext_offset -= pCached[ext_idx]->size;
-		}
-		ptru32 = (u32 *) ((char *)pCached[ext_idx]->fw + ext_offset);
-		left_u32s = pCached[ext_idx]->size - ext_offset;
-
-		if ((left_u32s * 4) >= sizeof(MpiExtImageHeader_t)) {
-			ExtHdr = (MpiExtImageHeader_t *) ptru32;
-			count = (ExtHdr->ImageSize + 3 )/4;
-			nextImage = ExtHdr->NextImageHeaderOffset;
-			load_addr = ExtHdr->LoadStartAddress;
-		} else {
-			u32 * ptmp = (u32 *)pCached[ext_idx+1]->fw;
-
-			switch (left_u32s) {
-			case 5:
-				count = *(ptru32 + 2);
-				nextImage = *(ptru32 + 3);
-				load_addr = *(ptru32 + 4);
-				break;
-			case 4:
-				count = *(ptru32 + 2);
-				nextImage = *(ptru32 + 3);
-				load_addr = *ptmp;
-				break;
-			case 3:
-				count = *(ptru32 + 2);
-				nextImage = *ptmp;
-				load_addr = *(ptmp + 1);
-				break;
-			case 2:
-				count = *ptmp;
-				nextImage = *(ptmp + 1);
-				load_addr = *(ptmp + 2);
-				break;
-
-			case 1:
-				count = *(ptmp + 1);
-				nextImage = *(ptmp + 2);
-				load_addr = *(ptmp + 3);
-				break;
+		pExtImage = (MpiExtImageHeader_t *) ((char *)pFwHeader + nextImage);
 
-			default:
-				count = 0;
-				nextImage = 0;
-				load_addr = 0;
-				/* FIXME
-				ERROR CASE
-				*/
-				;
+		load_addr = pExtImage->LoadStartAddress;
 
-			}
-			count = (count +3)/4;
-		}
+		fwSize = (pExtImage->ImageSize + 3) >> 2;
+		ptrFw = (u32 *)pExtImage;
 
-		ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x u32's @ %p\n",
-						ioc->name, count, ptru32));
+		ddlprintk((MYIOC_s_INFO_FMT "Write Ext Image: 0x%x bytes @ %p load_addr=%x\n",
+						ioc->name, fwSize*4, ptrFw, load_addr));
 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, load_addr);
 
-		while (count--) {
-			if (left_u32s == 0) {
-				fw_idx++;
-				if (fw_idx >= max_idx) {
-					/* FIXME
-					ERROR CASE
-					*/
-					;
-				}
-				ptru32 = (u32 *) pCached[fw_idx]->fw;
-				left_u32s = pCached[fw_idx]->size / 4;
-			}
-			left_u32s--;
-			CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptru32);
-			ptru32++;
+		while (fwSize--) {
+			CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, *ptrFw++);
 		}
+		nextImage = pExtImage->NextImageHeaderOffset;
 	}
 
 	/* Write the IopResetVectorRegAddr */
-	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr! \n", ioc->name));
-	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, FwHdr->IopResetRegAddr);
+	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Addr=%x! \n", ioc->name, 	pFwHeader->IopResetRegAddr));
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->IopResetRegAddr);
 
 	/* Write the IopResetVectorValue */
-	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value! \n", ioc->name));
-	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, FwHdr->IopResetVectorValue);
+	ddlprintk((MYIOC_s_INFO_FMT "Write IopResetVector Value=%x! \n", ioc->name, pFwHeader->IopResetVectorValue));
+	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, pFwHeader->IopResetVectorValue);
+
+	/* clear the PREVENT_IOC_BOOT bit */
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT\n",
+		ioc->name, diag0val));
+	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT);
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
+		ioc->name, diag0val));
+	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 
 	/* Clear the internal flash bad bit - autoincrementing register,
 	 * so must do two writes.
@@ -3146,15 +2916,63 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int s
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
 
-	/* clear the RW enable and DISARM bits */
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_FLASH_BAD_SIG);
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off DISABLE_ARM, RW_ENABLE, RESET_HISTORY\n",
+		ioc->name, diag0val));
+	diag0val &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | MPI_DIAG_RESET_HISTORY);
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
+		ioc->name, diag0val));
 	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
 
+	/* wait 100 msec */
+	if (sleepFlag == CAN_SLEEP) {
+		ddlprintk((MYIOC_s_INFO_FMT "CAN_SLEEP 100 msec before reset the sequencer\n", ioc->name));
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(100 * HZ / 1000);
+	} else {
+		ddlprintk((MYIOC_s_INFO_FMT "mdelay 100 msec before reset the sequencer\n", ioc->name));
+		mdelay (100);
+	}
+
+	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if ( diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_DISABLE_ARM) ) {
+		ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed, diag0val=%x FLASH_BAD_SIG | DISABLE_ARM on\n ",
+			ioc->name, diag0val));
+	}
 	/* Write 0xFF to reset the sequencer */
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 
-	return 0;
+	for (count=0; count<HZ*20; count++) {
+		if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) {
+			ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n",
+					ioc->name, count, ioc_state));
+/*			if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
+				if ((r = GetIocFacts(ioc, sleepFlag, MPT_HOSTEVENT_IOC_BRINGUP)) != 0) {
+					ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed\n",
+						ioc->name));
+						return -EFAULT;
+				}
+			} */
+			/* wait 2 sec */
+/*			if (sleepFlag == CAN_SLEEP) {
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(5000 * HZ / 1000);
+			} else {
+				mdelay (5000);
+			} */
+
+			return 0;
+		}
+		if (sleepFlag == CAN_SLEEP) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(1);
+		} else {
+			mdelay (10);
+		}
+	}
+	ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! IocState=%x\n",
+		ioc->name, ioc_state));
+	return -EFAULT;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -3190,7 +3008,7 @@ KickStart(MPT_ADAPTER *ioc, int force, i
 	u32 ioc_state;
 	int cnt = 0;
 
-	dprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
+	dinitprintk((KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name));
 	if ((int)ioc->chip_type > (int)FC929) {
 		/* Always issue a Msg Unit Reset first. This will clear some
 		 * SCSI bus hang conditions.
@@ -3437,6 +3255,7 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ign
 		/* Write magic sequence to WriteSequence register
 		 * Loop until in diagnostic mode
 		 */
+		CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
 		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
@@ -3516,10 +3335,10 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_
 	u32 state;
 	int cntdn, count;
 
-	dprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
+	drsprintk((KERN_WARNING MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
 			ioc->name, reset_type));
 	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
-	if ((r = WaitForDoorbellAck(ioc, 4, sleepFlag)) < 0)
+	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
 		return r;
 
 	/* FW ACK'd request, wait for READY state
@@ -3740,8 +3559,8 @@ out_fail:
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
- *	mpt_handshake_req_reply_wait - Send MPT request to and receive reply from
- *	IOC via doorbell handshake method.
+ *	mpt_handshake_req_reply_wait - Send MPT request to and receive reply 
+ *	from IOC via doorbell handshake method.
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@reqBytes: Size of the request in bytes
  *	@req: Pointer to MPT request frame
@@ -3801,7 +3620,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER
 	 * our handshake request.
 	 */
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-	if (!failcnt && (t = WaitForDoorbellAck(ioc, 4, sleepFlag)) < 0)
+	if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
 		failcnt++;
 
 	if (!failcnt) {
@@ -3819,7 +3638,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER
 				    (req_as_bytes[(ii*4) + 3] << 24));
 
 			CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
-			if ((t = WaitForDoorbellAck(ioc, 4, sleepFlag)) < 0)
+			if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
 				failcnt++;
 		}
 
@@ -3835,6 +3654,9 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER
 		if (!failcnt && (t = WaitForDoorbellReply(ioc, maxwait, sleepFlag)) < 0)
 			failcnt++;
 
+		dhsprintk((MYIOC_s_INFO_FMT "HandShake reply count=%d%s\n",
+				ioc->name, t, failcnt ? " - MISSING DOORBELL REPLY!" : ""));
+
 		/*
 		 * Copy out the cached reply...
 		 */
@@ -3865,7 +3687,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
 {
 	int cntdn;
 	int count = 0;
-	u32 intstat;
+	u32 intstat=0;
 
 	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
 
@@ -3889,13 +3711,13 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int
 	}
 
 	if (cntdn) {
-		dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (cnt=%d)\n",
+		dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell ACK (count=%d)\n",
 				ioc->name, count));
 		return count;
 	}
 
-	printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout(%d)!\n",
-			ioc->name, (count+5)/HZ);
+	printk(MYIOC_s_ERR_FMT "Doorbell ACK timeout (count=%d), IntStatus=%x!\n",
+			ioc->name, count, intstat);
 	return -1;
 }
 
@@ -3916,7 +3738,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
 {
 	int cntdn;
 	int count = 0;
-	u32 intstat;
+	u32 intstat=0;
 
 	cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong;
 	if (sleepFlag == CAN_SLEEP) {
@@ -3939,13 +3761,13 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int
 	}
 
 	if (cntdn) {
-		dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d)\n",
-				ioc->name, count));
+		dprintk((MYIOC_s_INFO_FMT "WaitForDoorbell INT (cnt=%d) howlong=%d\n",
+				ioc->name, count, howlong));
 		return count;
 	}
 
-	printk(MYIOC_s_ERR_FMT "Doorbell INT timeout(%d)!\n",
-			ioc->name, (count+5)/HZ);
+	printk(MYIOC_s_ERR_FMT "Doorbell INT timeout (count=%d), IntStatus=%x!\n",
+			ioc->name, count, intstat);
 	return -1;
 }
 
@@ -3983,7 +3805,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
 	} else {
 		hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
 		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-		if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0)
+		if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 			failcnt++;
 		else {
 			hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
@@ -3991,8 +3813,8 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
 		}
 	}
 
-	dhsprintk((MYIOC_s_INFO_FMT "First handshake reply word=%08x%s\n",
-			ioc->name, le32_to_cpu(*(u32 *)hs_reply),
+	dhsprintk((MYIOC_s_INFO_FMT "WaitCnt=%d First handshake reply word=%08x%s\n",
+			ioc->name, t, le32_to_cpu(*(u32 *)hs_reply), 
 			failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));
 
 	/*
@@ -4000,7 +3822,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
 	 * reply 16 bits at a time.
 	 */
 	for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
-		if ((t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0)
+		if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 			failcnt++;
 		hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
 		/* don't overflow our IOC hs_reply[] buffer! */
@@ -4009,7 +3831,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
 		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 	}
 
-	if (!failcnt && (t = WaitForDoorbellInt(ioc, 2, sleepFlag)) < 0)
+	if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 		failcnt++;
 	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
 
@@ -4030,8 +3852,8 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, i
 	dmfprintk((MYIOC_s_INFO_FMT "Got Handshake reply:\n", ioc->name));
 	DBG_DUMP_REPLY_FRAME(mptReply)
 
-	dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY (sz=%d)\n",
-			ioc->name, u16cnt/2));
+	dhsprintk((MYIOC_s_INFO_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n",
+			ioc->name, t, u16cnt/2));
 	return u16cnt/2;
 }
 
@@ -4374,6 +4196,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc
 				pPP0->Capabilities = le32_to_cpu(pPP0->Capabilities);
 				pPP0->PhysicalInterface = le32_to_cpu(pPP0->PhysicalInterface);
 
+				if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 )
+					ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS;
 				ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0;
 				data = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK;
 				if (data) {
@@ -4517,10 +4341,11 @@ mpt_readScsiDevicePageHeaders(MPT_ADAPTE
  *	-EFAULT if read of config page header fails or data pointer not NULL
  *	-ENOMEM if pci_alloc failed
  */
-static int
+int
 mpt_findImVolumes(MPT_ADAPTER *ioc)
 {
 	IOCPage2_t		*pIoc2;
+	u8			*mem;
 	ConfigPageIoc2RaidVol_t	*pIocRv;
 	dma_addr_t		 ioc2_dma;
 	CONFIGPARMS		 cfg;
@@ -4531,9 +4356,6 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
 	u8			 nVols, nPhys;
 	u8			 vid, vbus, vioc;
 
-	if (ioc->spi_data.pIocPg3)
-		return -EFAULT;	
-
 	/* Read IOCP2 header then the page.
 	 */
 	header.PageVersion = 0;
@@ -4562,11 +4384,22 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
 	if (mpt_config(ioc, &cfg) != 0)
 		goto done_and_free;
 
+	if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) {
+		mem = kmalloc(iocpage2sz, GFP_ATOMIC);
+		if (mem) {
+			ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem;
+		} else {
+			goto done_and_free;
+		}
+	}
+	memcpy(mem, (u8 *)pIoc2, iocpage2sz);
+
 	/* Identify RAID Volume Id's */
 	nVols = pIoc2->NumActiveVolumes;
 	if ( nVols == 0) {
-		/* No RAID Volumes.  Done.
+		/* No RAID Volume.
 		 */
+		goto done_and_free;
 	} else {
 		/* At least 1 RAID Volume
 		 */
@@ -4591,7 +4424,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc)
 	/* Identify Hidden Physical Disk Id's */
 	nPhys = pIoc2->NumActivePhysDisks;
 	if (nPhys == 0) {
-		/* No physical disks. Done.
+		/* No physical disks.
 		 */
 	} else {
 		mpt_read_ioc_pg_3(ioc);
@@ -4883,7 +4716,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
 	MPT_FRAME_HDR	*mf;
 	unsigned long	 flags;
 	int		 ii, rc;
-	int		 flagsLength;
+	u32		 flagsLength;
 	int		 in_isr;
 
 	/* (Bugzilla:fibrebugs, #513)
@@ -4910,9 +4743,8 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
 	pReq->Reserved = 0;
 	pReq->ChainOffset = 0;
 	pReq->Function = MPI_FUNCTION_CONFIG;
-	pReq->Reserved1[0] = 0;
-	pReq->Reserved1[1] = 0;
-	pReq->Reserved1[2] = 0;
+	pReq->ExtPageLength = 0;
+	pReq->ExtPageType = 0;
 	pReq->MsgFlags = 0;
 	for (ii=0; ii < 8; ii++)
 		pReq->Reserved2[ii] = 0;
@@ -4971,6 +4803,114 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mpt_toolbox - Generic function to issue toolbox message
+ *	@ioc - Pointer to an adapter structure
+ *	@cfg - Pointer to a toolbox structure. Struct contains
+ *		action, page address, direction, physical address
+ *		and pointer to a configuration page header
+ *		Page header is updated.
+ *
+ *	Returns 0 for success
+ *	-EPERM if not allowed due to ISR context
+ *	-EAGAIN if no msg frames currently available
+ *	-EFAULT for non-successful reply or no reply (timeout)
+ */
+int
+mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
+{
+	ToolboxIstwiReadWriteRequest_t	*pReq;
+	u32		*toolbox_alloc;
+	dma_addr_t	 toolbox_dma;
+	MPT_FRAME_HDR	*mf;
+	unsigned long	 flags;
+	int		 ii, rc;
+	u32		 flagsLength;
+	int		 in_isr;
+
+	/* (Bugzilla:fibrebugs, #513)
+	 * Bug fix (part 1)!  20010905 -sralston
+	 *	Prevent calling wait_event() (below), if caller happens
+	 *	to be in ISR context, because that is fatal!
+	 */
+	in_isr = in_interrupt();
+	if (in_isr) {
+		dcprintk((MYIOC_s_WARN_FMT "toobox request not allowed in ISR context!\n",
+				ioc->name));
+		return -EPERM;
+	}
+
+	/* Get and Populate a free Frame
+	 */
+	if ((mf = mpt_get_msg_frame(mpt_base_index, ioc->id)) == NULL) {
+		dcprintk((MYIOC_s_WARN_FMT "mpt_toolbox: no msg frames!\n",
+				ioc->name));
+		return -EAGAIN;
+	}
+	pReq = (ToolboxIstwiReadWriteRequest_t	*)mf;
+	pReq->Tool = pCfg->action;
+	pReq->Reserved = 0;
+	pReq->ChainOffset = 0;
+	pReq->Function = MPI_FUNCTION_TOOLBOX;
+	pReq->Reserved1 = 0;
+	pReq->Reserved2 = 0;
+	pReq->MsgFlags = 0;
+	pReq->Flags = pCfg->dir;
+	pReq->BusNum = 0;
+	pReq->Reserved3 = 0;
+	pReq->NumAddressBytes = 0x01;
+	pReq->Reserved4 = 0;
+	pReq->DataLength = 0x04;
+	pReq->DeviceAddr = 0xB0;
+	pReq->Addr1 = 0;
+	pReq->Addr2 = 0;
+	pReq->Addr3 = 0;
+	pReq->Reserved5 = 0;
+
+	/* Add a SGE to the config request.
+	 */
+
+	flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | 4;
+
+	mpt_add_sge((char *)&pReq->SGL, flagsLength, pCfg->physAddr);
+
+	dcprintk((MYIOC_s_INFO_FMT "Sending Toolbox request, Tool=%x\n",
+		ioc->name, pReq->Tool));
+
+	/* Append pCfg pointer to end of mf
+	 */
+	*((void **) (((u8 *) mf) + (ioc->req_sz - sizeof(void *)))) =  (void *) pCfg;
+
+	/* Initalize the timer
+	 */
+	init_timer(&pCfg->timer);
+	pCfg->timer.data = (unsigned long) ioc;
+	pCfg->timer.function = mpt_timer_expired;
+	pCfg->wait_done = 0;
+
+	/* Set the timer; ensure 10 second minimum */
+	if (pCfg->timeout < 10)
+		pCfg->timer.expires = jiffies + HZ*10;
+	else
+		pCfg->timer.expires = jiffies + HZ*pCfg->timeout;
+
+	/* Add to end of Q, set timer and then issue this command */
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+	Q_ADD_TAIL(&ioc->configQ.head, &pCfg->linkage, Q_ITEM);
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+	add_timer(&pCfg->timer);
+	mpt_put_msg_frame(mpt_base_index, ioc->id, mf);
+	wait_event(mpt_waitq, pCfg->wait_done);
+
+	/* mf has been freed - do not access */
+
+	rc = pCfg->status;
+
+	return rc;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mpt_timer_expired - Call back for timer process.
  *	Used only internal config functionality.
@@ -5753,109 +5693,11 @@ mpt_fc_log_info(MPT_ADAPTER *ioc, u32 lo
 		"FCP Initiator", "FCP Target", "LAN", "MPI Message Layer",
 		"FC Link", "Context Manager", "Invalid Field Offset", "State Change Info"
 	};
-	char *desc = "unknown";
 	u8 subcl = (log_info >> 24) & 0x7;
 	u32 SubCl = log_info & 0x27000000;
 
-	switch(log_info) {
-/* FCP Initiator */
-	case MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME:
-		desc = "Received an out of order frame - unsupported";
-		break;
-	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME:
-		desc = "Bad start of frame primative";
-		break;
-	case MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME:
-		desc = "Bad end of frame primative";
-		break;
-	case MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN:
-		desc = "Receiver hardware detected overrun";
-		break;
-	case MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER:
-		desc = "Other errors caught by IOC which require retries";
-		break;
-	case MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD:
-		desc = "Main processor could not initialize sub-processor";
-		break;
-/* FC Target */
-	case MPI_IOCLOGINFO_FC_TARGET_NO_PDISC:
-		desc = "Not sent because we are waiting for a PDISC from the initiator";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN:
-		desc = "Not sent because we are not logged in to the remote node";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP:
-		desc = "Data Out, Auto Response, not sent due to a LIP";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP:
-		desc = "Data In, Auto Response, not sent due to a LIP";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA:
-		desc = "Data In, Auto Response, missing data frames";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP:
-		desc = "Data Out, No Response, not sent due to a LIP";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP:
-		desc = "Auto-response after a write not sent due to a LIP";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP:
-		desc = "Data In, No Response, not completed due to a LIP";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA:
-		desc = "Data In, No Response, missing data frames";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP:
-		desc = "Manual Response not sent due to a LIP";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3:
-		desc = "Not sent because remote node does not support Class 3";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID:
-		desc = "Not sent because login to remote node not validated";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND:
-		desc = "Cleared from the outbound queue after a logout";
-		break;
-	case MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN:
-		desc = "Cleared waiting for data after a logout";
-		break;
-/* LAN */
-	case MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING:
-		desc = "Transaction Context Sgl Missing";
-		break;
-	case MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE:
-		desc = "Transaction Context found before an EOB";
-		break;
-	case MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET:
-		desc = "Transaction Context value has reserved bits set";
-		break;
-	case MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG:
-		desc = "Invalid SGL Flags";
-		break;
-/* FC Link */
-	case MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT:
-		desc = "Loop initialization timed out";
-		break;
-	case MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED:
-		desc = "Another system controller already initialized the loop";
-		break;
-	case MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED:
-		desc = "Not synchronized to signal or still negotiating (possible cable problem)";
-		break;
-	case MPI_IOCLOGINFO_FC_LINK_CRC_ERROR:
-		desc = "CRC check detected error on received frame";
-		break;
-	}
-
 	printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): SubCl={%s}",
 			ioc->name, log_info, subcl_str[subcl]);
-	if (SubCl == MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET)
-		printk(", byte_offset=%d\n", log_info & MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET);
-	else if (SubCl == MPI_IOCLOGINFO_FC_STATE_CHANGE)
-		printk("\n");		/* StateChg in LogInfo & 0x00FFFFFF, above */
-	else
-		printk("\n" KERN_INFO " %s\n", desc);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5984,6 +5826,8 @@ EXPORT_SYMBOL(mpt_lan_index);
 EXPORT_SYMBOL(mpt_stm_index);
 EXPORT_SYMBOL(mpt_HardResetHandler);
 EXPORT_SYMBOL(mpt_config);
+EXPORT_SYMBOL(mpt_toolbox);
+EXPORT_SYMBOL(mpt_findImVolumes);
 EXPORT_SYMBOL(mpt_read_ioc_pg_3);
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
@@ -6055,8 +5899,9 @@ fusion_exit(void)
 {
 	MPT_ADAPTER *this;
 	struct pci_dev *pdev;
+	int	ii;
 
-	dprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
+	dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
 
 	/* Whups?  20010120 -sralston
 	 *  Moved this *above* removal of all MptAdapters!
@@ -6064,23 +5909,40 @@ fusion_exit(void)
 #ifdef CONFIG_PROC_FS
 	(void) procmpt_destroy();
 #endif
+	/* Find onboard HBAs */
+	for (ii=0; ii < MPT_MAX_ADAPTERS; ii++) {
+		if ( (this = mpt_adapters[ii]) ) {
+			if (this->cached_fw != NULL) {
+				if (this->alt_ioc) {
+					pdev = (struct pci_dev *)this->alt_ioc->pcidev;
+					mpt_sync_irq(pdev->irq);
+
+					dexitprintk((MYIOC_s_INFO_FMT "Calling mpt_adapter_dispose for alt_ioc %d\n", this->name, this->alt_ioc->id));
+
+					Q_DEL_ITEM(this->alt_ioc);
+					mpt_adapter_dispose(this->alt_ioc);
+				}
+				pdev = (struct pci_dev *)this->pcidev;
+				mpt_sync_irq(pdev->irq);
+
+				dexitprintk((MYIOC_s_INFO_FMT "Calling mpt_adapter_dispose for on-board ioc %d\n", this->name, ii));
+
+				Q_DEL_ITEM(this);
+				mpt_adapter_dispose(this);
+			}
+		}
+	}
+
 
 	while (! Q_IS_EMPTY(&MptAdapters)) {
 		this = MptAdapters.head;
 
-		/* Disable interrupts! */
-		CHIPREG_WRITE32(&this->chip->IntMask, 0xFFFFFFFF);
-
 		this->active = 0;
 
 		pdev = (struct pci_dev *)this->pcidev;
 		mpt_sync_irq(pdev->irq);
 
-		/* Clear any lingering interrupt */
-		CHIPREG_WRITE32(&this->chip->IntStatus, 0);
-
-		CHIPREG_READ32(&this->chip->IntStatus);
-
+		dexitprintk((MYIOC_s_INFO_FMT "Calling mpt_adapter_dispose for ioc %d\n", this->name,this->id));
 		Q_DEL_ITEM(this);
 		mpt_adapter_dispose(this);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptbase.h linux-2.4.27-rc4/drivers/message/fusion/mptbase.h
--- linux-2.4.26/drivers/message/fusion/mptbase.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptbase.h	2004-07-30 16:26:08.000000000 +0000
@@ -8,7 +8,7 @@
  *  Credits:
  *     (see mptbase.c)
  *
- *  Copyright (c) 1999-2002 LSI Logic Corporation
+ *  Copyright (c) 1999-2004 LSI Logic Corporation
  *  Originally By: Steven J. Ralston
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:mpt_linux_developer@lsil.com)
@@ -68,6 +68,7 @@
 
 #include "lsi/mpi_fc.h"		/* Fibre Channel (lowlevel) support */
 #include "lsi/mpi_targ.h"	/* SCSI/FCP Target protcol support */
+#include "lsi/mpi_tool.h"	/* Tools support */
 #include "lsi/fc_log.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -77,11 +78,11 @@
 #endif
 
 #ifndef COPYRIGHT
-#define COPYRIGHT	"Copyright (c) 1999-2003 " MODULEAUTHOR
+#define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"2.05.11.03"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-2.05.11.03"
+#define MPT_LINUX_VERSION_COMMON	"2.05.16"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-2.05.16"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -152,6 +153,9 @@
 #define MPT_NARROW			0
 #define MPT_WIDE			1
 
+#define C0_1030				0x08
+#define XL_929				0x01
+
 #ifdef __KERNEL__	/* { */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -527,6 +531,7 @@ typedef struct _mpt_ioctl_events {
 typedef	struct _ScsiCfgData {
 	u32		 PortFlags;
 	int		*nvram;			/* table of device NVRAM values */
+	IOCPage2_t	*pIocPg2;		/* table of Raid Volumes */
 	IOCPage3_t	*pIocPg3;		/* table of physical disks */
 	IOCPage4_t	*pIocPg4;		/* SEP devices addressing */
 	dma_addr_t	 IocPg4_dma;		/* Phys Addr of IOCPage4 data */
@@ -548,13 +553,6 @@ typedef	struct _ScsiCfgData {
 	u8		 rsvd[1];
 } ScsiCfgData;
 
-typedef struct _fw_image {
-	char		*fw;
-	dma_addr_t	 fw_dma;
-	u32		 size;
-	u32		 rsvd;
-} fw_image_t;
-
 /*
  *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
  */
@@ -620,9 +618,9 @@ typedef struct _MPT_ADAPTER
 	int			timeout_maxcnt;
 #endif
 	struct _mpt_ioctl_events *events;	/* pointer to event log */
-	fw_image_t		**cached_fw;	/* Pointer to FW SG List */
+	u8			*cached_fw;	/* Pointer to FW */
+	dma_addr_t	 	cached_fw_dma;
 	Q_TRACKER		 configQ;	/* linked list of config. requests */
-	int			 num_fw_frags;	/* Number of SGE in FW SG List */
 	int			 hs_reply_idx;
 #ifndef MFCNT
 	u32			 pad0;
@@ -700,6 +698,33 @@ typedef struct _mpt_sge {
 #define dprintk(x)
 #endif
 
+#ifdef MPT_DEBUG_INIT
+#define dinitprintk(x)  printk x
+#define DBG_DUMP_FW_REQUEST_FRAME(mfp) \
+	{	int  i, n = 10;						\
+		u32 *m = (u32 *)(mfp);					\
+		printk(KERN_INFO " ");					\
+		for (i=0; i<n; i++)					\
+			printk(" %08x", le32_to_cpu(m[i]));		\
+		printk("\n");						\
+	}
+#else
+#define dinitprintk(x)
+#define DBG_DUMP_FW_REQUEST_FRAME(mfp)
+#endif
+
+#ifdef MPT_DEBUG_EXIT
+#define dexitprintk(x)  printk x
+#else
+#define dexitprintk(x)
+#endif
+
+#ifdef MPT_DEBUG_RESET
+#define drsprintk(x)  printk x
+#else
+#define drsprintk(x)
+#endif
+
 #ifdef MPT_DEBUG_HANDSHAKE
 #define dhsprintk(x)  printk x
 #else
@@ -1026,8 +1051,10 @@ extern u32	 mpt_GetIocState(MPT_ADAPTER 
 extern void	 mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan);
 extern int	 mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag);
 extern int	 mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
-extern void	*mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size, int *frags, int *alloc_sz);
-extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc, fw_image_t **alt_img);
+extern int	 mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *cfg);
+extern void	 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size);
+extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
+extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 
 /*
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptctl.c linux-2.4.27-rc4/drivers/message/fusion/mptctl.c
--- linux-2.4.26/drivers/message/fusion/mptctl.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptctl.c	2004-07-30 16:25:02.000000000 +0000
@@ -29,7 +29,7 @@
  *
  *      (see also mptbase.c)
  *
- *  Copyright (c) 1999-2002 LSI Logic Corporation
+ *  Copyright (c) 1999-2004 LSI Logic Corporation
  *  Originally By: Steven J. Ralston, Noah Romer
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:mpt_linux_developer@lsil.com)
@@ -93,7 +93,7 @@
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
 
-#define COPYRIGHT	"Copyright (c) 1999-2001 LSI Logic Corporation"
+#define COPYRIGHT	"Copyright (c) 1999-2004 LSI Logic Corporation"
 #define MODULEAUTHOR	"Steven J. Ralston, Noah Romer, Pamela Delaney"
 #include "mptbase.h"
 #include "mptctl.h"
@@ -209,6 +209,14 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in
 		return -EBUSY;
 	}
 
+#ifdef MPT_CONFIG_COMPAT
+	if (!nonblock) {
+		if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+			rc = -ERESTARTSYS;
+	} else {
+		rc = -EPERM;
+	}
+#else
 	if (nonblock) {
 		if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
 			rc = -EAGAIN;
@@ -216,6 +224,7 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, in
 		if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
 			rc = -ERESTARTSYS;
 	}
+#endif
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
 	return rc;
 }
@@ -1357,16 +1366,19 @@ mptctl_gettargetinfo (unsigned long arg)
 	MPT_ADAPTER		*ioc;
 	struct Scsi_Host	*sh;
 	MPT_SCSI_HOST		*hd;
+	VirtDevice		*vdev;
 	char			*pmem;
 	int			*pdata;
+	IOCPage2_t		*pIoc2;
+	IOCPage3_t		*pIoc3;
 	int			iocnum;
 	int			numDevices = 0;
 	unsigned int		max_id;
-	int			ii, jj, indexed_lun, lun_index;
+	int			id, jj, indexed_lun, lun_index;
 	u32			lun;
 	int			maxWordsLeft;
 	int			numBytes;
-	u8			port;
+	u8			port, devType, bus_id;
 
 	dctlprintk(("mptctl_gettargetinfo called.\n"));
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) {
@@ -1433,29 +1445,63 @@ mptctl_gettargetinfo (unsigned long arg)
 		 * sh->max_id = maximum target ID + 1
 		 */
 		if (hd && hd->Targets) {
-			ii = 0;
-			while (ii <= max_id) {
-				if (hd->Targets[ii]) {
+			mpt_findImVolumes(ioc);
+			pIoc2 = ioc->spi_data.pIocPg2;
+			for ( id = 0; id <= max_id; ) {
+				if ( pIoc2 && pIoc2->NumActiveVolumes ) {
+					if ( id == pIoc2->RaidVolume[0].VolumeID ) {
+						if (maxWordsLeft <= 0) {
+							printk(KERN_ERR "mptctl_gettargetinfo - "
+			"buffer is full but volume is available on ioc %d\n, numDevices=%d", iocnum, numDevices);
+							goto data_space_full;
+						}
+						if ( ( pIoc2->RaidVolume[0].Flags & MPI_IOCPAGE2_FLAG_VOLUME_INACTIVE ) == 0 )
+                        				devType = 0x80;
+                    				else
+                        				devType = 0xC0;
+						bus_id = pIoc2->RaidVolume[0].VolumeBus;
+	            				numDevices++;
+                    				*pdata = ( (devType << 24) | (bus_id << 8) | id );
+						dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+		"volume ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
+                    				pdata++;
+						--maxWordsLeft;
+						goto next_id;
+					} else {
+						pIoc3 = ioc->spi_data.pIocPg3;
+            					for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) {
+                    					if ( pIoc3->PhysDisk[jj].PhysDiskID == id )
+								goto next_id;
+						}
+					}
+				}
+				if ( (vdev = hd->Targets[id]) ) {
 					for (jj = 0; jj <= MPT_LAST_LUN; jj++) {
 						lun_index = (jj >> 5);
 						indexed_lun = (jj % 32);
 						lun = (1 << indexed_lun);
-						if (hd->Targets[ii]->luns[lun_index] & lun) {
+						if (vdev->luns[lun_index] & lun) {
+							if (maxWordsLeft <= 0) {
+								printk(KERN_ERR "mptctl_gettargetinfo - "
+			"buffer is full but more targets are available on ioc %d numDevices=%d\n", iocnum, numDevices);
+								goto data_space_full;
+							}
+							bus_id = vdev->bus_id;
 							numDevices++;
-							*pdata = (jj << 16) | ii;
-							--maxWordsLeft;
-
+                            				*pdata = ( (jj << 16) | (bus_id << 8) | id );
+							dctlprintk((KERN_ERR "mptctl_gettargetinfo - "
+		"target ioc=%d target=%x numDevices=%d pdata=%p\n", iocnum, *pdata, numDevices, pdata));
 							pdata++;
-
-							if (maxWordsLeft <= 0)
-								break;
+							--maxWordsLeft;
 						}
 					}
 				}
-				ii++;
+next_id:
+				id++;
 			}
 		}
 	}
+data_space_full:
 	karg.numDevices = numDevices;
 
 	/* Copy part of the data from kernel memory to user memory
@@ -1693,12 +1739,11 @@ mptctl_replace_fw (unsigned long arg)
 	struct mpt_ioctl_replace_fw	*uarg = (struct mpt_ioctl_replace_fw *) arg;
 	struct mpt_ioctl_replace_fw	 karg;
 	MPT_ADAPTER		 *ioc;
-	fw_image_t		 **fwmem = NULL;
+	u8			 *fwmem = NULL;
 	int			 iocnum;
 	int			 newFwSize;
-	int			 num_frags, alloc_sz;
+	int			 alloc_sz;
 	int			 ii;
-	u32			 offset;
 
 	dctlprintk(("mptctl_replace_fw called.\n"));
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
@@ -1715,51 +1760,39 @@ mptctl_replace_fw (unsigned long arg)
 		return -ENODEV;
 	}
 
-	/* If not caching FW, return 0
+	/* If caching FW, Free the old FW image
 	 */
-	if ((ioc->cached_fw == NULL) && (ioc->alt_ioc) && (ioc->alt_ioc->cached_fw == NULL))
+	if (ioc->cached_fw) {
+		mpt_free_fw_memory(ioc);
+	} else
 		return 0;
 
 	/* Allocate memory for the new FW image
 	 */
 	newFwSize = karg.newImageSize;
-	fwmem = mpt_alloc_fw_memory(ioc, newFwSize, &num_frags, &alloc_sz);
-	if (fwmem == NULL)
-		return -ENOMEM;
-
-	offset = 0;
-	for (ii = 0; ii < num_frags; ii++) {
-		/* Copy the data from user memory to kernel space
-		 */
-		if (copy_from_user(fwmem[ii]->fw, uarg->newImage + offset, fwmem[ii]->size)) {
-			printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
-				"Unable to read in mpt_ioctl_replace_fw image @ %p\n",
-					__FILE__, __LINE__, (void*)uarg);
-
-			mpt_free_fw_memory(ioc, fwmem);
-			return -EFAULT;
-		}
-		offset += fwmem[ii]->size;
-	}
+	if ( newFwSize & 0x01 )
+		newFwSize += 1;
+	if ( newFwSize & 0x02 )
+		newFwSize += 2;
 
+	mpt_alloc_fw_memory(ioc, newFwSize);
+	if (ioc->cached_fw == NULL)
+		return -ENOMEM;
 
-	/* Free the old FW image
+	/* Copy the data from user memory to kernel space
 	 */
-	if (ioc->cached_fw) {
-		mpt_free_fw_memory(ioc, 0);
-		ioc->cached_fw = fwmem;
-		ioc->alloc_total += alloc_sz;
-	} else if ((ioc->alt_ioc) && (ioc->alt_ioc->cached_fw)) {
-		mpt_free_fw_memory(ioc->alt_ioc, 0);
-		ioc->alt_ioc->cached_fw = fwmem;
-		ioc->alt_ioc->alloc_total += alloc_sz;
+	if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) {
+		printk(KERN_ERR "%s@%d::mptctl_replace_fw - "
+			"Unable to read in mpt_ioctl_replace_fw image @ %p\n",
+				__FILE__, __LINE__, (void*)uarg);
+
+		mpt_free_fw_memory(ioc);
+		return -EFAULT;
 	}
 
 	/* Update IOCFactsReply
 	 */
 	ioc->facts.FWImageSize = newFwSize;
-	if (ioc->alt_ioc)
-		ioc->alt_ioc->facts.FWImageSize = newFwSize;
 
 	return 0;
 }
@@ -2520,6 +2553,20 @@ mptctl_hp_hostinfo(unsigned long arg, un
 		}
 	}
 
+	cfg.pageAddr = 0;
+	cfg.action = MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL;
+	cfg.dir = MPI_TB_ISTWI_FLAGS_READ;
+	cfg.timeout = 10;
+	pbuf = pci_alloc_consistent(ioc->pcidev, 4, &buf_dma);
+	if (pbuf) {
+		cfg.physAddr = buf_dma;
+		if ((mpt_toolbox(ioc, &cfg)) == 0) {
+			karg.rsvd = *(u32 *)pbuf;
+		}
+		pci_free_consistent(ioc->pcidev, 4, pbuf, buf_dma);
+		pbuf = NULL;
+	}
+
 	/* Copy the data from kernel memory to user memory
 	 */
 	if (copy_to_user((char *)arg, &karg,
@@ -2900,8 +2947,7 @@ int __init mptctl_init(void)
 	if (++where && err) goto out_fail;
 	err = register_ioctl32_conversion(HP_GETHOSTINFO, compat_mptctl_ioctl);
 	if (++where && err) goto out_fail;
-	err = register_ioctl32_conversion(HP_GETTARGETINFO,
-	    				compat_mptctl_ioctl);
+	err = register_ioctl32_conversion(HP_GETTARGETINFO, compat_mptctl_ioctl);
 	if (++where && err) goto out_fail;
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptctl.h linux-2.4.27-rc4/drivers/message/fusion/mptctl.h
--- linux-2.4.26/drivers/message/fusion/mptctl.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptctl.h	2004-07-30 16:25:26.000000000 +0000
@@ -15,7 +15,7 @@
  *
  *      (see also mptbase.c)
  *
- *  Copyright (c) 1999-2002 LSI Logic Corporation
+ *  Copyright (c) 1999-2004 LSI Logic Corporation
  *  Originally By: Steven J. Ralston
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:mpt_linux_developer@lsil.com)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptlan.c linux-2.4.27-rc4/drivers/message/fusion/mptlan.c
--- linux-2.4.26/drivers/message/fusion/mptlan.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptlan.c	2004-07-30 16:28:38.000000000 +0000
@@ -23,7 +23,7 @@
  *
  *      (see also mptbase.c)
  *
- *  Copyright (c) 2000-2002 LSI Logic Corporation
+ *  Copyright (c) 2000-2004 LSI Logic Corporation
  *  Originally By: Noah Romer
  *
  *  $Id: mptlan.c,v 1.55 2003/05/07 14:08:32 pdelaney Exp $
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptscsih.c linux-2.4.27-rc4/drivers/message/fusion/mptscsih.c
--- linux-2.4.26/drivers/message/fusion/mptscsih.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptscsih.c	2004-07-30 16:27:42.000000000 +0000
@@ -21,7 +21,7 @@
  *
  *      (see mptbase.c)
  *
- *  Copyright (c) 1999-2002 LSI Logic Corporation
+ *  Copyright (c) 1999-2004 LSI Logic Corporation
  *  Original author: Steven J. Ralston
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:mpt_linux_developer@lsil.com)
@@ -217,7 +217,6 @@ static struct notifier_block mptscsih_no
  */
 
 static int	mpt_scsi_hosts = 0;
-static atomic_t	queue_depth;
 
 static int	ScsiDoneCtx = -1;
 static int	ScsiTaskCtx = -1;
@@ -741,8 +740,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 	if (sc == NULL) {
 		MPIHeader_t *hdr = (MPIHeader_t *)mf;
 
-		atomic_dec(&queue_depth);
-
 		/* Remark: writeSDP1 will use the ScsiDoneCtx
 		 * If a SCSI I/O cmd, device disabled by OS and
 		 * completion done. Cannot touch sc struct. Just free mem.
@@ -757,8 +754,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 	dmfprintk((MYIOC_s_INFO_FMT "ScsiDone (mf=%p,mr=%p,sc=%p,idx=%d)\n",
 			ioc->name, mf, mr, sc, req_idx));
 
-	atomic_dec(&queue_depth);
-
 	sc->result = DID_OK << 16;		/* Set default reply as OK */
 	pScsiReq = (SCSIIORequest_t *) mf;
 	pScsiReply = (SCSIIOReply_t *) mr;
@@ -788,23 +783,21 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 
 		/* If regular Inquiry cmd - save inquiry data
 		 */
-		if (pScsiReq->CDB[0] == INQUIRY && !(pScsiReq->CDB[1] & 0x3)) {
+		if (pScsiReq->CDB[0] == INQUIRY) {
 			int	 dlen;
 
 			dlen = le32_to_cpu(pScsiReq->DataLength);
-			if (dlen >= SCSI_STD_INQUIRY_BYTES) {
-				mptscsih_initTarget(hd,
-						sc->channel,
-						sc->target,
-						pScsiReq->LUN[1],
-						sc->buffer,
-						dlen);
-			}
+			mptscsih_initTarget(hd,
+					sc->channel,
+					sc->target,
+					pScsiReq->LUN[1],
+					sc->buffer,
+					dlen);
 		}
 	} else {
 		u32	 xfer_cnt;
 		u16	 status;
-		u8	 scsi_state;
+		u8	 scsi_state, scsi_status;
 
 		status = le16_to_cpu(pScsiReply->IOCStatus) & MPI_IOCSTATUS_MASK;
 		scsi_state = pScsiReply->SCSIState;
@@ -820,14 +813,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
 			copy_sense_data(sc, hd, mf, pScsiReply);
 
-		/*
-		 *  Look for + dump FCP ResponseInfo[]!
-		 */
-		if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) {
-			dprintk((KERN_NOTICE "  FCP_ResponseInfo=%08xh\n",
-					     le32_to_cpu(pScsiReply->ResponseInfo)));
-		}
-
 		switch(status) {
 		case MPI_IOCSTATUS_BUSY:			/* 0x0002 */
 			/* CHECKME!
@@ -877,35 +862,45 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 				mptscsih_no_negotiate(hd, sc->target);
 			break;
 
+		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
+			sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | 
+					(CHECK_CONDITION << 1);
+			sc->sense_buffer[0] = 0x70;
+			sc->sense_buffer[2] = NO_SENSE;
+			sc->sense_buffer[12] = 0;
+			sc->sense_buffer[13] = 0;
+			dprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
+			break;
+
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
 			/*
-			 *  YIKES!  I just discovered that SCSI IO which
-			 *  returns check condition, SenseKey=05 (ILLEGAL REQUEST)
-			 *  and ASC/ASCQ=94/01 (LSI Logic RAID vendor specific),
-			 *  comes down this path!
 			 *  Do upfront check for valid SenseData and give it
 			 *  precedence!
 			 */
-			sc->result = (DID_OK << 16) | pScsiReply->SCSIStatus;
-			if (scsi_state == 0) {
-				;
-			} else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
+			scsi_status = pScsiReply->SCSIStatus;
+			sc->result = (DID_OK << 16) | scsi_status;
+			xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
+			if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) {
 				/* Have already saved the status and sense data
 				 */
 				;
-			} else if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
-				/* What to do?
-				 */
-				sc->result = DID_SOFT_ERROR << 16;
-			}
-			else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
-				/*  Not real sure here either...  */
-				sc->result = DID_RESET << 16;
+			} else {
+				if ( (xfer_cnt == 0) || (sc->underflow > xfer_cnt)) {
+					sc->result = DID_SOFT_ERROR << 16;
+				}
+				if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) {
+					/* What to do?
+				 	*/
+					sc->result = DID_SOFT_ERROR << 16;
+				}
+				else if (scsi_state & MPI_SCSI_STATE_TERMINATED) {
+					/*  Not real sure here either...  */
+					sc->result = DID_RESET << 16;
+				}
 			}
 
 			/* Give report and update residual count.
 			 */
-			xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
 			dprintk((KERN_NOTICE "  sc->underflow={report ERR if < %02xh bytes xfer'd}\n",
 					sc->underflow));
 			dprintk((KERN_NOTICE "  ActBytesXferd=%02xh\n", xfer_cnt));
@@ -914,22 +909,15 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 			sc->resid = sc->request_bufflen - xfer_cnt;
 			dprintk((KERN_NOTICE "  SET sc->resid=%02xh\n", sc->resid));
 #endif
-			if((xfer_cnt == 0 ) || (sc->underflow > xfer_cnt)) {
-				sc->result = DID_SOFT_ERROR << 16;
-			}
-
 			/* Report Queue Full
 			 */
-			if (sc->result == MPI_SCSI_STATUS_TASK_SET_FULL)
+			if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
 				mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
 
 			/* If regular Inquiry cmd and some data was transferred,
 			 * save inquiry data
 			 */
-			if (    pScsiReq->CDB[0] == INQUIRY
-			     && !(pScsiReq->CDB[1] & 0x3)
-			     && xfer_cnt >= SCSI_STD_INQUIRY_BYTES
-			   ) {
+			if ( (pScsiReq->CDB[0] == INQUIRY) && xfer_cnt ) {
 				mptscsih_initTarget(hd,
 						sc->channel,
 						sc->target,
@@ -1006,11 +994,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 			/* If regular Inquiry cmd - save inquiry data
 			 */
 			xfer_cnt = le32_to_cpu(pScsiReply->TransferCount);
-			if (    sc->result == (DID_OK << 16)
-			     && pScsiReq->CDB[0] == INQUIRY
-			     && !(pScsiReq->CDB[1] & 0x3)
-			     && xfer_cnt >= SCSI_STD_INQUIRY_BYTES
-			   ) {
+			if ( (sc->result == (DID_OK << 16))
+			     && xfer_cnt
+			     && pScsiReq->CDB[0] == INQUIRY ) {
 				mptscsih_initTarget(hd,
 						sc->channel,
 						sc->target,
@@ -1037,7 +1023,6 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 		case MPI_IOCSTATUS_INVALID_STATE:		/* 0x0008 */
 		case MPI_IOCSTATUS_SCSI_DATA_OVERRUN:		/* 0x0044 */
 		case MPI_IOCSTATUS_SCSI_IO_DATA_ERROR:		/* 0x0046 */
-		case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:	/* 0x0049 */
 		case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED:	/* 0x004A */
 		default:
 			/*
@@ -1371,11 +1356,9 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOS
 #endif
 
 			/* Search pendingQ, if found,
-			 * delete from Q. If found, do not decrement
-			 * queue_depth, command never posted.
+			 * delete from Q.
 			 */
-			if (mptscsih_search_pendingQ(hd, ii) == NULL)
-				atomic_dec(&queue_depth);
+			mptscsih_search_pendingQ(hd, ii);
 
 			/* Null ScsiLookup index
 			 */
@@ -2429,7 +2412,6 @@ int mptscsih_proc_info(char *buffer, cha
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-	static int max_qd = 1;
 #if 0
 static int index_log[128];
 static int index_ent = 0;
@@ -2443,32 +2425,6 @@ static __inline__ void ADD_INDEX_LOG(int
 #define ADD_INDEX_LOG(req_ent)	do { } while(0)
 #endif
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	mptscsih_put_msgframe - Wrapper routine to post message frame to F/W.
- *	@context: Call back context (ScsiDoneCtx, ScsiScanDvCtx)
- *	@id: IOC id number
- *	@mf: Pointer to message frame
- *
- *	Handles the call to mptbase for posting request and queue depth
- *	tracking.
- *
- *	Returns none.
- */
-static inline void
-mptscsih_put_msgframe(int context, int id, MPT_FRAME_HDR *mf)
-{
-	/* Main banana... */
-	atomic_inc(&queue_depth);
-	if (atomic_read(&queue_depth) > max_qd) {
-		max_qd = atomic_read(&queue_depth);
-		dprintk((KERN_INFO MYNAM ": Queue depth now %d.\n", max_qd));
-	}
-
-	mpt_put_msg_frame(context, id, mf);
-
-	return;
-}
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
@@ -2599,7 +2555,6 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*d
 
 	/*
 	 *  Write SCSI CDB into the message
-	 *  Should write from cmd_len up to 16, but skip for performance reasons.
 	 */
 	cmd_len = SCpnt->cmd_len;
 	for (ii=0; ii < cmd_len; ii++)
@@ -2640,17 +2595,6 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*d
 
 			if (dvStatus || hd->ioc->spi_data.forceDv) {
 
-				/* Write SDP1 on this I/O to this target */
-				if (dvStatus & MPT_SCSICFG_NEGOTIATE) {
-					mptscsih_writeSDP1(hd, 0, target, hd->negoNvram);
-					dvStatus &= ~MPT_SCSICFG_NEGOTIATE;
-					hd->ioc->spi_data.dvStatus[target] =  dvStatus;
-				} else if (dvStatus & MPT_SCSICFG_BLK_NEGO) {
-					mptscsih_writeSDP1(hd, 0, target, MPT_SCSICFG_BLK_NEGO);
-					dvStatus &= ~MPT_SCSICFG_BLK_NEGO;
-					hd->ioc->spi_data.dvStatus[target] =  dvStatus;
-				}
-
 #ifndef MPTSCSIH_DISABLE_DOMAIN_VALIDATION
 				if ((dvStatus & MPT_SCSICFG_NEED_DV) ||
 					(hd->ioc->spi_data.forceDv & MPT_SCSICFG_NEED_DV)) {
@@ -2698,7 +2642,7 @@ mptscsih_qcmd(Scsi_Cmnd *SCpnt, void (*d
 #endif
 
 		if (issueCmd) {
-			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
+			mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
 			dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
 					hd->ioc->name, SCpnt, mf, my_idx));
 		} else {
@@ -3073,8 +3017,8 @@ mptscsih_abort(Scsi_Cmnd * SCpnt)
 	if (hd->resetPending)
 		return FAILED;
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p, numIOs=%d)\n",
-	       hd->ioc->name, SCpnt, atomic_read(&queue_depth));
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n",
+	       hd->ioc->name, SCpnt));
 
 	if (hd->timeouts < -1)
 		hd->timeouts++;
@@ -3099,7 +3043,7 @@ mptscsih_abort(Scsi_Cmnd * SCpnt)
 	 * and then following up with the reset request.
 	 */
 	if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
+		mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
 		post_pendingQ_commands(hd);
 		nehprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: "
 			   "Posting pended cmd! (sc=%p)\n",
@@ -3164,8 +3108,8 @@ mptscsih_dev_reset(Scsi_Cmnd * SCpnt)
 	if (hd->resetPending)
 		return FAILED;
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p, numIOs=%d)\n",
-	       hd->ioc->name, SCpnt, atomic_read(&queue_depth));
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
+	       hd->ioc->name, SCpnt);
 
 	/* Unsupported for SCSI. Supported for FCP
 	 */
@@ -3211,8 +3155,8 @@ mptscsih_bus_reset(Scsi_Cmnd * SCpnt)
 		return FAILED;
 	}
 
-	printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p, numIOs=%d)\n",
-	       hd->ioc->name, SCpnt, atomic_read(&queue_depth));
+	printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n",
+	       hd->ioc->name, SCpnt));
 
 	if (hd->timeouts < -1)
 		hd->timeouts++;
@@ -3262,8 +3206,6 @@ mptscsih_host_reset(Scsi_Cmnd *SCpnt)
 
 	printk(KERN_WARNING MYNAM ": %s: >> Attempting host reset! (sc=%p)\n",
 	       hd->ioc->name, SCpnt);
-	printk(KERN_WARNING MYNAM ": %s: IOs outstanding = %d\n",
-	       hd->ioc->name, atomic_read(&queue_depth));
 
 	/*  If our attempts to reset the host failed, then return a failed
 	 *  status.  The host will be taken off line by the SCSI mid-layer.
@@ -3339,7 +3281,6 @@ mptscsih_old_abort(Scsi_Cmnd *SCpnt)
 	int			 scpnt_idx;
 
 	printk(KERN_WARNING MYNAM ": OldAbort scheduling ABORT SCSI IO (sc=%p)\n", (void *) SCpnt);
-	printk(KERN_WARNING "  IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
 		printk(KERN_WARNING "  WARNING - OldAbort, NULL hostdata ptr!!\n");
@@ -3366,7 +3307,7 @@ mptscsih_old_abort(Scsi_Cmnd *SCpnt)
 		 */
 #ifndef MPTSCSIH_DBG_TIMEOUT
 		if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
+			mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
 			post_pendingQ_commands(hd);
 		}
 #endif
@@ -3472,7 +3413,6 @@ mptscsih_old_reset(Scsi_Cmnd *SCpnt, uns
 	int			 scpnt_idx;
 
 	printk(KERN_WARNING MYNAM ": OldReset scheduling BUS_RESET (sc=%p)\n", (void *) SCpnt);
-	printk(KERN_WARNING "  IOs outstanding = %d\n", atomic_read(&queue_depth));
 
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->host->hostdata) == NULL) {
 		SCpnt->result = DID_ERROR << 16;
@@ -3498,7 +3438,7 @@ mptscsih_old_reset(Scsi_Cmnd *SCpnt, uns
 		 */
 #ifndef MPTSCSIH_DBG_TIMEOUT
 		if ((mf = mptscsih_search_pendingQ(hd, scpnt_idx)) != NULL) {
-			mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
+			mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
 			post_pendingQ_commands(hd);
 		}
 #endif
@@ -3740,7 +3680,6 @@ mptscsih_taskmgmt_bh(void *sc)
 						": WARNING[1] - IOC error processing TaskMgmt request (sc=%p)\n", (void *) SCpnt);
 
 					if (hd->ScsiLookup[scpnt_idx] != NULL) {
-						atomic_dec(&queue_depth);
 						SCpnt->result = DID_SOFT_ERROR << 16;
                                                 MPT_HOST_LOCK(flags);
 						SCpnt->scsi_done(SCpnt);
@@ -3937,7 +3876,6 @@ mptscsih_select_queue_depths(struct Scsi
 			continue;
 
 		if (hd->Targets != NULL) {
-			pTarget = NULL;
 			if (device->id > sh->max_id) {
 				/* error case, should never happen */
 				device->queue_depth = 1;
@@ -3949,25 +3887,27 @@ mptscsih_select_queue_depths(struct Scsi
 			if (pTarget == NULL) {
 				/* error case - don't know about this device */
 				device->queue_depth = 1;
-			} else if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
-				if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
-					device->queue_depth = 1;
-				else if (((pTarget->inq_data[0] & 0x1f) == 0x00)
-					 && (pTarget->minSyncFactor <= MPT_ULTRA160 || !hd->is_spi)){
-					device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
-				} else
-					device->queue_depth = MPT_SCSI_CMD_PER_DEV_LOW;
-
 			} else {
-				/* error case - No Inq. Data */
-				device->queue_depth = 1;
+				device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+				if ( hd->is_spi ) {
+					if (pTarget->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
+						if (!(pTarget->tflags & MPT_TARGET_FLAGS_Q_YES))
+							device->queue_depth = 1;
+						else if (((pTarget->inq_data[0] & 0x1f) == 0x00) && (pTarget->minSyncFactor <= MPT_ULTRA160 )){
+							device->queue_depth = MPT_SCSI_CMD_PER_DEV_HIGH;
+						} else
+							device->queue_depth = MPT_SCSI_CMD_PER_DEV_LOW;
+					} else {
+						/* error case - No Inq. Data */
+						device->queue_depth = 1;
+					}
+				}
 			}
 
 			if (pTarget != NULL) {
 				dprintk((MYIOC_s_INFO_FMT
-					 "scsi%d: Id=%d Lun=%d: Queue depth=%d\n",
-					 hd->ioc->name, 
-					 device->id, device->lun, device->queue_depth));
+					 "scsi%d: Id=%d Lun=%d: Queue depth=%d tflags=%x\n",
+					 hd->ioc->name, device->id, pTarget->target_id, device->lun, device->queue_depth, pTarget->tflags));
 
 				dprintk((MYIOC_s_INFO_FMT
 					 "Id = %d, sync factor = %x\n",
@@ -4172,7 +4112,7 @@ post_pendingQ_commands(MPT_SCSI_HOST *hd
 			continue;
 		}
 
-		mptscsih_put_msgframe(ScsiDoneCtx, hd->ioc->id, mf);
+		mpt_put_msg_frame(ScsiDoneCtx, hd->ioc->id, mf);
 
 #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY)
 		{
@@ -4239,7 +4179,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int
 		if (hd->cmdPtr) {
 			del_timer(&hd->timer);
 			mpt_free_msg_frame(ScsiScanDvCtx, ioc->id, hd->cmdPtr);
-			atomic_dec(&queue_depth);
 		}
 
 		/* 2d. If a task management has not completed,
@@ -4978,31 +4917,41 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 {
 	int		indexed_lun, lun_index;
 	VirtDevice	*vdev;
+	char		data_56;
 
-	dprintk((MYIOC_s_INFO_FMT "initTarget (%d,%d,%d) called, hd=%p\n",
+	dprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n",
 			hd->ioc->name, bus_id, target_id, lun, hd));
 
+	/* Is LUN supported? If so, upper 3 bits will be 0
+	* in first byte of inquiry data.
+	*/
+	if (data[0] & 0xe0)
+		return;
+
 	if ((vdev = hd->Targets[target_id]) == NULL) {
 		if ((vdev = kmalloc(sizeof(VirtDevice), GFP_ATOMIC)) == NULL) {
 			printk(MYIOC_s_ERR_FMT "initTarget kmalloc(%d) FAILED!\n",
 					hd->ioc->name, (int)sizeof(VirtDevice));
 			return;
-		} else {
-			memset(vdev, 0, sizeof(VirtDevice));
-			rwlock_init(&vdev->VdevLock);
-			Q_INIT(&vdev->WaitQ, void);
-			Q_INIT(&vdev->SentQ, void);
-			Q_INIT(&vdev->DoneQ, void);
-			vdev->tflags = 0;
-			vdev->ioc_id = hd->ioc->id;
-			vdev->target_id = target_id;
-			vdev->bus_id = bus_id;
-
-			hd->Targets[target_id] = vdev;
-			dprintk((KERN_INFO "  *NEW* Target structure (id %d) @ %p\n",
-					target_id, vdev));
 		}
-	}
+		memset(vdev, 0, sizeof(VirtDevice));
+		rwlock_init(&vdev->VdevLock);
+		Q_INIT(&vdev->WaitQ, void);
+		Q_INIT(&vdev->SentQ, void);
+		Q_INIT(&vdev->DoneQ, void);
+		vdev->tflags = 0;
+		vdev->ioc_id = hd->ioc->id;
+		vdev->target_id = target_id;
+		vdev->bus_id = bus_id;
+
+		hd->Targets[target_id] = vdev;
+		dprintk((KERN_INFO "  *NEW* Target structure (id %d) @ %p\n",
+			target_id, vdev));
+	}
+
+	lun_index = (lun >> 5);  /* 32 luns per lun_index */
+	indexed_lun = (lun % 32);
+	vdev->luns[lun_index] |= (1 << indexed_lun);
 
 	vdev->raidVolume = 0;
 	if (hd->is_spi) {
@@ -5013,10 +4962,20 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 	}
 
 	if (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY)) {
-		/* Copy the inquiry data  - if we haven't yet.
-		*/
-
-		memcpy (vdev->inq_data, data, 8);
+		if ( dlen > 8 ) {
+			memcpy (vdev->inq_data, data, 8);
+		} else {
+			memcpy (vdev->inq_data, data, dlen);
+		}
+		vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+		
+		/* If LUN 0, tape and have not done DV, set the DV flag.
+		 */
+		if (hd->is_spi && (lun == 0) && (data[0] == SCSI_TYPE_TAPE)) {
+			ScsiCfgData *pSpi = &hd->ioc->spi_data;
+			if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
+				pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
+		}
 
 		if ( (data[0] == SCSI_TYPE_PROC) && 
 			!(vdev->tflags & MPT_TARGET_FLAGS_SAF_TE_ISSUED )) {
@@ -5039,35 +4998,18 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, i
 					mptscsih_writeIOCPage4(hd, target_id, bus_id);
 				}
 			}
-		} else 
-			vdev->tflags |= MPT_TARGET_FLAGS_VALID_INQUIRY;
+		} 
 
-		if ((dlen > 56) && (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
+		data_56 = 0x0F;  /* Default to full capabilities if Inq data length is < 57 */
+		if (dlen > 56) {
+			if ( (!(vdev->tflags & MPT_TARGET_FLAGS_VALID_56))) {
 			/* Update the target capabilities
 			 */
-			if (dlen > 56) {
-				mptscsih_setTargetNegoParms(hd, vdev, data[56]);
+				data_56 = data[56];
 				vdev->tflags |= MPT_TARGET_FLAGS_VALID_56;
-			} else
-				mptscsih_setTargetNegoParms(hd, vdev, 0);
-
-			/* If LUN 0, tape and have not done DV, set the DV flag.
-			 */
-			if (hd->is_spi && (lun == 0) && ((data[0] & 0x1F) == 0x01)) {
-				ScsiCfgData *pSpi = &hd->ioc->spi_data;
-				if (pSpi->dvStatus[target_id] & MPT_SCSICFG_DV_NOT_DONE)
-					pSpi->dvStatus[target_id] |= MPT_SCSICFG_NEED_DV;
 			}
 		}
-	}
-
-	/* Is LUN supported? If so, upper 3 bits will be 0
-	 * in first byte of inquiry data.
-	 */
-	if ((*data & 0xe0) == 0) {
-		lun_index = (lun >> 5);  /* 32 luns per lun_index */
-		indexed_lun = (lun % 32);
-		vdev->luns[lun_index] |= (1 << indexed_lun);
+		mptscsih_setTargetNegoParms(hd, vdev, data_56);
 	}
 
 	dprintk((KERN_INFO "  target = %p\n", vdev));
@@ -5093,7 +5035,7 @@ void mptscsih_setTargetNegoParms(MPT_SCS
 	u8 offset = 0;
 	u8 version, nfactor;
 	u8 noQas = 1;
-
+	
 	if (!hd->is_spi) {
 		if (target->tflags & MPT_TARGET_FLAGS_VALID_INQUIRY) {
 			if (target->inq_data[7] & 0x02)
@@ -5123,14 +5065,16 @@ void mptscsih_setTargetNegoParms(MPT_SCS
 			}
 
 			if (target->inq_data[7] & 0x10) {
-				/* bits 2 & 3 show DT support
+				/* bits 2 & 3 show Clocking support
 				 */
-				if ((byte56 & 0x04) == 0)
+				if ((byte56 & 0x0C) == 0)
 					factor = MPT_ULTRA2;
-				else if ((byte56 & 0x03) == 0)
-					factor = MPT_ULTRA160;
-				else
-					factor = MPT_ULTRA320;
+				else {
+					if ((byte56 & 0x03) == 0)
+						factor = MPT_ULTRA160;
+					else
+						factor = MPT_ULTRA320;
+				}
 				offset = pspi_data->maxSyncOffset;
 
 				/* If RAID, never disable QAS
@@ -5139,8 +5083,9 @@ void mptscsih_setTargetNegoParms(MPT_SCS
 				 * bit 1 QAS support, non-raid only
 				 * bit 0 IU support
 				 */
-				if ((target->raidVolume == 1) || ((byte56 & 0x02) != 0))
+				if ((target->raidVolume == 1) || (byte56 & 0x02)) {
 					noQas = 0;
+				}
 			} else {
 				factor = MPT_ASYNC;
 				offset = 0;
@@ -5218,7 +5163,7 @@ void mptscsih_setTargetNegoParms(MPT_SCS
 				/* Disable QAS in a mixed configuration case
 		 		*/
 
-//				ddvtprintk((KERN_INFO "Disabling QAS!\n"));
+				ddvtprintk((KERN_INFO "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id));
 				for (ii = 0; ii < id; ii++) {
 					if ( (vdev = hd->Targets[ii]) ) {
 						vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
@@ -5226,8 +5171,17 @@ void mptscsih_setTargetNegoParms(MPT_SCS
 				}
 			}
 		}
+	
+		/* Write SDP1 on this I/O to this target */
+		if (pspi_data->dvStatus[id] & MPT_SCSICFG_NEGOTIATE) {
+			mptscsih_writeSDP1(hd, 0, id, hd->negoNvram);
+			pspi_data->dvStatus[id] &= ~MPT_SCSICFG_NEGOTIATE;
+		} else if (pspi_data->dvStatus[id] & MPT_SCSICFG_BLK_NEGO) {
+			mptscsih_writeSDP1(hd, 0, id, MPT_SCSICFG_BLK_NEGO);
+			pspi_data->dvStatus[id] &= ~MPT_SCSICFG_BLK_NEGO;
+		}
+	
 	}
-
 	return;
 }
 
@@ -5488,9 +5442,8 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
 		pReq->Reserved = 0;
 		pReq->ChainOffset = 0;
 		pReq->Function = MPI_FUNCTION_CONFIG;
-		pReq->Reserved1[0] = 0;
-		pReq->Reserved1[1] = 0;
-		pReq->Reserved1[2] = 0;
+		pReq->ExtPageLength = 0;
+		pReq->ExtPageType = 0;
 		pReq->MsgFlags = 0;
 		for (ii=0; ii < 8; ii++) {
 			pReq->Reserved2[ii] = 0;
@@ -5522,7 +5475,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, in
 				ioc->name, id, (id | (bus<<8)),
 				requested, configuration));
 
-		mptscsih_put_msgframe(ScsiDoneCtx, ioc->id, mf);
+		mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
 	}
 
 	return 0;
@@ -5576,9 +5529,8 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
 	pReq->Reserved = 0;
 	pReq->ChainOffset = 0;
 	pReq->Function = MPI_FUNCTION_CONFIG;
-	pReq->Reserved1[0] = 0;
-	pReq->Reserved1[1] = 0;
-	pReq->Reserved1[2] = 0;
+	pReq->ExtPageLength = 0;
+	pReq->ExtPageType = 0;
 	pReq->MsgFlags = 0;
 	for (ii=0; ii < 8; ii++) {
 		pReq->Reserved2[ii] = 0;
@@ -5603,7 +5555,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd
 		"writeIOCPage4: pgaddr 0x%x\n",
 			ioc->name, (target_id | (bus<<8))));
 
-	mptscsih_put_msgframe(ScsiDoneCtx, ioc->id, mf);
+	mpt_put_msg_frame(ScsiDoneCtx, ioc->id, mf);
 
 	return 0;
 }
@@ -5704,8 +5656,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *io
 	ddvprintk((MYIOC_s_INFO_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n",
 			hd->ioc->name, mf, mr, req_idx));
 
-	atomic_dec(&queue_depth);
-
 	hd->pLocal = &hd->localReply;
 	hd->pLocal->scsiStatus = 0;
 
@@ -5948,7 +5898,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
 			hd->ioc->name, action, io->id));
 
 	hd->pLocal = NULL;
-	hd->timer.expires = jiffies + HZ*2; /* 2 second timeout */
+	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
 	scandv_wait_done = 0;
 
 	/* Save cmd pointer, for resource free if timeout or
@@ -5957,7 +5907,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 a
 	hd->cmdPtr = mf;
 
 	add_timer(&hd->timer);
-	mptscsih_put_msgframe(ScsiScanDvCtx, hd->ioc->id, mf);
+	mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
 	wait_event(scandv_waitq, scandv_wait_done);
 
 	if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
@@ -6194,7 +6144,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTER
 	hd->cmdPtr = mf;
 
 	add_timer(&hd->timer);
-	mptscsih_put_msgframe(ScsiScanDvCtx, hd->ioc->id, mf);
+	mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc->id, mf);
 	wait_event(scandv_waitq, scandv_wait_done);
 
 	if (hd->pLocal) {
@@ -6638,8 +6588,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 	lun = 0;
 	bus = (u8) bus_number;
 	ddvtprintk((MYIOC_s_NOTE_FMT
-			"DV started: numIOs %d bus=%d, id %d dv @ %p\n",
-			ioc->name, atomic_read(&queue_depth), bus, id, &dv));
+			"DV started: bus=%d, id %d dv @ %p\n",
+			ioc->name, bus, id, &dv));
 
 	/* Prep DV structure
 	 */
@@ -6818,7 +6768,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 	sz = SCSI_STD_INQUIRY_BYTES;
 	rc = MPT_SCANDV_GOOD;
 	while (1) {
-		ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test.\n", ioc->name));
+		ddvprintk((MYIOC_s_NOTE_FMT "DV: Start Basic test on id=%d\n", ioc->name, id));
 		retcode = 0;
 		dv.cmd = MPT_SET_MIN;
 		mptscsih_dv_parms(hd, &dv, (void *)pcfg1Data);
@@ -7010,7 +6960,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus
 			firstPass = 0;
 		}
 	}
-	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test completed OK.\n", ioc->name));
+	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
 	inq0 = (*pbuf1) & 0x1F;
 
 	/* Continue only for disks
@@ -7461,8 +7411,8 @@ target_done:
 	if (pDvBuf)
 		pci_free_consistent(ioc->pcidev, dv_alloc, pDvBuf, dvbuf_dma);
 
-	ddvtprintk((MYIOC_s_INFO_FMT "DV Done. IOs outstanding = %d\n",
-			ioc->name, atomic_read(&queue_depth)));
+	ddvtprintk((MYIOC_s_INFO_FMT "DV Done.\n",
+			ioc->name));
 
 	return retcode;
 }
@@ -7631,7 +7581,6 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVP
 				factor = MPT_ULTRA;
 				width = MPT_WIDE;
 			} else if ((factor == MPT_ULTRA) && width) {
-				factor = MPT_ULTRA;
 				width = MPT_NARROW;
 			} else if (factor < MPT_FAST) {
 				factor = MPT_FAST;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/mptscsih.h linux-2.4.27-rc4/drivers/message/fusion/mptscsih.h
--- linux-2.4.26/drivers/message/fusion/mptscsih.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/mptscsih.h	2004-07-30 16:32:06.000000000 +0000
@@ -15,7 +15,7 @@
  *
  *      (see also mptbase.c)
  *
- *  Copyright (c) 1999-2002 LSI Logic Corporation
+ *  Copyright (c) 1999-2004 LSI Logic Corporation
  *  Originally By: Steven J. Ralston
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:mpt_linux_developer@lsil.com)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/message/fusion/scsi3.h linux-2.4.27-rc4/drivers/message/fusion/scsi3.h
--- linux-2.4.26/drivers/message/fusion/scsi3.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/message/fusion/scsi3.h	2004-07-30 16:27:48.000000000 +0000
@@ -4,7 +4,7 @@
  *      (Ultimately) SCSI-3 definitions; for now, inheriting
  *      SCSI-2 definitions.
  *
- *  Copyright (c) 1996-2002 Steven J. Ralston
+ *  Copyright (c) 1996-2004 Steven J. Ralston
  *  Written By: Steven J. Ralston (19960517)
  *  (mailto:sjralston1@netscape.net)
  *  (mailto:mpt_linux_developer@lsil.com)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/8139cp.c linux-2.4.27-rc4/drivers/net/8139cp.c
--- linux-2.4.26/drivers/net/8139cp.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/8139cp.c	2004-07-30 16:28:25.000000000 +0000
@@ -1,6 +1,6 @@
 /* 8139cp.c: A Linux PCI Ethernet driver for the RealTek 8139C+ chips. */
 /*
-	Copyright 2001,2002 Jeff Garzik <jgarzik@pobox.com>
+	Copyright 2001-2004 Jeff Garzik <jgarzik@pobox.com>
 
 	Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com) [tg3.c]
 	Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com) [sungem.c]
@@ -48,8 +48,8 @@
  */
 
 #define DRV_NAME		"8139cp"
-#define DRV_VERSION		"1.1"
-#define DRV_RELDATE		"Aug 30, 2003"
+#define DRV_VERSION		"1.2"
+#define DRV_RELDATE		"Mar 22, 2004"
 
 
 #include <linux/config.h>
@@ -69,6 +69,7 @@
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#include <linux/cache.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -334,36 +335,36 @@ struct cp_extra_stats {
 };
 
 struct cp_private {
-	unsigned		tx_head;
-	unsigned		tx_tail;
-	unsigned		rx_tail;
-
 	void			*regs;
 	struct net_device	*dev;
 	spinlock_t		lock;
+	u32			msg_enable;
+
+	struct pci_dev		*pdev;
+	u32			rx_config;
+	u16			cpcmd;
+
+	struct net_device_stats net_stats;
+	struct cp_extra_stats	cp_stats;
+	struct cp_dma_stats	*nic_stats;
+	dma_addr_t		nic_stats_dma;
 
+	unsigned		rx_tail		____cacheline_aligned;
 	struct cp_desc		*rx_ring;
-	struct cp_desc		*tx_ring;
-	struct ring_info	tx_skb[CP_TX_RING_SIZE];
 	struct ring_info	rx_skb[CP_RX_RING_SIZE];
 	unsigned		rx_buf_sz;
+
+	unsigned		tx_head		____cacheline_aligned;
+	unsigned		tx_tail;
+
+	struct cp_desc		*tx_ring;
+	struct ring_info	tx_skb[CP_TX_RING_SIZE];
 	dma_addr_t		ring_dma;
 
 #if CP_VLAN_TAG_USED
 	struct vlan_group	*vlgrp;
 #endif
 
-	u32			msg_enable;
-
-	struct net_device_stats net_stats;
-	struct cp_extra_stats	cp_stats;
-	struct cp_dma_stats	*nic_stats;
-	dma_addr_t		nic_stats_dma;
-
-	struct pci_dev		*pdev;
-	u32			rx_config;
-	u16			cpcmd;
-
 	unsigned int		wol_enabled : 1; /* Is Wake-on-LAN enabled? */
 	u32			power_state[16];
 
@@ -424,25 +425,27 @@ static struct {
 #if CP_VLAN_TAG_USED
 static void cp_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 	cp->vlgrp = grp;
 	cp->cpcmd |= RxVlanOn;
 	cpw16(CpCmd, cp->cpcmd);
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 }
 
 static void cp_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 	cp->cpcmd &= ~RxVlanOn;
 	cpw16(CpCmd, cp->cpcmd);
 	if (cp->vlgrp)
 		cp->vlgrp->vlan_devices[vid] = NULL;
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 }
 #endif /* CP_VLAN_TAG_USED */
 
@@ -510,7 +513,7 @@ static inline unsigned int cp_rx_csum_ok
 
 static int cp_rx_poll (struct net_device *dev, int *budget)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	unsigned rx_tail = cp->rx_tail;
 	unsigned rx_work = dev->quota;
 	unsigned rx;
@@ -630,9 +633,13 @@ static irqreturn_t
 cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_instance;
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp;
 	u16 status;
 
+	if (unlikely(dev == NULL))
+		return IRQ_NONE;
+	cp = netdev_priv(dev);
+
 	status = cpr16(IntrStatus);
 	if (!status || (status == 0xFFFF))
 		return IRQ_NONE;
@@ -648,20 +655,23 @@ cp_interrupt (int irq, void *dev_instanc
 	/* close possible race's with dev_close */
 	if (unlikely(!netif_running(dev))) {
 		cpw16(IntrMask, 0);
-		goto out;
+		spin_unlock(&cp->lock);
+		return IRQ_HANDLED;
 	}
 
-	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr)) {
+	if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
 		if (netif_rx_schedule_prep(dev)) {
 			cpw16_f(IntrMask, cp_norx_intr_mask);
 			__netif_rx_schedule(dev);
 		}
-	}
+
 	if (status & (TxOK | TxErr | TxEmpty | SWInt))
 		cp_tx(cp);
 	if (status & LinkChg)
 		mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
 
+	spin_unlock(&cp->lock);
+
 	if (status & PciErr) {
 		u16 pci_status;
 
@@ -672,8 +682,7 @@ cp_interrupt (int irq, void *dev_instanc
 
 		/* TODO: reset hardware */
 	}
-out:
-	spin_unlock(&cp->lock);
+
 	return IRQ_HANDLED;
 }
 
@@ -736,7 +745,7 @@ static void cp_tx (struct cp_private *cp
 
 static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	unsigned entry;
 	u32 eor;
 #if CP_VLAN_TAG_USED
@@ -894,7 +903,7 @@ static int cp_start_xmit (struct sk_buff
 
 static void __cp_set_rx_mode (struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	u32 mc_filter[2];	/* Multicast hash filter */
 	int i, rx_mode;
 	u32 tmp;
@@ -939,7 +948,7 @@ static void __cp_set_rx_mode (struct net
 static void cp_set_rx_mode (struct net_device *dev)
 {
 	unsigned long flags;
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 
 	spin_lock_irqsave (&cp->lock, flags);
 	__cp_set_rx_mode(dev);
@@ -955,35 +964,28 @@ static void __cp_get_stats(struct cp_pri
 
 static struct net_device_stats *cp_get_stats(struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 
 	/* The chip only need report frame silently dropped. */
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
  	if (netif_running(dev) && netif_device_present(dev))
  		__cp_get_stats(cp);
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 
 	return &cp->net_stats;
 }
 
 static void cp_stop_hw (struct cp_private *cp)
 {
-	struct net_device *dev = cp->dev;
-
 	cpw16(IntrStatus, ~(cpr16(IntrStatus)));
 	cpw16_f(IntrMask, 0);
 	cpw8(Cmd, 0);
 	cpw16_f(CpCmd, 0);
-	cpw16(IntrStatus, ~(cpr16(IntrStatus)));
-	synchronize_irq();
-	udelay(10);
+	cpw16_f(IntrStatus, ~(cpr16(IntrStatus)));
 
 	cp->rx_tail = 0;
 	cp->tx_head = cp->tx_tail = 0;
-
-	(void) dev; /* avoid compiler warning when synchronize_irq()
-		     * disappears during !CONFIG_SMP
-		     */
 }
 
 static void cp_reset_hw (struct cp_private *cp)
@@ -1012,6 +1014,7 @@ static inline void cp_start_hw (struct c
 static void cp_init_hw (struct cp_private *cp)
 {
 	struct net_device *dev = cp->dev;
+	dma_addr_t ring_dma;
 
 	cp_reset_hw(cp);
 
@@ -1037,10 +1040,13 @@ static void cp_init_hw (struct cp_privat
 	cpw32_f(HiTxRingAddr, 0);
 	cpw32_f(HiTxRingAddr + 4, 0);
 
-	cpw32_f(RxRingAddr, cp->ring_dma);
-	cpw32_f(RxRingAddr + 4, 0);		/* FIXME: 64-bit PCI */
-	cpw32_f(TxRingAddr, cp->ring_dma + (sizeof(struct cp_desc) * CP_RX_RING_SIZE));
-	cpw32_f(TxRingAddr + 4, 0);		/* FIXME: 64-bit PCI */
+	ring_dma = cp->ring_dma;
+	cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+	cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+	ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+	cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+	cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
 
 	cpw16(MultiIntr, 0);
 
@@ -1154,7 +1160,7 @@ static void cp_free_rings (struct cp_pri
 
 static int cp_open (struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	int rc;
 
 	if (netif_msg_ifup(cp))
@@ -1184,19 +1190,24 @@ err_out_hw:
 
 static int cp_close (struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 
 	if (netif_msg_ifdown(cp))
 		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
 
+	spin_lock_irqsave(&cp->lock, flags);
+
 	netif_stop_queue(dev);
 	netif_carrier_off(dev);
 
-	spin_lock_irq(&cp->lock);
 	cp_stop_hw(cp);
-	spin_unlock_irq(&cp->lock);
 
+	spin_unlock_irqrestore(&cp->lock, flags);
+
+	synchronize_irq();
 	free_irq(dev->irq, dev);
+
 	cp_free_rings(cp);
 	return 0;
 }
@@ -1204,8 +1215,9 @@ static int cp_close (struct net_device *
 #ifdef BROKEN
 static int cp_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	int rc;
+	unsigned long flags;
 
 	/* check for invalid MTU, according to hardware limits */
 	if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
@@ -1218,7 +1230,7 @@ static int cp_change_mtu(struct net_devi
 		return 0;
 	}
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 
 	cp_stop_hw(cp);			/* stop h/w and free rings */
 	cp_clean_rings(cp);
@@ -1229,7 +1241,7 @@ static int cp_change_mtu(struct net_devi
 	rc = cp_init_rings(cp);		/* realloc and restart h/w */
 	cp_start_hw(cp);
 
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 
 	return rc;
 }
@@ -1248,7 +1260,7 @@ static char mii_2_8139_map[8] = {
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 
 	return location < 8 && mii_2_8139_map[location] ?
 	       readw(cp->regs + mii_2_8139_map[location]) : 0;
@@ -1258,7 +1270,7 @@ static int mdio_read(struct net_device *
 static void mdio_write(struct net_device *dev, int phy_id, int location,
 		       int value)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 
 	if (location == 0) {
 		cpw8(Cfg9346, Cfg9346_Unlock);
@@ -1326,7 +1338,7 @@ static void netdev_get_wol (struct cp_pr
 
 static void cp_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 
 	strcpy (info->driver, DRV_NAME);
 	strcpy (info->version, DRV_VERSION);
@@ -1345,55 +1357,57 @@ static int cp_get_stats_count (struct ne
 
 static int cp_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	int rc;
+	unsigned long flags;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 	rc = mii_ethtool_gset(&cp->mii_if, cmd);
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 
 	return rc;
 }
 
 static int cp_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	int rc;
+	unsigned long flags;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 	rc = mii_ethtool_sset(&cp->mii_if, cmd);
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 
 	return rc;
 }
 
 static int cp_nway_reset(struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	return mii_nway_restart(&cp->mii_if);
 }
 
 static u32 cp_get_msglevel(struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	return cp->msg_enable;
 }
 
 static void cp_set_msglevel(struct net_device *dev, u32 value)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	cp->msg_enable = value;
 }
 
 static u32 cp_get_rx_csum(struct net_device *dev)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	return (cpr16(CpCmd) & RxChkSum) ? 1 : 0;
 }
 
 static int cp_set_rx_csum(struct net_device *dev, u32 data)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	u16 cmd = cp->cpcmd, newcmd;
 
 	newcmd = cmd;
@@ -1404,10 +1418,12 @@ static int cp_set_rx_csum(struct net_dev
 		newcmd &= ~RxChkSum;
 
 	if (newcmd != cmd) {
-		spin_lock_irq(&cp->lock);
+		unsigned long flags;
+
+		spin_lock_irqsave(&cp->lock, flags);
 		cp->cpcmd = newcmd;
 		cpw16_f(CpCmd, newcmd);
-		spin_unlock_irq(&cp->lock);
+		spin_unlock_irqrestore(&cp->lock, flags);
 	}
 
 	return 0;
@@ -1416,35 +1432,38 @@ static int cp_set_rx_csum(struct net_dev
 static void cp_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 		        void *p)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 
 	if (regs->len < CP_REGS_SIZE)
 		return /* -EINVAL */;
 
 	regs->version = CP_REGS_VER;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 	memcpy_fromio(p, cp->regs, CP_REGS_SIZE);
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 }
 
 static void cp_get_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 
-	spin_lock_irq (&cp->lock);
+	spin_lock_irqsave (&cp->lock, flags);
 	netdev_get_wol (cp, wol);
-	spin_unlock_irq (&cp->lock);
+	spin_unlock_irqrestore (&cp->lock, flags);
 }
 
 static int cp_set_wol (struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned long flags;
 	int rc;
 
-	spin_lock_irq (&cp->lock);
+	spin_lock_irqsave (&cp->lock, flags);
 	rc = netdev_set_wol (cp, wol);
-	spin_unlock_irq (&cp->lock);
+	spin_unlock_irqrestore (&cp->lock, flags);
 
 	return rc;
 }
@@ -1464,13 +1483,13 @@ static void cp_get_strings (struct net_d
 static void cp_get_ethtool_stats (struct net_device *dev,
 				  struct ethtool_stats *estats, u64 *tmp_stats)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	unsigned int work = 100;
 	int i;
 
 	/* begin NIC statistics dump */
-	cpw32(StatsAddr + 4, 0); /* FIXME: 64-bit PCI */
-	cpw32(StatsAddr, cp->nic_stats_dma | DumpStats);
+	cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
+	cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
 	cpr32(StatsAddr);
 
 	while (work-- > 0) {
@@ -1526,16 +1545,17 @@ static struct ethtool_ops cp_ethtool_ops
 
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 	struct mii_ioctl_data *mii = (struct mii_ioctl_data *) &rq->ifr_data;
 	int rc;
+	unsigned long flags;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_irq(&cp->lock);
+	spin_lock_irqsave(&cp->lock, flags);
 	rc = generic_mii_ioctl(&cp->mii_if, mii, cmd, NULL);
-	spin_unlock_irq(&cp->lock);
+	spin_unlock_irqrestore(&cp->lock, flags);
 	return rc;
 }
 
@@ -1637,7 +1657,9 @@ static int cp_init_one (struct pci_dev *
 	if (!dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(dev);
-	cp = dev->priv;
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	cp = netdev_priv(dev);
 	cp->pdev = pdev;
 	cp->dev = dev;
 	cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
@@ -1662,12 +1684,6 @@ static int cp_init_one (struct pci_dev *
 	if (rc)
 		goto err_out_mwi;
 
-	if (pdev->irq < 2) {
-		rc = -EIO;
-		printk(KERN_ERR PFX "invalid irq (%d) for pci dev %s\n",
-		       pdev->irq, pci_name(pdev));
-		goto err_out_res;
-	}
 	pciaddr = pci_resource_start(pdev, 1);
 	if (!pciaddr) {
 		rc = -EIO;
@@ -1687,19 +1703,20 @@ static int cp_init_one (struct pci_dev *
 	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
 		pci_using_dac = 1;
 	} else {
+		pci_using_dac = 0;
+
 		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
 		if (rc) {
 			printk(KERN_ERR PFX "No usable DMA configuration, "
 			       "aborting.\n");
 			goto err_out_res;
 		}
-		pci_using_dac = 0;
 	}
 
 	cp->cpcmd = (pci_using_dac ? PCIDAC : 0) |
 		    PCIMulRW | RxChkSum | CpRxOn | CpTxOn;
 
-	regs = ioremap_nocache(pciaddr, CP_REGS_SIZE);
+	regs = ioremap(pciaddr, CP_REGS_SIZE);
 	if (!regs) {
 		rc = -EIO;
 		printk(KERN_ERR PFX "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n",
@@ -1740,6 +1757,9 @@ static int cp_init_one (struct pci_dev *
 	dev->vlan_rx_kill_vid = cp_vlan_rx_kill_vid;
 #endif
 
+	if (pci_using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
+
 	dev->irq = pdev->irq;
 
 	rc = register_netdev(dev);
@@ -1774,14 +1794,14 @@ err_out_mwi:
 err_out_disable:
 	pci_disable_device(pdev);
 err_out_free:
-	kfree(dev);
+	free_netdev(dev);
 	return rc;
 }
 
 static void cp_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct cp_private *cp = dev->priv;
+	struct cp_private *cp = netdev_priv(dev);
 
 	if (!dev)
 		BUG();
@@ -1792,7 +1812,7 @@ static void cp_remove_one (struct pci_de
 	pci_clear_mwi(pdev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
-	kfree(dev);
+	free_netdev(dev);
 }
 
 #ifdef CONFIG_PM
@@ -1803,7 +1823,7 @@ static int cp_suspend (struct pci_dev *p
 	unsigned long flags;
 
 	dev = pci_get_drvdata (pdev);
-	cp  = dev->priv;
+	cp  = netdev_priv(dev);
 
 	if (!dev || !netif_running (dev)) return 0;
 
@@ -1832,7 +1852,7 @@ static int cp_resume (struct pci_dev *pd
 	struct cp_private *cp;
 
 	dev = pci_get_drvdata (pdev);
-	cp  = dev->priv;
+	cp  = netdev_priv(dev);
 
 	netif_device_attach (dev);
 	
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/8139too.c linux-2.4.27-rc4/drivers/net/8139too.c
--- linux-2.4.26/drivers/net/8139too.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/8139too.c	2004-07-30 16:24:18.000000000 +0000
@@ -2482,6 +2482,8 @@ static int rtl8139_suspend (struct pci_d
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
+	pci_save_state (pdev, tp->pci_state);
+
 	if (!netif_running (dev))
 		return 0;
 
@@ -2498,7 +2500,6 @@ static int rtl8139_suspend (struct pci_d
 	RTL_W32 (RxMissed, 0);
 
 	pci_set_power_state (pdev, 3);
-	pci_save_state (pdev, tp->pci_state);
 
 	spin_unlock_irqrestore (&tp->lock, flags);
 	return 0;
@@ -2510,9 +2511,9 @@ static int rtl8139_resume (struct pci_de
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct rtl8139_private *tp = dev->priv;
 
+	pci_restore_state (pdev, tp->pci_state);
 	if (!netif_running (dev))
 		return 0;
-	pci_restore_state (pdev, tp->pci_state);
 	pci_set_power_state (pdev, 0);
 	rtl8139_init_ring (dev);
 	rtl8139_hw_start (dev);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/8390.c linux-2.4.27-rc4/drivers/net/8390.c
--- linux-2.4.26/drivers/net/8390.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/8390.c	2004-07-30 16:25:41.000000000 +0000
@@ -1109,7 +1109,7 @@ void NS8390_init(struct net_device *dev,
 	for(i = 0; i < 6; i++) 
 	{
 		outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
-		if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
+		if (ei_debug > 1 && inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
 			printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
 	}
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/Config.in linux-2.4.27-rc4/drivers/net/Config.in
--- linux-2.4.26/drivers/net/Config.in	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/Config.in	2004-07-30 16:29:26.000000000 +0000
@@ -311,6 +311,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; the
    fi
 fi
 
+if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
+   dep_tristate 'IBM PowerPC Virtual Ethernet driver support' CONFIG_IBMVETH $CONFIG_PPC_PSERIES
+fi 
+
 dep_tristate 'PLIP (parallel port) support' CONFIG_PLIP $CONFIG_PARPORT
 
 tristate 'PPP (point-to-point protocol) support' CONFIG_PPP
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/Makefile linux-2.4.27-rc4/drivers/net/Makefile
--- linux-2.4.26/drivers/net/Makefile	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/Makefile	2004-07-30 16:26:58.000000000 +0000
@@ -245,6 +245,8 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o 
 obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
 obj-$(CONFIG_USB_USBNET) += mii.o
 
+obj-$(CONFIG_IBMVETH) += ibmveth.o
+
 ifeq ($(CONFIG_ARCH_ACORN),y)
 mod-subdirs	+= ../acorn/net
 subdir-y	+= ../acorn/net
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/a2065.c linux-2.4.27-rc4/drivers/net/a2065.c
--- linux-2.4.26/drivers/net/a2065.c	2003-06-13 14:51:34.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/a2065.c	2004-07-30 16:29:11.000000000 +0000
@@ -284,6 +284,7 @@ static int lance_rx (struct net_device *
 	struct sk_buff *skb = 0;	/* XXX shut up gcc warnings */
 
 #ifdef TEST_HITS
+	int i;
 	printk ("[");
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		if (i == lp->rx_new)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/aironet4500_core.c linux-2.4.27-rc4/drivers/net/aironet4500_core.c
--- linux-2.4.26/drivers/net/aironet4500_core.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/aironet4500_core.c	2004-07-30 16:24:26.000000000 +0000
@@ -2836,7 +2836,7 @@ char name[] = "ElmerLinux";
  	return 0; 
    final:
    	printk(KERN_ERR "aironet init failed \n");
-   	return NODEV;
+   	return ENODEV;
    	
  };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/amd8111e.c linux-2.4.27-rc4/drivers/net/amd8111e.c
--- linux-2.4.26/drivers/net/amd8111e.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/amd8111e.c	2004-07-30 16:25:27.000000000 +0000
@@ -1,6 +1,6 @@
 
 /* Advanced  Micro Devices Inc. AMD8111E Linux Network Driver 
- * Copyright (C) 2003 Advanced Micro Devices 
+ * Copyright (C) 2004 Advanced Micro Devices 
  *
  * 
  * Copyright 2001,2002 Jeff Garzik <jgarzik@mandrakesoft.com> [ 8139cp.c,tg3.c ]
@@ -55,6 +55,14 @@ Revision History:
 	 4. Dynamic IPG support is disabled by default.
 	3.0.3 06/05/2003
 	 1. Bug fix: Fixed failure to close the interface if SMP is enabled.
+	3.0.4 12/09/2003
+	 1. Added set_mac_address routine for bonding driver support.
+	 2. Tested the driver for bonding support
+	 3. Bug fix: Fixed mismach in actual receive buffer lenth and lenth 
+	    indicated to the h/w.
+	 4. Modified amd8111e_rx() routine to receive all the received packets 
+	    in the first interrupt.
+	 5. Bug fix: Corrected  rx_errors  reported in get_stats() function.  
 
 */
 
@@ -91,9 +99,9 @@ Revision History:
 
 #include "amd8111e.h"
 #define MODULE_NAME	"amd8111e"
-#define MODULE_VERSION	"3.0.3"
+#define MODULE_VERSION	"3.0.4"
 MODULE_AUTHOR("Advanced Micro Devices, Inc.");
-MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.3");
+MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version 3.0.4");
 MODULE_LICENSE("GPL");
 MODULE_PARM(speed_duplex, "1-" __MODULE_STRING (MAX_UNITS) "i");
 MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotitate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
@@ -276,8 +284,10 @@ static inline void amd8111e_set_rx_buff_
 	unsigned int mtu = dev->mtu;
 	
 	if (mtu > ETH_DATA_LEN){
-		/* MTU + ethernet header + FCS + optional VLAN tag */
-		lp->rx_buff_len = mtu + ETH_HLEN + 8;
+		/* MTU + ethernet header + FCS
+		+ optional VLAN tag + skb reserve space 2 */
+
+		lp->rx_buff_len = mtu + ETH_HLEN + 10;
 		lp->options |= OPTION_JUMBO_ENABLE;
 	} else{
 		lp->rx_buff_len = PKT_BUFF_SZ;
@@ -337,7 +347,7 @@ static int amd8111e_init_ring(struct net
 			lp->rx_skbuff[i]->data,lp->rx_buff_len-2, PCI_DMA_FROMDEVICE);
 
 		lp->rx_ring[i].buff_phy_addr = cpu_to_le32(lp->rx_dma_addr[i]);
-		lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len);
+		lp->rx_ring[i].buff_count = cpu_to_le16(lp->rx_buff_len-2);
 		lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
 	}
 
@@ -513,6 +523,9 @@ static void amd8111e_init_hw_default( st
 	void * mmio = lp->mmio;
 
 
+        /* stop the chip */
+	writel(RUN, mmio + CMD0);
+
 	/* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
 	writew( 0x8101, mmio + AUTOPOLL0);
 
@@ -710,7 +723,7 @@ static int amd8111e_rx(struct net_device
 	int rx_index = lp->rx_idx & RX_RING_DR_MOD_MASK;
 	int min_pkt_len, status;
 	int num_rx_pkt = 0;
-	int max_rx_pkt = NUM_RX_BUFFERS/2;
+	int max_rx_pkt = NUM_RX_BUFFERS;
 	short pkt_len;
 #if AMD8111E_VLAN_TAG_USED		
 	short vtag;
@@ -752,14 +765,14 @@ static int amd8111e_rx(struct net_device
 
 		if (pkt_len < min_pkt_len) {
 			lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
-			lp->stats.rx_errors++;
+			lp->drv_rx_errors++;
 			goto err_next_pkt;
 		}
 		if(!(new_skb = dev_alloc_skb(lp->rx_buff_len))){
 			/* if allocation fail, 
 				ignore that pkt and go to next one */
 			lp->rx_ring[rx_index].rx_flags &= RESET_RX_FLAGS;
-			lp->stats.rx_errors++;
+			lp->drv_rx_errors++;
 			goto err_next_pkt;
 		}
 		
@@ -896,12 +909,14 @@ static struct net_device_stats *amd8111e
 	new_stats->tx_bytes = amd8111e_read_mib(mmio, xmt_octets);
 
 	/* stats.rx_errors */
+	/* hw errors + errors driver reported */
 	new_stats->rx_errors = amd8111e_read_mib(mmio, rcv_undersize_pkts)+
 				amd8111e_read_mib(mmio, rcv_fragments)+
 				amd8111e_read_mib(mmio, rcv_jabbers)+
 				amd8111e_read_mib(mmio, rcv_alignment_errors)+
 				amd8111e_read_mib(mmio, rcv_fcs_errors)+
-				amd8111e_read_mib(mmio, rcv_miss_pkts);
+				amd8111e_read_mib(mmio, rcv_miss_pkts)+
+				lp->drv_rx_errors;
 
 	/* stats.tx_errors */
 	new_stats->tx_errors = amd8111e_read_mib(mmio, xmt_underrun_pkts);
@@ -1171,7 +1186,7 @@ static int amd8111e_close(struct net_dev
 
 	spin_unlock_irq(&lp->lock);
 	free_irq(dev->irq, dev);
-
+	
 	/* Update the statistics before closing */
 	amd8111e_get_stats(dev);
 	lp->opened = 0;
@@ -1545,6 +1560,23 @@ static int amd8111e_ioctl(struct net_dev
 	}
 	return -EOPNOTSUPP;
 }
+static int amd8111e_set_mac_address(struct net_device *dev, void *p)
+{
+	struct amd8111e_priv *lp = dev->priv;
+	int i;
+	struct sockaddr *addr = p;
+
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	spin_lock_irq(&lp->lock);
+	/* Setting the MAC address to the device */
+	for(i = 0; i < ETH_ADDR_LEN; i++)
+		writeb( dev->dev_addr[i], lp->mmio + PADR + i ); 
+		
+	spin_unlock_irq(&lp->lock);
+
+	return 0;
+}
+
 /* 
 This function changes the mtu of the device. It restarts the device  to initialize the descriptor with new receive buffers.
 */  
@@ -1875,6 +1907,7 @@ static int __devinit amd8111e_probe_one(
 	dev->stop = amd8111e_close;
 	dev->get_stats = amd8111e_get_stats;
 	dev->set_multicast_list = amd8111e_set_multicast_list;
+	dev->set_mac_address = amd8111e_set_mac_address;
 	dev->do_ioctl = amd8111e_ioctl;
 	dev->change_mtu = amd8111e_change_mtu;
 	dev->irq =pdev->irq;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/amd8111e.h linux-2.4.27-rc4/drivers/net/amd8111e.h
--- linux-2.4.26/drivers/net/amd8111e.h	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/amd8111e.h	2004-07-30 16:30:10.000000000 +0000
@@ -1,6 +1,6 @@
 /*
  * Advanced  Micro Devices Inc. AMD8111E Linux Network Driver 
- * Copyright (C) 2003 Advanced Micro Devices 
+ * Copyright (C) 2004 Advanced Micro Devices 
  *
  * 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
@@ -790,6 +790,7 @@ struct amd8111e_priv{
 #endif	
 	char opened;
 	struct net_device_stats stats;
+	unsigned int drv_rx_errors;
 	struct dev_mc_list* mc_list;
 	struct amd8111e_coalesce_conf coal_conf;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/b44.c linux-2.4.27-rc4/drivers/net/b44.c
--- linux-2.4.26/drivers/net/b44.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/b44.c	2004-07-30 16:28:00.000000000 +0000
@@ -2,6 +2,8 @@
  *
  * Copyright (C) 2002 David S. Miller (davem@redhat.com)
  * Fixed by Pekka Pietikainen (pp@ee.oulu.fi)
+ *
+ * Distribute under GPL.
  */
 
 #include <linux/kernel.h>
@@ -25,8 +27,8 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"0.92"
-#define DRV_MODULE_RELDATE	"Nov 4, 2003"
+#define DRV_MODULE_VERSION	"0.93"
+#define DRV_MODULE_RELDATE	"Mar, 2004"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -83,6 +85,10 @@ static int b44_debug = -1;	/* -1 == use 
 static struct pci_device_id b44_pci_tbl[] = {
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B0,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BCM4401B1,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ }	/* terminate list with empty entry */
 };
 
@@ -90,7 +96,7 @@ MODULE_DEVICE_TABLE(pci, b44_pci_tbl);
 
 static void b44_halt(struct b44 *);
 static void b44_init_rings(struct b44 *);
-static int b44_init_hw(struct b44 *);
+static void b44_init_hw(struct b44 *);
 
 static int b44_wait_bit(struct b44 *bp, unsigned long reg,
 			u32 bit, unsigned long timeout, const int clear)
@@ -1170,11 +1176,10 @@ static int b44_set_mac_addr(struct net_d
  * packet processing.  Invoked with bp->lock held.
  */
 static void __b44_set_rx_mode(struct net_device *);
-static int b44_init_hw(struct b44 *bp)
+static void b44_init_hw(struct b44 *bp)
 {
 	u32 val;
 
-	b44_disable_ints(bp);
 	b44_chip_reset(bp);
 	b44_phy_reset(bp);
 	b44_setup_phy(bp);
@@ -1203,8 +1208,6 @@ static int b44_init_hw(struct b44 *bp)
 
 	val = br32(B44_ENET_CTRL);
 	bw32(B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
-
-	return 0;
 }
 
 static int b44_open(struct net_device *dev)
@@ -1223,9 +1226,7 @@ static int b44_open(struct net_device *d
 	spin_lock_irq(&bp->lock);
 
 	b44_init_rings(bp);
-	err = b44_init_hw(bp);
-	if (err)
-		goto err_out_noinit;
+	b44_init_hw(bp);
 	bp->flags |= B44_FLAG_INIT_COMPLETE;
 
 	spin_unlock_irq(&bp->lock);
@@ -1240,11 +1241,6 @@ static int b44_open(struct net_device *d
 
 	return 0;
 
-err_out_noinit:
-	b44_halt(bp);
-	b44_free_rings(bp);
-	spin_unlock_irq(&bp->lock);
-	free_irq(dev->irq, dev);
 err_out_free:
 	b44_free_consistent(bp);
 	return err;
@@ -1373,7 +1369,7 @@ static void b44_set_rx_mode(struct net_d
 	spin_unlock_irq(&bp->lock);
 }
 
-static int b44_ethtool_ioctl (struct net_device *dev, void *useraddr)
+static int b44_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
 {
 	struct b44 *bp = dev->priv;
 	struct pci_dev *pci_dev = bp->pdev;
@@ -1383,7 +1379,7 @@ static int b44_ethtool_ioctl (struct net
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:{
+	case ETHTOOL_GDRVINFO: {
 		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
 		strcpy (info.driver, DRV_MODULE_NAME);
 		strcpy (info.version, DRV_MODULE_VERSION);
@@ -1616,13 +1612,13 @@ static int b44_ethtool_ioctl (struct net
 
 static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
+	struct mii_ioctl_data __user *data = (struct mii_ioctl_data __user *)&ifr->ifr_data;
 	struct b44 *bp = dev->priv;
 	int err;
 
 	switch (cmd) {
 	case SIOCETHTOOL:
-		return b44_ethtool_ioctl(dev, (void *) ifr->ifr_data);
+		return b44_ethtool_ioctl(dev, (void __user*) ifr->ifr_data);
 
 	case SIOCGMIIPHY:
 		data->phy_id = bp->phy_addr;
@@ -1758,6 +1754,7 @@ static int __devinit b44_init_one(struct
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev,&pdev->dev);
 
 	/* No interesting netdevice features in this card... */
 	dev->features |= 0;
@@ -1884,6 +1881,8 @@ static int b44_resume(struct pci_dev *pd
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct b44 *bp = dev->priv;
 
+	pci_restore_state(pdev, bp->pci_cfg_state);
+
 	if (!netif_running(dev))
 		return 0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/defxx.c linux-2.4.27-rc4/drivers/net/defxx.c
--- linux-2.4.26/drivers/net/defxx.c	2001-12-21 17:41:54.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/defxx.c	2004-07-30 16:24:21.000000000 +0000
@@ -500,7 +500,7 @@ static int __devinit dfx_init_one(struct
 
 static int __init dfx_eisa_init(void)
 {
-	int rc = -NODEV;
+	int rc = -ENODEV;
 	int i;			/* used in for loops */
 	u16 port;		/* temporary I/O (port) address */
 	u32 slot_id;		/* EISA hardware (slot) ID read from adapter */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e100/e100.h linux-2.4.27-rc4/drivers/net/e100/e100.h
--- linux-2.4.26/drivers/net/e100/e100.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e100/e100.h	2004-07-30 16:27:55.000000000 +0000
@@ -434,6 +434,7 @@ struct driver_stats {
 #define D102_REV_ID      12
 #define D102C_REV_ID     13	/* 82550 step C */
 #define D102E_REV_ID     15
+#define D102E_A1_REV_ID  16
 
 /* ############Start of 82555 specific defines################## */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e100/e100_main.c linux-2.4.27-rc4/drivers/net/e100/e100_main.c
--- linux-2.4.26/drivers/net/e100/e100_main.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e100/e100_main.c	2004-07-30 16:25:34.000000000 +0000
@@ -46,7 +46,16 @@
 
 /* Change Log
  * 
- * 2.3.38       12/14/03
+ * 2.3.40       2/13/04
+ * o Updated microcode for D102 rev 15 and rev 16 to include fix
+ *   for TCO issue.  NFS packets would be misinterpreted as TCO packets
+ *   and incorrectly routed to the BMC over SMBus.  The microcode fix
+ *   checks the fragmented IP bit in the NFS/UDP header to distinguish
+ *   between NFS and TCO.
+ * o Bug fix: don't strip MAC header count from Rx byte count.
+ *   Ben Greear (greear@candeltech.com).
+ *
+ * 2.3.38	12/14/03
  * o Added netpoll support.
  * o Added ICH6 device ID support
  * o Moved to 2.6 APIs: pci_name() and free_netdev().
@@ -54,12 +63,6 @@
  *   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>
@@ -132,7 +135,7 @@ static void e100_non_tx_background(unsig
 static inline void e100_tx_skb_free(struct e100_private *bdp, tcb_t *tcb);
 /* Global Data structures and variables */
 char e100_copyright[] __devinitdata = "Copyright (c) 2004 Intel Corporation";
-char e100_driver_version[]="2.3.38-k1";
+char e100_driver_version[]="2.3.43-k1";
 const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver";
 char e100_short_driver_name[] = "e100";
 static int e100nics = 0;
@@ -582,6 +585,7 @@ e100_found1(struct pci_dev *pcid, const 
 	bdp->device = dev;
 
 	pci_set_drvdata(pcid, dev);
+	SET_NETDEV_DEV(dev, &pcid->dev);
 
 	bdp->flags = 0;
 	bdp->ifs_state = 0;
@@ -2062,6 +2066,8 @@ e100_rx_srv(struct e100_private *bdp)
 		else
 			skb_put(skb, (int) data_sz);
 
+		bdp->drv_stats.net_stats.rx_bytes += skb->len;
+
 		/* set the protocol */
 		skb->protocol = eth_type_trans(skb, dev);
 
@@ -2076,8 +2082,6 @@ e100_rx_srv(struct e100_private *bdp)
 			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 {
@@ -2835,6 +2839,11 @@ e100_load_microcode(struct e100_private 
 		  D102_E_CPUSAVER_TIMER_DWORD,
 		  D102_E_CPUSAVER_BUNDLE_DWORD,
 		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
+		{ D102E_A1_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;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e100/e100_ucode.h linux-2.4.27-rc4/drivers/net/e100/e100_ucode.h
--- linux-2.4.26/drivers/net/e100/e100_ucode.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e100/e100_ucode.h	2004-07-30 16:29:39.000000000 +0000
@@ -346,7 +346,7 @@ below), and they each have their own ver
 
 #define     D102_E_RCVBUNDLE_UCODE \
 {\
-0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x1FFF1FFF, 0x1FFF1FFF, \
+0x007D028F, 0x0E4204F9, 0x14ED0C85, 0x14FA14E9, 0x0EF70E36, 0x1FFF1FFF, \
 0x00E014B9, 0x00000000, 0x00000000, 0x00000000, \
 0x00E014BD, 0x00000000, 0x00000000, 0x00000000, \
 0x00E014D5, 0x00000000, 0x00000000, 0x00000000, \
@@ -359,7 +359,26 @@ below), and they each have their own ver
 0x00200600, 0x00E014EE, 0x00000000, 0x00000000, \
 0x0030FF80, 0x00940E46, 0x00038200, 0x00102000, \
 0x00E00E43, 0x00000000, 0x00000000, 0x00000000, \
-0x00300006, 0x00E014FB, 0x00000000, 0x00000000  \
+0x00300006, 0x00E014FB, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00906E41, 0x00800E3C, 0x00E00E39, 0x00000000, \
+0x00906EFD, 0x00900EFD, 0x00E00EF8, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+0x00000000, 0x00000000, 0x00000000, 0x00000000, \
 }
 
 #endif /* _E100_UCODE_H_ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000.h linux-2.4.27-rc4/drivers/net/e1000/e1000.h
--- linux-2.4.26/drivers/net/e1000/e1000.h	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000.h	2004-07-30 16:27:29.000000000 +0000
@@ -70,6 +70,7 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
+#include <linux/moduleparam.h>
 
 #define BAR_0		0
 #define BAR_1		1
@@ -90,6 +91,12 @@ struct e1000_adapter;
 
 #define E1000_ERR(args...) printk(KERN_ERR "e1000: " args)
 
+#define PFX "e1000: "
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+	(void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
+	printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
+		__FUNCTION__ , ## args))
+
 #define E1000_MAX_INTR 10
 
 /* How many descriptors for TX and RX ? */
@@ -113,7 +120,7 @@ struct e1000_adapter;
 #define E1000_SMARTSPEED_MAX       15
 
 /* Packet Buffer allocations */
-#define E1000_TX_FIFO_SIZE_SHIFT 0xA
+#define E1000_PBA_BYTES_SHIFT 0xA
 #define E1000_TX_HEAD_ADDR_SHIFT 7
 #define E1000_PBA_TX_MASK 0xFFFF0000
 
@@ -190,6 +197,7 @@ struct e1000_adapter {
 	uint32_t part_num;
 	uint32_t wol;
 	uint32_t smartspeed;
+	uint32_t en_mng_pt;
 	uint16_t link_speed;
 	uint16_t link_duplex;
 	spinlock_t stats_lock;
@@ -246,5 +254,6 @@ struct e1000_adapter {
 
 
 	uint32_t pci_state[16];
+	int msg_enable;
 };
 #endif /* _E1000_H_ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000_ethtool.c linux-2.4.27-rc4/drivers/net/e1000/e1000_ethtool.c
--- linux-2.4.26/drivers/net/e1000/e1000_ethtool.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000_ethtool.c	2004-07-30 16:29:45.000000000 +0000
@@ -53,7 +53,7 @@ struct e1000_stats {
 
 #define E1000_STAT(m) sizeof(((struct e1000_adapter *)0)->m), \
 		      offsetof(struct e1000_adapter, m)
-static struct e1000_stats e1000_gstrings_stats[] = {
+static const struct e1000_stats e1000_gstrings_stats[] = {
 	{ "rx_packets", E1000_STAT(net_stats.rx_packets) },
 	{ "tx_packets", E1000_STAT(net_stats.tx_packets) },
 	{ "rx_bytes", E1000_STAT(net_stats.rx_bytes) },
@@ -89,7 +89,8 @@ static struct e1000_stats e1000_gstrings
 	{ "tx_flow_control_xon", E1000_STAT(stats.xontxc) },
 	{ "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) },
 	{ "rx_csum_offload_good", E1000_STAT(hw_csum_good) },
-	{ "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }
+        { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) },
+	{ "rx_long_byte_count", E1000_STAT(stats.gorcl) }
 };
 #define E1000_STATS_LEN	\
 	sizeof(e1000_gstrings_stats) / sizeof(struct e1000_stats)
@@ -100,9 +101,10 @@ static char e1000_gstrings_test[][ETH_GS
 };
 #define E1000_TEST_LEN sizeof(e1000_gstrings_test) / ETH_GSTRING_LEN
 
-static void
-e1000_ethtool_gset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
+static int
+e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
 
 	if(hw->media_type == e1000_media_type_copper) {
@@ -169,11 +171,13 @@ e1000_ethtool_gset(struct e1000_adapter 
 	}
 
 	ecmd->autoneg = (hw->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
+	return 0;
 }
 
 static int
-e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd)
+e1000_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
 
 	if(ecmd->autoneg == AUTONEG_ENABLE) {
@@ -195,42 +199,41 @@ e1000_ethtool_sset(struct e1000_adapter 
 	return 0;
 }
 
-static int
-e1000_ethtool_gpause(struct e1000_adapter *adapter,
-                     struct ethtool_pauseparam *epause)
+static void 
+e1000_get_pauseparam(struct net_device *netdev,
+                    struct ethtool_pauseparam *pause)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
-	
-	epause->autoneg = 
+	pause->autoneg = 
 		(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
 	
 	if(hw->fc == e1000_fc_rx_pause)
-		epause->rx_pause = 1;
+		pause->rx_pause = 1;
 	else if(hw->fc == e1000_fc_tx_pause)
-		epause->tx_pause = 1;
+		pause->tx_pause = 1;
 	else if(hw->fc == e1000_fc_full) {
-		epause->rx_pause = 1;
-		epause->tx_pause = 1;
+		pause->rx_pause = 1;
+		pause->tx_pause = 1;
 	}
-	
-	return 0;
 }
 
-static int
-e1000_ethtool_spause(struct e1000_adapter *adapter,
-                     struct ethtool_pauseparam *epause)
+static int 
+e1000_set_pauseparam(struct net_device *netdev,
+                    struct ethtool_pauseparam *pause)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
 	
-	adapter->fc_autoneg = epause->autoneg;
+	adapter->fc_autoneg = pause->autoneg;
 
-	if(epause->rx_pause && epause->tx_pause)
+	if(pause->rx_pause && pause->tx_pause)
 		hw->fc = e1000_fc_full;
-	else if(epause->rx_pause && !epause->tx_pause)
+	else if(pause->rx_pause && !pause->tx_pause)
 		hw->fc = e1000_fc_rx_pause;
-	else if(!epause->rx_pause && epause->tx_pause)
+	else if(!pause->rx_pause && pause->tx_pause)
 		hw->fc = e1000_fc_tx_pause;
-	else if(!epause->rx_pause && !epause->tx_pause)
+	else if(!pause->rx_pause && !pause->tx_pause)
 		hw->fc = e1000_fc_none;
 
 	hw->original_fc = hw->fc;
@@ -248,28 +251,101 @@ e1000_ethtool_spause(struct e1000_adapte
 	return 0;
 }
 
+static uint32_t
+e1000_get_rx_csum(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	return adapter->rx_csum;
+}
+
+static int
+e1000_set_rx_csum(struct net_device *netdev, uint32_t data)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	adapter->rx_csum = data;
+
+	if(netif_running(netdev)) {
+		e1000_down(adapter);
+		e1000_up(adapter);
+	} else
+		e1000_reset(adapter);
+	return 0;
+}
+
+static uint32_t
+e1000_get_tx_csum(struct net_device *netdev)
+{
+	return (netdev->features & NETIF_F_HW_CSUM) != 0;
+}
+
+static int
+e1000_set_tx_csum(struct net_device *netdev, uint32_t data)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+
+	if(adapter->hw.mac_type < e1000_82543) {
+		if (!data)
+			return -EINVAL;
+		return 0;
+	}
+
+	if (data)
+		netdev->features |= NETIF_F_HW_CSUM;
+	else
+		netdev->features &= ~NETIF_F_HW_CSUM;
+
+	return 0;
+}
+
+#ifdef NETIF_F_TSO
+static int
+e1000_set_tso(struct net_device *netdev, uint32_t data)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	if ((adapter->hw.mac_type < e1000_82544) ||
+	    (adapter->hw.mac_type == e1000_82547)) 
+		return data ? -EINVAL : 0;
+
+	if (data)
+		netdev->features |= NETIF_F_TSO;
+	else
+		netdev->features &= ~NETIF_F_TSO;
+	return 0;
+} 
+#endif /* NETIF_F_TSO */
+
+static uint32_t
+e1000_get_msglevel(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	return adapter->msg_enable;
+}
+
 static void
-e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter,
-                       struct ethtool_drvinfo *drvinfo)
+e1000_set_msglevel(struct net_device *netdev, uint32_t data)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	adapter->msg_enable = data;
+}
+
+static int 
+e1000_get_regs_len(struct net_device *netdev)
 {
-	strncpy(drvinfo->driver,  e1000_driver_name, 32);
-	strncpy(drvinfo->version, e1000_driver_version, 32);
-	strncpy(drvinfo->fw_version, "N/A", 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
-	drvinfo->n_stats = E1000_STATS_LEN;
-	drvinfo->testinfo_len = E1000_TEST_LEN;
 #define E1000_REGS_LEN 32
-	drvinfo->regdump_len  = E1000_REGS_LEN * sizeof(uint32_t);
-	drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2;
+	return E1000_REGS_LEN * sizeof(uint32_t);
 }
 
 static void
-e1000_ethtool_gregs(struct e1000_adapter *adapter,
-                    struct ethtool_regs *regs, uint32_t *regs_buff)
+e1000_get_regs(struct net_device *netdev,
+                    struct ethtool_regs *regs, void *p)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
+	uint32_t *regs_buff = p;
 	uint16_t phy_data;
 
+	memset(p, 0, E1000_REGS_LEN * sizeof(uint32_t));
+
 	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;
 
 	regs_buff[0]  = E1000_READ_REG(hw, CTRL);
@@ -342,59 +418,72 @@ e1000_ethtool_gregs(struct e1000_adapter
 	e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
 	regs_buff[24] = (uint32_t)phy_data;  /* phy local receiver status */
 	regs_buff[25] = regs_buff[24];  /* phy remote receiver status */
+}
 
-	return;
+static int
+e1000_get_eeprom_len(struct net_device *netdev)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	return adapter->hw.eeprom.word_size * 2;
 }
 
 static int
-e1000_ethtool_geeprom(struct e1000_adapter *adapter,
-                      struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff)
+e1000_get_eeprom(struct net_device *netdev,
+                      struct ethtool_eeprom *eeprom, uint8_t *bytes)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
+	uint16_t *eeprom_buff;
 	int first_word, last_word;
 	int ret_val = 0;
+	uint16_t i;
 
-	if(eeprom->len == 0) {
-		ret_val = -EINVAL;
-		goto geeprom_error;
-	}
+	if(eeprom->len == 0) 
+		return -EINVAL;
 
 	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
 
-	if(eeprom->offset > eeprom->offset + eeprom->len) {
-		ret_val = -EINVAL;
-		goto geeprom_error;
-	}
-
-	if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2))
-		eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset);
-
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 
+	eeprom_buff = kmalloc(sizeof(uint16_t) * 
+			(last_word - first_word + 1), GFP_KERNEL);
+	if (!eeprom_buff)
+		return -ENOMEM;
+
 	if(hw->eeprom.type == e1000_eeprom_spi)
 		ret_val = e1000_read_eeprom(hw, first_word,
 					    last_word - first_word + 1,
 					    eeprom_buff);
 	else {
-		uint16_t i;
 		for (i = 0; i < last_word - first_word + 1; i++)
 			if((ret_val = e1000_read_eeprom(hw, first_word + i, 1,
 							&eeprom_buff[i])))
 				break;
 	}
-geeprom_error:
+
+	/* Device's eeprom is always little-endian, word addressable */
+	for (i = 0; i < last_word - first_word + 1; i++)
+		le16_to_cpus(&eeprom_buff[i]);
+
+
+	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset%2), 
+				eeprom->len);
+	kfree(eeprom_buff);
+
 	return ret_val;
 }
 
 static int
-e1000_ethtool_seeprom(struct e1000_adapter *adapter,
-                      struct ethtool_eeprom *eeprom, void *user_data)
+e1000_set_eeprom(struct net_device *netdev,
+                      struct ethtool_eeprom *eeprom, uint8_t *bytes)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
 	uint16_t *eeprom_buff;
 	void *ptr;
 	int max_len, first_word, last_word, ret_val = 0;
+	uint16_t i;
 
 	if(eeprom->len == 0)
 		return -EOPNOTSUPP;
@@ -404,9 +493,6 @@ e1000_ethtool_seeprom(struct e1000_adapt
 
 	max_len = hw->eeprom.word_size * 2;
 
-	if((eeprom->offset + eeprom->len) > max_len)
-		eeprom->len = (max_len - eeprom->offset);
-
 	first_word = eeprom->offset >> 1;
 	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
 	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
@@ -428,10 +514,14 @@ e1000_ethtool_seeprom(struct e1000_adapt
 		ret_val = e1000_read_eeprom(hw, last_word, 1,
 		                  &eeprom_buff[last_word - first_word]);
 	}
-	if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) {
-		ret_val = -EFAULT;
-		goto seeprom_error;
-	}
+
+	/* Device's eeprom is always little-endian, word addressable */
+	for (i = 0; i < last_word - first_word + 1; i++)
+		le16_to_cpus(&eeprom_buff[i]);
+
+	memcpy(ptr, bytes, eeprom->len);
+	for (i = 0; i < last_word - first_word + 1; i++)
+		eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]);
 
 	ret_val = e1000_write_eeprom(hw, first_word,
 				     last_word - first_word + 1, eeprom_buff);
@@ -440,11 +530,107 @@ e1000_ethtool_seeprom(struct e1000_adapt
 	if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG)
 		e1000_update_eeprom_checksum(hw);
 
-seeprom_error:
 	kfree(eeprom_buff);
 	return ret_val;
 }
 
+static void
+e1000_get_drvinfo(struct net_device *netdev,
+                       struct ethtool_drvinfo *drvinfo)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+
+	strncpy(drvinfo->driver,  e1000_driver_name, 32);
+	strncpy(drvinfo->version, e1000_driver_version, 32);
+	strncpy(drvinfo->fw_version, "N/A", 32);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	drvinfo->n_stats = E1000_STATS_LEN;
+	drvinfo->testinfo_len = E1000_TEST_LEN;
+	drvinfo->regdump_len = e1000_get_regs_len(netdev);
+	drvinfo->eedump_len = e1000_get_eeprom_len(netdev);
+}
+
+static void
+e1000_get_ringparam(struct net_device *netdev,
+                    struct ethtool_ringparam *ring)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	e1000_mac_type mac_type = adapter->hw.mac_type;
+	struct e1000_desc_ring *txdr = &adapter->tx_ring;
+	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+
+	ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD :
+		E1000_MAX_82544_RXD;
+	ring->tx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_TXD :
+		E1000_MAX_82544_TXD;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->rx_pending = rxdr->count;
+	ring->tx_pending = txdr->count;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+}
+
+static int 
+e1000_set_ringparam(struct net_device *netdev,
+                    struct ethtool_ringparam *ring)
+{
+	int err;
+	struct e1000_adapter *adapter = netdev->priv;
+	e1000_mac_type mac_type = adapter->hw.mac_type;
+	struct e1000_desc_ring *txdr = &adapter->tx_ring;
+	struct e1000_desc_ring *rxdr = &adapter->rx_ring;
+	struct e1000_desc_ring tx_old, tx_new;
+	struct e1000_desc_ring rx_old, rx_new;
+
+	tx_old = adapter->tx_ring;
+	rx_old = adapter->rx_ring;
+	
+	if(netif_running(adapter->netdev))
+		e1000_down(adapter);
+
+	rxdr->count = max(ring->rx_pending,(uint32_t)E1000_MIN_RXD);
+	rxdr->count = min(rxdr->count,(uint32_t)(mac_type < e1000_82544 ?
+		E1000_MAX_RXD : E1000_MAX_82544_RXD));
+	E1000_ROUNDUP(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE); 
+
+	txdr->count = max(ring->tx_pending,(uint32_t)E1000_MIN_TXD);
+	txdr->count = min(txdr->count,(uint32_t)(mac_type < e1000_82544 ?
+		E1000_MAX_TXD : E1000_MAX_82544_TXD));
+	E1000_ROUNDUP(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); 
+
+	if(netif_running(adapter->netdev)) {
+		/* try to get new resources before deleting old */
+		if((err = e1000_setup_rx_resources(adapter)))
+			goto err_setup_rx;
+		if((err = e1000_setup_tx_resources(adapter)))
+			goto err_setup_tx;
+
+		/* save the new, restore the old in order to free it,
+		 * then restore the new back again */	
+	
+		rx_new = adapter->rx_ring;
+		tx_new = adapter->tx_ring;
+		adapter->rx_ring = rx_old;
+		adapter->tx_ring = tx_old;
+		e1000_free_rx_resources(adapter);
+		e1000_free_tx_resources(adapter);
+		adapter->rx_ring = rx_new;
+		adapter->tx_ring = tx_new;
+		if((err = e1000_up(adapter)))
+			return err;
+	}
+	return 0;
+err_setup_tx:
+	e1000_free_rx_resources(adapter);
+err_setup_rx:
+	adapter->rx_ring = rx_old;
+	adapter->tx_ring = tx_old;
+	e1000_up(adapter);
+	return err;
+}
+
+
 #define REG_PATTERN_TEST(R, M, W)                                              \
 {                                                                              \
 	uint32_t pat, value;                                                   \
@@ -535,6 +721,7 @@ e1000_reg_test(struct e1000_adapter *ada
 	for(i = 0; i < E1000_MC_TBL_SIZE; i++)
 		REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF);
 
+	*data = 0;
 	return 0;
 }
 
@@ -846,8 +1033,6 @@ e1000_phy_disable_receiver(struct e1000_
 	e1000_write_phy_reg(&adapter->hw, 30, 0x8FFC);
 	e1000_write_phy_reg(&adapter->hw, 29, 0x001A);
 	e1000_write_phy_reg(&adapter->hw, 30, 0x8FF0);
-
-	return;
 }
 
 static void
@@ -1164,15 +1349,27 @@ e1000_link_test(struct e1000_adapter *ad
 	return *data;
 }
 
-static int
-e1000_ethtool_test(struct e1000_adapter *adapter,
+static int 
+e1000_diag_test_count(struct net_device *netdev)
+{
+	return E1000_TEST_LEN;
+}
+
+static void
+e1000_diag_test(struct net_device *netdev, 
 		   struct ethtool_test *eth_test, uint64_t *data)
 {
-	boolean_t if_running = netif_running(adapter->netdev);
+	struct e1000_adapter *adapter = netdev->priv;
+	boolean_t if_running = netif_running(netdev);
 
 	if(eth_test->flags == ETH_TEST_FL_OFFLINE) {
 		/* Offline tests */
 
+		/* save speed, duplex, autoneg settings */
+		uint16_t autoneg_advertised = adapter->hw.autoneg_advertised;
+    		uint8_t forced_speed_duplex = adapter->hw.forced_speed_duplex;
+		uint8_t autoneg = adapter->hw.autoneg;
+
 		/* Link test performed before hardware reset so autoneg doesn't
 		 * interfere with test result */
 		if(e1000_link_test(adapter, &data[4]))
@@ -1198,6 +1395,10 @@ e1000_ethtool_test(struct e1000_adapter 
 		if(e1000_loopback_test(adapter, &data[3]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
+		/* restore Autoneg/speed/duplex settings */
+		adapter->hw.autoneg_advertised = autoneg_advertised;
+    		adapter->hw.forced_speed_duplex = forced_speed_duplex;
+    		adapter->hw.autoneg = autoneg;
 		e1000_reset(adapter);
 		if(if_running)
 			e1000_up(adapter);
@@ -1212,12 +1413,12 @@ e1000_ethtool_test(struct e1000_adapter 
 		data[2] = 0;
 		data[3] = 0;
 	}
-	return 0;
 }
 
 static void
-e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+e1000_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
 
 	switch(adapter->hw.device_id) {
@@ -1257,8 +1458,9 @@ e1000_ethtool_gwol(struct e1000_adapter 
 }
 
 static int
-e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol)
+e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
+	struct e1000_adapter *adapter = netdev->priv;
 	struct e1000_hw *hw = &adapter->hw;
 
 	switch(adapter->hw.device_id) {
@@ -1294,7 +1496,6 @@ e1000_ethtool_swol(struct e1000_adapter 
 	return 0;
 }
 
-
 /* toggle LED 4 times per second = 2 "blinks" per second */
 #define E1000_ID_INTERVAL	(HZ/4)
 
@@ -1315,8 +1516,13 @@ e1000_led_blink_callback(unsigned long d
 }
 
 static int
-e1000_ethtool_led_blink(struct e1000_adapter *adapter, struct ethtool_value *id)
+e1000_phys_id(struct net_device *netdev, uint32_t data)
 {
+	struct e1000_adapter *adapter = netdev->priv;
+
+	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
+
 	if(!adapter->blink_timer.function) {
 		init_timer(&adapter->blink_timer);
 		adapter->blink_timer.function = e1000_led_blink_callback;
@@ -1327,11 +1533,8 @@ e1000_ethtool_led_blink(struct e1000_ada
 	mod_timer(&adapter->blink_timer, jiffies);
 
 	set_current_state(TASK_INTERRUPTIBLE);
-	if(id->data)
-		schedule_timeout(id->data * HZ);
-	else
-		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
 
+	schedule_timeout(data * HZ);
 	del_timer_sync(&adapter->blink_timer);
 	e1000_led_off(&adapter->hw);
 	clear_bit(E1000_LED_ON, &adapter->led_status);
@@ -1340,329 +1543,96 @@ e1000_ethtool_led_blink(struct e1000_ada
 	return 0;
 }
 
-int
-e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
+static int
+e1000_nway_reset(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev->priv;
-	void *addr = ifr->ifr_data;
-	uint32_t cmd;
-
-	if(get_user(cmd, (uint32_t *) addr))
-		return -EFAULT;
-
-	switch(cmd) {
-	case ETHTOOL_GSET: {
-		struct ethtool_cmd ecmd = {ETHTOOL_GSET};
-		e1000_ethtool_gset(adapter, &ecmd);
-		if(copy_to_user(addr, &ecmd, sizeof(ecmd)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SSET: {
-		struct ethtool_cmd ecmd;
-		if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
-			return -EFAULT;
-		return e1000_ethtool_sset(adapter, &ecmd);
-	}
-	case ETHTOOL_GDRVINFO: {
-		struct ethtool_drvinfo drvinfo = {ETHTOOL_GDRVINFO};
-		e1000_ethtool_gdrvinfo(adapter, &drvinfo);
-		if(copy_to_user(addr, &drvinfo, sizeof(drvinfo)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GSTRINGS: {
-		struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
-		char *strings = NULL;
-		int err = 0;
-
-		if(copy_from_user(&gstrings, addr, sizeof(gstrings)))
-			return -EFAULT;
-		switch(gstrings.string_set) {
-		case ETH_SS_TEST:
-			gstrings.len = E1000_TEST_LEN;
-			strings = kmalloc(E1000_TEST_LEN * ETH_GSTRING_LEN,
-					  GFP_KERNEL);
-			if(!strings)
-				return -ENOMEM;
-			memcpy(strings, e1000_gstrings_test, E1000_TEST_LEN *
-			       ETH_GSTRING_LEN);
-			break;
-		case ETH_SS_STATS: {
-			int i;
-			gstrings.len = E1000_STATS_LEN;
-			strings = kmalloc(E1000_STATS_LEN * ETH_GSTRING_LEN,
-					  GFP_KERNEL);
-			if(!strings)
-				return -ENOMEM;
-			for(i=0; i < E1000_STATS_LEN; i++) {
-				memcpy(&strings[i * ETH_GSTRING_LEN],
-				       e1000_gstrings_stats[i].stat_string,
-				       ETH_GSTRING_LEN);
-			}
-			break;
-		}
-		default:
-			return -EOPNOTSUPP;
-		}
-		if(copy_to_user(addr, &gstrings, sizeof(gstrings)))
-			err = -EFAULT;
-		addr += offsetof(struct ethtool_gstrings, data);
-		if(!err && copy_to_user(addr, strings,
-		   gstrings.len * ETH_GSTRING_LEN))
-			err = -EFAULT;
-
-		kfree(strings);
-		return err;
-	}
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs regs = {ETHTOOL_GREGS};
-		uint32_t regs_buff[E1000_REGS_LEN];
-
-		if(copy_from_user(&regs, addr, sizeof(regs)))
-			return -EFAULT;
-		e1000_ethtool_gregs(adapter, &regs, regs_buff);
-		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;
-	}
-	case ETHTOOL_NWAY_RST: {
-		if(netif_running(netdev)) {
-			e1000_down(adapter);
-			e1000_up(adapter);
-		}
-		return 0;
-	}
-	case ETHTOOL_PHYS_ID: {
-		struct ethtool_value id;
-		if(copy_from_user(&id, addr, sizeof(id)))
-			return -EFAULT;
-		return e1000_ethtool_led_blink(adapter, &id);
-	}
-	case ETHTOOL_GLINK: {
-		struct ethtool_value link = {ETHTOOL_GLINK};
-		link.data = netif_carrier_ok(netdev);
-		if(copy_to_user(addr, &link, sizeof(link)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_GWOL: {
-		struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
-		e1000_ethtool_gwol(adapter, &wol);
-		if(copy_to_user(addr, &wol, sizeof(wol)) != 0)
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SWOL: {
-		struct ethtool_wolinfo wol;
-		if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
-			return -EFAULT;
-		return e1000_ethtool_swol(adapter, &wol);
-	}
-	case ETHTOOL_GEEPROM: {
-		struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM};
-		struct e1000_hw *hw = &adapter->hw;
-		uint16_t *eeprom_buff;
-		void *ptr;
-		int err = 0;
-
-		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
-			return -EFAULT;
-
-		eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL);
-
-		if(!eeprom_buff)
-			return -ENOMEM;
-
-		if((err = e1000_ethtool_geeprom(adapter, &eeprom,
-						eeprom_buff)))
-			goto err_geeprom_ioctl;
-
-		if(copy_to_user(addr, &eeprom, sizeof(eeprom))) {
-			err = -EFAULT;
-			goto err_geeprom_ioctl;
-		}
-
-		addr += offsetof(struct ethtool_eeprom, data);
-		ptr = ((void *)eeprom_buff) + (eeprom.offset & 1);
-
-		if(copy_to_user(addr, ptr, eeprom.len))
-			err = -EFAULT;
-
-err_geeprom_ioctl:
-		kfree(eeprom_buff);
-		return err;
-	}
-	case ETHTOOL_SEEPROM: {
-		struct ethtool_eeprom eeprom;
-
-		if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
-			return -EFAULT;
-
-		addr += offsetof(struct ethtool_eeprom, data);
-		return e1000_ethtool_seeprom(adapter, &eeprom, addr);
-	}
-	case ETHTOOL_GPAUSEPARAM: {
-		struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM};
-		e1000_ethtool_gpause(adapter, &epause);
-		if(copy_to_user(addr, &epause, sizeof(epause)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SPAUSEPARAM: {
-		struct ethtool_pauseparam epause;
-		if(copy_from_user(&epause, addr, sizeof(epause)))
-			return -EFAULT;
-		return e1000_ethtool_spause(adapter, &epause);
-	}
-	case ETHTOOL_GSTATS: {
-		struct {
-			struct ethtool_stats eth_stats;
-			uint64_t data[E1000_STATS_LEN];
-		} stats = { {ETHTOOL_GSTATS, E1000_STATS_LEN} };
-		int i;
-
-		e1000_update_stats(adapter);
-		for(i = 0; i < E1000_STATS_LEN; i++)
-			stats.data[i] = (e1000_gstrings_stats[i].sizeof_stat ==
-					sizeof(uint64_t)) ?
-				*(uint64_t *)((char *)adapter +
-					e1000_gstrings_stats[i].stat_offset) :
-				*(uint32_t *)((char *)adapter +
-					e1000_gstrings_stats[i].stat_offset);
-		if(copy_to_user(addr, &stats, sizeof(stats)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_TEST: {
-		struct {
-			struct ethtool_test eth_test;
-			uint64_t data[E1000_TEST_LEN];
-		} test = { {ETHTOOL_TEST} };
-		int err;
-
-		if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
-			return -EFAULT;
-
-		test.eth_test.len = E1000_TEST_LEN;
-
-		if((err = e1000_ethtool_test(adapter, &test.eth_test,
-					     test.data)))
-			return err;
-
-		if(copy_to_user(addr, &test, sizeof(test)) != 0)
-			return -EFAULT;
-		return 0;
+	if(netif_running(netdev)) {
+		e1000_down(adapter);
+		e1000_up(adapter);
 	}
-	case ETHTOOL_GRXCSUM: {
-		struct ethtool_value edata = { ETHTOOL_GRXCSUM };
+	return 0;
+}
 
-		edata.data = adapter->rx_csum;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_SRXCSUM: {
-		struct ethtool_value edata;
+static int 
+e1000_get_stats_count(struct net_device *netdev)
+{
+	return E1000_STATS_LEN;
+}
 
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
-		adapter->rx_csum = edata.data;
-		if(netif_running(netdev)) {
-			e1000_down(adapter);
-			e1000_up(adapter);
-		} else
-			e1000_reset(adapter);
-		return 0;
-	}
-	case ETHTOOL_GTXCSUM: {
-		struct ethtool_value edata = { ETHTOOL_GTXCSUM };
+static void 
+e1000_get_ethtool_stats(struct net_device *netdev, 
+		struct ethtool_stats *stats, uint64_t *data)
+{
+	struct e1000_adapter *adapter = netdev->priv;
+	int i;
 
-		edata.data =
-			(netdev->features & NETIF_F_HW_CSUM) != 0;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
+	e1000_update_stats(adapter);
+	for(i = 0; i < E1000_STATS_LEN; i++) {
+		char *p = (char *)adapter+e1000_gstrings_stats[i].stat_offset;	
+		data[i] = (e1000_gstrings_stats[i].sizeof_stat == sizeof(uint64_t)) 
+			? *(uint64_t *)p : *(uint32_t *)p;
 	}
-	case ETHTOOL_STXCSUM: {
-		struct ethtool_value edata;
+}
 
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
+static void 
+e1000_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+{
+	int i;
 
-		if(adapter->hw.mac_type < e1000_82543) {
-			if (edata.data != 0)
-				return -EINVAL;
-			return 0;
+	switch(stringset) {
+	case ETH_SS_TEST:
+		memcpy(data, *e1000_gstrings_test, 
+			E1000_TEST_LEN*ETH_GSTRING_LEN);
+		break;
+	case ETH_SS_STATS:
+		for (i=0; i < E1000_STATS_LEN; i++) {
+			memcpy(data + i * ETH_GSTRING_LEN, 
+			e1000_gstrings_stats[i].stat_string,
+			ETH_GSTRING_LEN);
 		}
-
-		if (edata.data)
-			netdev->features |= NETIF_F_HW_CSUM;
-		else
-			netdev->features &= ~NETIF_F_HW_CSUM;
-
-		return 0;
-	}
-	case ETHTOOL_GSG: {
-		struct ethtool_value edata = { ETHTOOL_GSG };
-
-		edata.data =
-			(netdev->features & NETIF_F_SG) != 0;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
+		break;
 	}
-	case ETHTOOL_SSG: {
-		struct ethtool_value edata;
-
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
-
-		if (edata.data)
-			netdev->features |= NETIF_F_SG;
-		else
-			netdev->features &= ~NETIF_F_SG;
+}
 
-		return 0;
-	}
+struct ethtool_ops e1000_ethtool_ops = {
+	.get_settings           = e1000_get_settings,
+	.set_settings           = e1000_set_settings,
+	.get_drvinfo            = e1000_get_drvinfo,
+	.get_regs_len           = e1000_get_regs_len,
+	.get_regs               = e1000_get_regs,
+	.get_wol                = e1000_get_wol,
+	.set_wol                = e1000_set_wol,
+	.get_msglevel	        = e1000_get_msglevel,
+	.set_msglevel	        = e1000_set_msglevel,
+	.nway_reset             = e1000_nway_reset,
+	.get_link               = ethtool_op_get_link,
+	.get_eeprom_len         = e1000_get_eeprom_len,
+	.get_eeprom             = e1000_get_eeprom,
+	.set_eeprom             = e1000_set_eeprom,
+	.get_ringparam          = e1000_get_ringparam,
+	.set_ringparam          = e1000_set_ringparam,
+	.get_pauseparam		= e1000_get_pauseparam,
+	.set_pauseparam		= e1000_set_pauseparam,
+	.get_rx_csum		= e1000_get_rx_csum,
+	.set_rx_csum		= e1000_set_rx_csum,
+	.get_tx_csum		= e1000_get_tx_csum,
+	.set_tx_csum		= e1000_set_tx_csum,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= ethtool_op_set_sg,
 #ifdef NETIF_F_TSO
-	case ETHTOOL_GTSO: {
-		struct ethtool_value edata = { ETHTOOL_GTSO };
-
-		edata.data = (netdev->features & NETIF_F_TSO) != 0;
-		if (copy_to_user(addr, &edata, sizeof(edata)))
-			return -EFAULT;
-		return 0;
-	}
-	case ETHTOOL_STSO: {
-		struct ethtool_value edata;
-
-		if (copy_from_user(&edata, addr, sizeof(edata)))
-			return -EFAULT;
-
-		if ((adapter->hw.mac_type < e1000_82544) ||
-		    (adapter->hw.mac_type == e1000_82547)) {
-			if (edata.data != 0)
-				return -EINVAL;
-			return 0;
-		}
-
-		if (edata.data)
-			netdev->features |= NETIF_F_TSO;
-		else
-			netdev->features &= ~NETIF_F_TSO;
-
-		return 0;
-	}
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= e1000_set_tso,
 #endif
-	default:
-		return -EOPNOTSUPP;
-	}
-}
-
+	.self_test_count        = e1000_diag_test_count,
+	.self_test              = e1000_diag_test,
+	.get_strings            = e1000_get_strings,
+	.phys_id                = e1000_phys_id,
+	.get_stats_count        = e1000_get_stats_count,
+	.get_ethtool_stats      = e1000_get_ethtool_stats,
+};
 
+void set_ethtool_ops(struct net_device *netdev)
+{
+	SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops);
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000_hw.c linux-2.4.27-rc4/drivers/net/e1000/e1000_hw.c
--- linux-2.4.26/drivers/net/e1000/e1000_hw.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000_hw.c	2004-07-30 16:29:47.000000000 +0000
@@ -65,6 +65,7 @@ static void e1000_release_eeprom(struct 
 static void e1000_standby_eeprom(struct e1000_hw *hw);
 static int32_t e1000_id_led_init(struct e1000_hw * hw);
 static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
+static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
 
 /* IGP cable length table */
 static const
@@ -264,6 +265,17 @@ e1000_set_mac_type(struct e1000_hw *hw)
         return -E1000_ERR_MAC_TYPE;
     }
 
+    switch(hw->mac_type) {
+    case e1000_82541:
+    case e1000_82547:
+    case e1000_82541_rev_2:
+    case e1000_82547_rev_2:
+        hw->asf_firmware_present = TRUE;
+        break;
+    default:
+        break;
+    }
+
     return E1000_SUCCESS;
 }
 
@@ -469,11 +481,11 @@ e1000_init_hw(struct e1000_hw *hw)
     uint16_t pcix_stat_hi_word;
     uint16_t cmd_mmrbc;
     uint16_t stat_mmrbc;
-
     DEBUGFUNC("e1000_init_hw");
 
     /* Initialize Identification LED */
-    if((ret_val = e1000_id_led_init(hw))) {
+    ret_val = e1000_id_led_init(hw);
+    if(ret_val) {
         DEBUGOUT("Error Initializing Identification LED\n");
         return ret_val;
     }
@@ -594,16 +606,16 @@ e1000_adjust_serdes_amplitude(struct e10
         return E1000_SUCCESS;
     }
 
-    if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
-                                     &eeprom_data))) {
+    ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, &eeprom_data);
+    if (ret_val) {
         return ret_val;
     }
 
     if(eeprom_data != EEPROM_RESERVED_WORD) {
         /* Adjust SERDES output amplitude only. */
         eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; 
-        if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL,
-                                          eeprom_data)))
+        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
+        if(ret_val)
             return ret_val;
     }
 
@@ -752,14 +764,16 @@ e1000_setup_fiber_serdes_link(struct e10
     if(hw->media_type == e1000_media_type_fiber)
         signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
 
-    if((ret_val = e1000_adjust_serdes_amplitude(hw)))
+    ret_val = e1000_adjust_serdes_amplitude(hw);
+    if(ret_val)
         return ret_val;
 
     /* Take the link out of reset */
     ctrl &= ~(E1000_CTRL_LRST);
 
     /* Adjust VCO speed to improve BER performance */
-    if((ret_val = e1000_set_vco_speed(hw)))
+    ret_val = e1000_set_vco_speed(hw);
+    if(ret_val)
         return ret_val;
 
     e1000_config_collision_dist(hw);
@@ -846,7 +860,8 @@ e1000_setup_fiber_serdes_link(struct e10
              * we detect a signal. This will allow us to communicate with
              * non-autonegotiating link partners.
              */
-            if((ret_val = e1000_check_for_link(hw))) {
+            ret_val = e1000_check_for_link(hw);
+            if(ret_val) {
                 DEBUGOUT("Error while checking for link\n");
                 return ret_val;
             }
@@ -893,12 +908,24 @@ e1000_setup_copper_link(struct e1000_hw 
     }
 
     /* Make sure we have a valid PHY */
-    if((ret_val = e1000_detect_gig_phy(hw))) {
+    ret_val = e1000_detect_gig_phy(hw);
+    if(ret_val) {
         DEBUGOUT("Error, did not detect valid phy.\n");
         return ret_val;
     }
     DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
 
+    /* Set PHY to class A mode (if necessary) */
+    ret_val = e1000_set_phy_mode(hw);
+    if(ret_val)
+        return ret_val;
+
+    if(hw->mac_type == e1000_82545_rev_3) {
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+        phy_data |= 0x00000008;
+        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+    }
+
     if(hw->mac_type <= e1000_82543 ||
        hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
        hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
@@ -907,7 +934,8 @@ e1000_setup_copper_link(struct e1000_hw 
     if(!hw->phy_reset_disable) {
         if (hw->phy_type == e1000_phy_igp) {
 
-            if((ret_val = e1000_phy_reset(hw))) {
+            ret_val = e1000_phy_reset(hw);
+            if(ret_val) {
                 DEBUGOUT("Error Resetting the PHY\n");
                 return ret_val;
             }
@@ -922,14 +950,16 @@ e1000_setup_copper_link(struct e1000_hw 
             E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
 
             /* disable lplu d3 during driver init */
-            if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) {
+            ret_val = e1000_set_d3_lplu_state(hw, FALSE);
+            if(ret_val) {
                 DEBUGOUT("Error Disabling LPLU D3\n");
                 return ret_val;
             }
 
             /* Configure mdi-mdix settings */
-            if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
-                                             &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
+                                         &phy_data);
+            if(ret_val)
                 return ret_val;
 
             if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
@@ -956,8 +986,9 @@ e1000_setup_copper_link(struct e1000_hw 
                     break;
                 }
             }
-            if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
-                                              phy_data)))
+            ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
+                                          phy_data);
+            if(ret_val)
                 return ret_val;
 
             /* set auto-master slave resolution settings */
@@ -975,27 +1006,28 @@ e1000_setup_copper_link(struct e1000_hw 
                  * resolution as hardware default. */
                 if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
                     /* Disable SmartSpeed */
-                    if((ret_val = e1000_read_phy_reg(hw,
-                                                    IGP01E1000_PHY_PORT_CONFIG,
-                                                    &phy_data)))
+                    ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+                                                 &phy_data);
+                    if(ret_val)
                         return ret_val;
                     phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-                    if((ret_val = e1000_write_phy_reg(hw,
-                                                     IGP01E1000_PHY_PORT_CONFIG,
-                                                     phy_data)))
+                    ret_val = e1000_write_phy_reg(hw,
+                                                  IGP01E1000_PHY_PORT_CONFIG,
+                                                  phy_data);
+                    if(ret_val)
                         return ret_val;
                     /* Set auto Master/Slave resolution process */
-                    if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL,
-                                                     &phy_data)))
+                    ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+                    if(ret_val)
                         return ret_val;
                     phy_data &= ~CR_1000T_MS_ENABLE;
-                    if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
-                                                      phy_data)))
+                    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+                    if(ret_val)
                         return ret_val;
                 }
 
-                if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL,
-                                                 &phy_data)))
+                ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+                if(ret_val)
                     return ret_val;
 
                 /* load defaults for future use */
@@ -1018,14 +1050,15 @@ e1000_setup_copper_link(struct e1000_hw 
                 default:
                     break;
                 }
-                if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
-                                                  phy_data)))
+                ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+                if(ret_val)
                     return ret_val;
             }
         } else {
             /* Enable CRS on TX. This must be set for half-duplex operation. */
-            if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
-                                             &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                         &phy_data);
+            if(ret_val)
                 return ret_val;
 
             phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
@@ -1064,15 +1097,17 @@ e1000_setup_copper_link(struct e1000_hw 
             phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
             if(hw->disable_polarity_correction == 1)
                 phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
-            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
-                                              phy_data)))
+            ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                          phy_data);
+            if(ret_val)
                 return ret_val;
 
             /* Force TX_CLK in the Extended PHY Specific Control Register
              * to 25MHz clock.
              */
-            if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-                                             &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+                                         &phy_data);
+            if(ret_val)
                 return ret_val;
 
             phy_data |= M88E1000_EPSCR_TX_CLK_25;
@@ -1083,14 +1118,15 @@ e1000_setup_copper_link(struct e1000_hw 
                               M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
                 phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
                              M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
-                if((ret_val = e1000_write_phy_reg(hw,
-                                                  M88E1000_EXT_PHY_SPEC_CTRL,
-                                                  phy_data)))
+                ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
+                                              phy_data);
+                if(ret_val)
                     return ret_val;
             }
 
             /* SW Reset the PHY so all changes take effect */
-            if((ret_val = e1000_phy_reset(hw))) {
+            ret_val = e1000_phy_reset(hw);
+            if(ret_val) {
                 DEBUGOUT("Error Resetting the PHY\n");
                 return ret_val;
             }
@@ -1124,7 +1160,8 @@ e1000_setup_copper_link(struct e1000_hw 
                 hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
 
             DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
-            if((ret_val = e1000_phy_setup_autoneg(hw))) {
+            ret_val = e1000_phy_setup_autoneg(hw);
+            if(ret_val) {
                 DEBUGOUT("Error Setting up Auto-Negotiation\n");
                 return ret_val;
             }
@@ -1133,18 +1170,21 @@ e1000_setup_copper_link(struct e1000_hw 
             /* Restart auto-negotiation by setting the Auto Neg Enable bit and
              * the Auto Neg Restart bit in the PHY control register.
              */
-            if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+            if(ret_val)
                 return ret_val;
 
             phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
-            if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))
+            ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
+            if(ret_val)
                 return ret_val;
 
             /* Does the user want to wait for Auto-Neg to complete here, or
              * check at a later time (for example, callback routine).
              */
             if(hw->wait_autoneg_complete) {
-                if((ret_val = e1000_wait_autoneg(hw))) {
+                ret_val = e1000_wait_autoneg(hw);
+                if(ret_val) {
                     DEBUGOUT("Error while waiting for autoneg to complete\n");
                     return ret_val;
                 }
@@ -1152,7 +1192,8 @@ e1000_setup_copper_link(struct e1000_hw 
             hw->get_link_status = TRUE;
         } else {
             DEBUGOUT("Forcing speed and duplex\n");
-            if((ret_val = e1000_phy_force_speed_duplex(hw))) {
+            ret_val = e1000_phy_force_speed_duplex(hw);
+            if(ret_val) {
                 DEBUGOUT("Error Forcing Speed and Duplex\n");
                 return ret_val;
             }
@@ -1163,9 +1204,11 @@ e1000_setup_copper_link(struct e1000_hw 
      * valid.
      */
     for(i = 0; i < 10; i++) {
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
 
         if(phy_data & MII_SR_LINK_STATUS) {
@@ -1180,19 +1223,22 @@ e1000_setup_copper_link(struct e1000_hw 
             if(hw->mac_type >= e1000_82544) {
                 e1000_config_collision_dist(hw);
             } else {
-                if((ret_val = e1000_config_mac_to_phy(hw))) {
+                ret_val = e1000_config_mac_to_phy(hw);
+                if(ret_val) {
                     DEBUGOUT("Error configuring MAC to PHY settings\n");
                     return ret_val;
                 }
             }
-            if((ret_val = e1000_config_fc_after_link_up(hw))) {
+            ret_val = e1000_config_fc_after_link_up(hw);
+            if(ret_val) {
                 DEBUGOUT("Error Configuring Flow Control\n");
                 return ret_val;
             }
             DEBUGOUT("Valid link established!!!\n");
 
             if(hw->phy_type == e1000_phy_igp) {
-                if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) {
+                ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
+                if(ret_val) {
                     DEBUGOUT("Error Configuring DSP after link up\n");
                     return ret_val;
                 }
@@ -1222,12 +1268,13 @@ e1000_phy_setup_autoneg(struct e1000_hw 
     DEBUGFUNC("e1000_phy_setup_autoneg");
 
     /* Read the MII Auto-Neg Advertisement Register (Address 4). */
-    if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
-                                     &mii_autoneg_adv_reg)))
+    ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
+    if(ret_val)
         return ret_val;
 
     /* Read the MII 1000Base-T Control Register (Address 9). */
-    if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg)))
+    ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+    if(ret_val)
         return ret_val;
 
     /* Need to parse both autoneg_advertised and fc and set up
@@ -1334,13 +1381,14 @@ e1000_phy_setup_autoneg(struct e1000_hw 
         return -E1000_ERR_CONFIG;
     }
 
-    if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV,
-                                      mii_autoneg_adv_reg)))
+    ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
+    if(ret_val)
         return ret_val;
 
     DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-    if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg)))
+    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+    if(ret_val)
         return ret_val;
 
     return E1000_SUCCESS;
@@ -1379,7 +1427,8 @@ e1000_phy_force_speed_duplex(struct e100
     ctrl &= ~E1000_CTRL_ASDE;
 
     /* Read the MII Control Register. */
-    if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg)))
+    ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
+    if(ret_val)
         return ret_val;
 
     /* We need to disable autoneg in order to force link and duplex. */
@@ -1426,16 +1475,16 @@ e1000_phy_force_speed_duplex(struct e100
     E1000_WRITE_REG(hw, CTRL, ctrl);
 
     if (hw->phy_type == e1000_phy_m88) {
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+        if(ret_val)
             return ret_val;
 
         /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
          * forced whenever speed are duplex are forced.
          */
         phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-        if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
-                                          phy_data)))
+        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+        if(ret_val)
             return ret_val;
 
         DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data);
@@ -1446,20 +1495,21 @@ e1000_phy_force_speed_duplex(struct e100
         /* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
          * forced whenever speed or duplex are forced.
          */
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
         phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
 
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
-                                          phy_data)))
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+        if(ret_val)
             return ret_val;
     }
 
     /* Write back the modified PHY MII control register. */
-    if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg)))
+    ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
+    if(ret_val)
         return ret_val;
 
     udelay(1);
@@ -1481,10 +1531,12 @@ e1000_phy_force_speed_duplex(struct e100
             /* Read the MII Status Register and wait for Auto-Neg Complete bit
              * to be set.
              */
-            if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
+            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+            if(ret_val)
                 return ret_val;
 
-            if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
+            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+            if(ret_val)
                 return ret_val;
 
             if(mii_status_reg & MII_SR_LINK_STATUS) break;
@@ -1492,7 +1544,8 @@ e1000_phy_force_speed_duplex(struct e100
         }
         if((i == 0) && (hw->phy_type == e1000_phy_m88)) {
             /* We didn't get link.  Reset the DSP and wait again for link. */
-            if((ret_val = e1000_phy_reset_dsp(hw))) {
+            ret_val = e1000_phy_reset_dsp(hw);
+            if(ret_val) {
                 DEBUGOUT("Error Resetting PHY DSP\n");
                 return ret_val;
             }
@@ -1504,10 +1557,12 @@ e1000_phy_force_speed_duplex(struct e100
             /* Read the MII Status Register and wait for Auto-Neg Complete bit
              * to be set.
              */
-            if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
+            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+            if(ret_val)
                 return ret_val;
 
-            if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
+            ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+            if(ret_val)
                 return ret_val;
         }
     }
@@ -1517,46 +1572,26 @@ e1000_phy_force_speed_duplex(struct e100
          * Extended PHY Specific Control Register to 25MHz clock.  This value
          * defaults back to a 2.5MHz clock when the PHY is reset.
          */
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_data |= M88E1000_EPSCR_TX_CLK_25;
-        if((ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
-                                          phy_data)))
+        ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+        if(ret_val)
             return ret_val;
 
         /* In addition, because of the s/w reset above, we need to enable CRS on
          * TX.  This must be set for both full and half duplex operation.
          */
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
-        if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
-                                          phy_data)))
+        ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+        if(ret_val)
             return ret_val;
-
-        /* Polarity reversal workaround for forced 10F/10H links. */
-        if(hw->mac_type <= e1000_82544 &&
-           (hw->forced_speed_duplex == e1000_10_full ||
-            hw->forced_speed_duplex == e1000_10_half)) {
-            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
-                                              0x0019)))
-                return ret_val;
-            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
-                                              0x8F0F)))
-                return ret_val;
-            /* IEEE requirement is 150ms */
-            msec_delay(200);
-            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
-                                              0x0019)))
-                return ret_val;
-            if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
-                                              0x8F00)))
-                return ret_val;
-        }
     }
     return E1000_SUCCESS;
 }
@@ -1614,8 +1649,9 @@ e1000_config_mac_to_phy(struct e1000_hw 
      * registers depending on negotiated values.
      */
     if (hw->phy_type == e1000_phy_igp) {
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
 
         if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;
@@ -1633,8 +1669,9 @@ e1000_config_mac_to_phy(struct e1000_hw 
                 IGP01E1000_PSSR_SPEED_100MBPS)
             ctrl |= E1000_CTRL_SPD_100;
     } else {
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
 
         if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;
@@ -1752,7 +1789,8 @@ e1000_config_fc_after_link_up(struct e10
     if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) ||
        ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed)) ||
        ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) {
-        if((ret_val = e1000_force_mac_fc(hw))) {
+        ret_val = e1000_force_mac_fc(hw);
+        if(ret_val) {
             DEBUGOUT("Error forcing flow control settings\n");
             return ret_val;
         }
@@ -1768,9 +1806,11 @@ e1000_config_fc_after_link_up(struct e10
          * has completed.  We read this twice because this reg has
          * some "sticky" (latched) bits.
          */
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
             return ret_val;
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
+        if(ret_val)
             return ret_val;
 
         if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
@@ -1780,11 +1820,13 @@ e1000_config_fc_after_link_up(struct e10
              * Register (Address 5) to determine how flow control was
              * negotiated.
              */
-            if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
-                                             &mii_nway_adv_reg)))
+            ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
+                                         &mii_nway_adv_reg);
+            if(ret_val)
                 return ret_val;
-            if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
-                                             &mii_nway_lp_ability_reg)))
+            ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
+                                         &mii_nway_lp_ability_reg);
+            if(ret_val)
                 return ret_val;
 
             /* Two bits in the Auto Negotiation Advertisement Register
@@ -1901,7 +1943,8 @@ e1000_config_fc_after_link_up(struct e10
              * negotiated to HALF DUPLEX, flow control should not be
              * enabled per IEEE 802.3 spec.
              */
-            if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) {
+            ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+            if(ret_val) {
                 DEBUGOUT("Error getting link speed and duplex\n");
                 return ret_val;
             }
@@ -1912,7 +1955,8 @@ e1000_config_fc_after_link_up(struct e10
             /* Now we call a subroutine to actually force the MAC
              * controller to use the correct flow control settings.
              */
-            if((ret_val = e1000_force_mac_fc(hw))) {
+            ret_val = e1000_force_mac_fc(hw);
+            if(ret_val) {
                 DEBUGOUT("Error forcing flow control settings\n");
                 return ret_val;
             }
@@ -1933,7 +1977,7 @@ e1000_config_fc_after_link_up(struct e10
 int32_t
 e1000_check_for_link(struct e1000_hw *hw)
 {
-    uint32_t rxcw;
+    uint32_t rxcw = 0;
     uint32_t ctrl;
     uint32_t status;
     uint32_t rctl;
@@ -1943,16 +1987,23 @@ e1000_check_for_link(struct e1000_hw *hw
 
     DEBUGFUNC("e1000_check_for_link");
 
+    ctrl = E1000_READ_REG(hw, CTRL);
+    status = E1000_READ_REG(hw, STATUS);
+
     /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be
      * set when the optics detect a signal. On older adapters, it will be
      * cleared when there is a signal.  This applies to fiber media only.
      */
-    if(hw->media_type == e1000_media_type_fiber)
-        signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+    if((hw->media_type == e1000_media_type_fiber) ||
+       (hw->media_type == e1000_media_type_internal_serdes)) {
+        rxcw = E1000_READ_REG(hw, RXCW);
 
-    ctrl = E1000_READ_REG(hw, CTRL);
-    status = E1000_READ_REG(hw, STATUS);
-    rxcw = E1000_READ_REG(hw, RXCW);
+        if(hw->media_type == e1000_media_type_fiber) {
+            signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
+            if(status & E1000_STATUS_LU)
+                hw->get_link_status = FALSE;
+        }
+    }
 
     /* If we have a copper PHY then we only want to go out to the PHY
      * registers to see if Auto-Neg has completed and/or if our link
@@ -1966,9 +2017,11 @@ e1000_check_for_link(struct e1000_hw *hw
          * of the PHY.
          * Read the register twice since the link bit is sticky.
          */
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
 
         if(phy_data & MII_SR_LINK_STATUS) {
@@ -2002,7 +2055,8 @@ e1000_check_for_link(struct e1000_hw *hw
         if(hw->mac_type >= e1000_82544)
             e1000_config_collision_dist(hw);
         else {
-            if((ret_val = e1000_config_mac_to_phy(hw))) {
+            ret_val = e1000_config_mac_to_phy(hw);
+            if(ret_val) {
                 DEBUGOUT("Error configuring MAC to PHY settings\n");
                 return ret_val;
             }
@@ -2012,7 +2066,8 @@ e1000_check_for_link(struct e1000_hw *hw
          * need to restore the desired flow control settings because we may
          * have had to re-autoneg with a different link partner.
          */
-        if((ret_val = e1000_config_fc_after_link_up(hw))) {
+        ret_val = e1000_config_fc_after_link_up(hw);
+        if(ret_val) {
             DEBUGOUT("Error configuring flow control\n");
             return ret_val;
         }
@@ -2061,8 +2116,8 @@ e1000_check_for_link(struct e1000_hw *hw
      * in. The autoneg_failed flag does this.
      */
     else if((((hw->media_type == e1000_media_type_fiber) &&
-            ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
-            (hw->media_type == e1000_media_type_internal_serdes)) &&
+              ((ctrl & E1000_CTRL_SWDPIN1) == signal)) ||
+             (hw->media_type == e1000_media_type_internal_serdes)) &&
             (!(status & E1000_STATUS_LU)) &&
             (!(rxcw & E1000_RXCW_C))) {
         if(hw->autoneg_failed == 0) {
@@ -2080,7 +2135,8 @@ e1000_check_for_link(struct e1000_hw *hw
         E1000_WRITE_REG(hw, CTRL, ctrl);
 
         /* Configure Flow Control after forcing link up. */
-        if((ret_val = e1000_config_fc_after_link_up(hw))) {
+        ret_val = e1000_config_fc_after_link_up(hw);
+        if(ret_val) {
             DEBUGOUT("Error configuring flow control\n");
             return ret_val;
         }
@@ -2092,8 +2148,7 @@ e1000_check_for_link(struct e1000_hw *hw
      */
     else if(((hw->media_type == e1000_media_type_fiber) ||
              (hw->media_type == e1000_media_type_internal_serdes)) &&
-              (ctrl & E1000_CTRL_SLU) &&
-              (rxcw & E1000_RXCW_C)) {
+            (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
         DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
@@ -2173,13 +2228,15 @@ e1000_get_speed_and_duplex(struct e1000_
      * match the duplex in the link partner's capabilities.
      */
     if(hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
-        if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
+        if(ret_val)
             return ret_val;
 
         if(!(phy_data & NWAY_ER_LP_NWAY_CAPS))
             *duplex = HALF_DUPLEX;
         else {
-            if((ret_val == e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
+            if(ret_val)
                 return ret_val;
             if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) ||
                (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
@@ -2210,9 +2267,11 @@ e1000_wait_autoneg(struct e1000_hw *hw)
         /* Read the MII Status Register and wait for Auto-Neg
          * Complete bit to be set.
          */
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
-        if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
         if(phy_data & MII_SR_AUTONEG_COMPLETE) {
             return E1000_SUCCESS;
@@ -2377,8 +2436,9 @@ e1000_read_phy_reg(struct e1000_hw *hw,
 
     if(hw->phy_type == e1000_phy_igp &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
-        if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
-                                             (uint16_t)reg_addr)))
+        ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+                                         (uint16_t)reg_addr);
+        if(ret_val)
             return ret_val;
     }
 
@@ -2480,8 +2540,9 @@ e1000_write_phy_reg(struct e1000_hw *hw,
 
     if(hw->phy_type == e1000_phy_igp &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
-        if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
-                                             (uint16_t)reg_addr)))
+        ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
+                                         (uint16_t)reg_addr);
+        if(ret_val)
             return ret_val;
     }
 
@@ -2620,11 +2681,13 @@ e1000_phy_reset(struct e1000_hw *hw)
     DEBUGFUNC("e1000_phy_reset");
 
     if(hw->mac_type != e1000_82541_rev_2) {
-        if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_data |= MII_CR_RESET;
-        if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data)))
+        ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
+        if(ret_val)
             return ret_val;
 
         udelay(1);
@@ -2651,12 +2714,14 @@ e1000_detect_gig_phy(struct e1000_hw *hw
     DEBUGFUNC("e1000_detect_gig_phy");
 
     /* Read the PHY ID Registers to identify which PHY is onboard. */
-    if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high)))
+    ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
+    if(ret_val)
         return ret_val;
 
     hw->phy_id = (uint32_t) (phy_id_high << 16);
     udelay(20);
-    if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low)))
+    ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
+    if(ret_val)
         return ret_val;
 
     hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK);
@@ -2708,9 +2773,12 @@ e1000_phy_reset_dsp(struct e1000_hw *hw)
     DEBUGFUNC("e1000_phy_reset_dsp");
 
     do {
-        if((ret_val = e1000_write_phy_reg(hw, 29, 0x001d))) break;
-        if((ret_val = e1000_write_phy_reg(hw, 30, 0x00c1))) break;
-        if((ret_val = e1000_write_phy_reg(hw, 30, 0x0000))) break;
+        ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
+        if(ret_val) break;
+        ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
+        if(ret_val) break;
+        ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
+        if(ret_val) break;
         ret_val = E1000_SUCCESS;
     } while(0);
 
@@ -2743,13 +2811,14 @@ e1000_phy_igp_get_info(struct e1000_hw *
     phy_info->polarity_correction = e1000_polarity_reversal_enabled;
 
     /* Check polarity status */
-    if((ret_val = e1000_check_polarity(hw, &polarity)))
+    ret_val = e1000_check_polarity(hw, &polarity);
+    if(ret_val)
         return ret_val;
 
     phy_info->cable_polarity = polarity;
 
-    if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
-                                     &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
+    if(ret_val)
         return ret_val;
 
     phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >>
@@ -2758,7 +2827,8 @@ e1000_phy_igp_get_info(struct e1000_hw *
     if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
        IGP01E1000_PSSR_SPEED_1000MBPS) {
         /* Local/Remote Receiver Information are only valid at 1000 Mbps */
-        if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
@@ -2767,7 +2837,8 @@ e1000_phy_igp_get_info(struct e1000_hw *
                               SR_1000T_REMOTE_RX_STATUS_SHIFT;
 
         /* Get cable length */
-        if((ret_val = e1000_get_cable_length(hw, &min_length, &max_length)))
+        ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
+        if(ret_val)
             return ret_val;
 
         /* transalte to old method */
@@ -2807,7 +2878,8 @@ e1000_phy_m88_get_info(struct e1000_hw *
      * and it stored in the hw->speed_downgraded parameter. */
     phy_info->downshift = hw->speed_downgraded;
 
-    if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+    if(ret_val)
         return ret_val;
 
     phy_info->extended_10bt_distance =
@@ -2818,12 +2890,14 @@ e1000_phy_m88_get_info(struct e1000_hw *
         M88E1000_PSCR_POLARITY_REVERSAL_SHIFT;
 
     /* Check polarity status */
-    if((ret_val = e1000_check_polarity(hw, &polarity)))
+    ret_val = e1000_check_polarity(hw, &polarity);
+    if(ret_val)
         return ret_val;
 
     phy_info->cable_polarity = polarity;
 
-    if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+    if(ret_val)
         return ret_val;
 
     phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
@@ -2836,7 +2910,8 @@ e1000_phy_m88_get_info(struct e1000_hw *
         phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                                   M88E1000_PSSR_CABLE_LENGTH_SHIFT);
 
-        if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >>
@@ -2878,10 +2953,12 @@ e1000_phy_get_info(struct e1000_hw *hw,
         return -E1000_ERR_CONFIG;
     }
 
-    if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+    if(ret_val)
         return ret_val;
 
-    if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
+    if(ret_val)
         return ret_val;
 
     if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
@@ -3344,6 +3421,7 @@ e1000_spi_eeprom_ready(struct e1000_hw *
         udelay(5);
         retry_count += 5;
 
+        e1000_standby_eeprom(hw);
     } while(retry_count < EEPROM_MAX_RETRY_SPI);
 
     /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
@@ -4112,12 +4190,14 @@ e1000_setup_led(struct e1000_hw *hw)
     case e1000_82541_rev_2:
     case e1000_82547_rev_2:
         /* Turn off PHY Smart Power Down (if enabled) */
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
-                                         &hw->phy_spd_default)))
-            return ret_val;
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
-                                          (uint16_t)(hw->phy_spd_default &
-                                          ~IGP01E1000_GMII_SPD))))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
+                                     &hw->phy_spd_default);
+        if(ret_val)
+            return ret_val;
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+                                      (uint16_t)(hw->phy_spd_default &
+                                      ~IGP01E1000_GMII_SPD));
+        if(ret_val)
             return ret_val;
         /* Fall Through */
     default:
@@ -4164,8 +4244,9 @@ e1000_cleanup_led(struct e1000_hw *hw)
     case e1000_82541_rev_2:
     case e1000_82547_rev_2:
         /* Turn on PHY Smart Power Down (if previously enabled) */
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
-                                          hw->phy_spd_default)))
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
+                                      hw->phy_spd_default);
+        if(ret_val)
             return ret_val;
         /* Fall Through */
     default:
@@ -4612,8 +4693,9 @@ e1000_get_cable_length(struct e1000_hw *
 
     /* Use old method for Phy older than IGP */
     if(hw->phy_type == e1000_phy_m88) {
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
 
         /* Convert the enum value to ranged values */
@@ -4652,7 +4734,8 @@ e1000_get_cable_length(struct e1000_hw *
         /* Read the AGC registers for all channels */
         for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
 
-            if((ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
+            if(ret_val)
                 return ret_val;
 
             cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
@@ -4719,15 +4802,17 @@ e1000_check_polarity(struct e1000_hw *hw
 
     if(hw->phy_type == e1000_phy_m88) {
         /* return the Polarity bit in the Status register. */
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
         *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
                     M88E1000_PSSR_REV_POLARITY_SHIFT;
     } else if(hw->phy_type == e1000_phy_igp) {
         /* Read the Status register to check the speed */
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
 
         /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
@@ -4736,8 +4821,9 @@ e1000_check_polarity(struct e1000_hw *hw
            IGP01E1000_PSSR_SPEED_1000MBPS) {
 
             /* Read the GIG initialization PCS register (0x00B4) */
-            if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
-                                             &phy_data)))
+            ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
+                                         &phy_data);
+            if(ret_val)
                 return ret_val;
 
             /* Check the polarity bits */
@@ -4775,15 +4861,17 @@ e1000_check_downshift(struct e1000_hw *h
     DEBUGFUNC("e1000_check_downshift");
 
     if(hw->phy_type == e1000_phy_igp) {
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
 
         hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
     }
     else if(hw->phy_type == e1000_phy_m88) {
-        if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
+                                     &phy_data);
+        if(ret_val)
             return ret_val;
 
         hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
@@ -4823,7 +4911,8 @@ e1000_config_dsp_after_link_change(struc
         return E1000_SUCCESS;
 
     if(link_up) {
-        if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) {
+        ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
+        if(ret_val) {
             DEBUGOUT("Error getting link speed and duplex\n");
             return ret_val;
         }
@@ -4836,14 +4925,16 @@ e1000_config_dsp_after_link_change(struc
                 min_length >= e1000_igp_cable_length_50) {
 
                 for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-                    if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
-                                                     &phy_data)))
+                    ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
+                                                 &phy_data);
+                    if(ret_val)
                         return ret_val;
 
                     phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
 
-                    if((ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
-                                                      phy_data)))
+                    ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
+                                                  phy_data);
+                    if(ret_val)
                         return ret_val;
                 }
                 hw->dsp_config_state = e1000_dsp_config_activated;
@@ -4856,23 +4947,26 @@ e1000_config_dsp_after_link_change(struc
                 uint32_t idle_errs = 0;
 
                 /* clear previous idle error counts */
-                if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
-                                                 &phy_data)))
+                ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+                                             &phy_data);
+                if(ret_val)
                     return ret_val;
 
                 for(i = 0; i < ffe_idle_err_timeout; i++) {
                     udelay(1000);
-                    if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
-                                                     &phy_data)))
+                    ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
+                                                 &phy_data);
+                    if(ret_val)
                         return ret_val;
 
                     idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
                     if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
                         hw->ffe_config_state = e1000_ffe_config_active;
 
-                        if((ret_val = e1000_write_phy_reg(hw,
+                        ret_val = e1000_write_phy_reg(hw,
                                     IGP01E1000_PHY_DSP_FFE,
-                                    IGP01E1000_PHY_DSP_FFE_CM_CP)))
+                                    IGP01E1000_PHY_DSP_FFE_CM_CP);
+                        if(ret_val)
                             return ret_val;
                         break;
                     }
@@ -4884,43 +4978,87 @@ e1000_config_dsp_after_link_change(struc
         }
     } else {
         if(hw->dsp_config_state == e1000_dsp_config_activated) {
-            if((ret_val = e1000_write_phy_reg(hw, 0x0000,
-                IGP01E1000_IEEE_FORCE_GIGA)))
+            ret_val = e1000_write_phy_reg(hw, 0x0000,
+                                          IGP01E1000_IEEE_FORCE_GIGA);
+            if(ret_val)
                 return ret_val;
             for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
-                if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
-                                                 &phy_data)))
+                ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], &phy_data);
+                if(ret_val)
                     return ret_val;
 
                 phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
                 phy_data |=  IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
 
-                if((ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i],
-                                                  phy_data)))
+                ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], phy_data);
+                if(ret_val)
                     return ret_val;
             }
 
-            if((ret_val = e1000_write_phy_reg(hw, 0x0000,
-                                              IGP01E1000_IEEE_RESTART_AUTONEG)))
+            ret_val = e1000_write_phy_reg(hw, 0x0000,
+                                          IGP01E1000_IEEE_RESTART_AUTONEG);
+            if(ret_val)
                 return ret_val;
 
             hw->dsp_config_state = e1000_dsp_config_enabled;
         }
 
         if(hw->ffe_config_state == e1000_ffe_config_active) {
-            if((ret_val = e1000_write_phy_reg(hw, 0x0000,
-                                              IGP01E1000_IEEE_FORCE_GIGA)))
+            ret_val = e1000_write_phy_reg(hw, 0x0000,
+                                          IGP01E1000_IEEE_FORCE_GIGA);
+            if(ret_val)
+                return ret_val;
+            ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
+                                          IGP01E1000_PHY_DSP_FFE_DEFAULT);
+            if(ret_val)
                 return ret_val;
-            if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
-                                              IGP01E1000_PHY_DSP_FFE_DEFAULT)))
+
+            ret_val = e1000_write_phy_reg(hw, 0x0000,
+                                          IGP01E1000_IEEE_RESTART_AUTONEG);
+            if(ret_val)
                 return ret_val;
+            hw->ffe_config_state = e1000_ffe_config_enabled;
+        }
+    }
+    return E1000_SUCCESS;
+}
+
+/*****************************************************************************
+ * Set PHY to class A mode
+ * Assumes the following operations will follow to enable the new class mode.
+ *  1. Do a PHY soft reset
+ *  2. Restart auto-negotiation or force link.
+ *
+ * hw - Struct containing variables accessed by shared code
+ ****************************************************************************/
+static int32_t
+e1000_set_phy_mode(struct e1000_hw *hw)
+{
+    int32_t ret_val;
+    uint16_t eeprom_data;
+
+    DEBUGFUNC("e1000_set_phy_mode");
+
+    if((hw->mac_type == e1000_82545_rev_3) &&
+       (hw->media_type == e1000_media_type_copper)) {
+        ret_val = e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, &eeprom_data);
+        if(ret_val) {
+            return ret_val;
+        }
 
-            if((ret_val = e1000_write_phy_reg(hw, 0x0000,
-                                              IGP01E1000_IEEE_RESTART_AUTONEG)))
+        if((eeprom_data != EEPROM_RESERVED_WORD) &&
+           (eeprom_data & EEPROM_PHY_CLASS_A)) {
+            ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B);
+            if(ret_val)
                 return ret_val;
-        hw->ffe_config_state = e1000_ffe_config_enabled;
+            ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104);
+            if(ret_val)
+                return ret_val;
+
+            hw->phy_reset_disable = FALSE;
         }
     }
+
     return E1000_SUCCESS;
 }
 
@@ -4953,25 +5091,27 @@ e1000_set_d3_lplu_state(struct e1000_hw 
     /* During driver activity LPLU should not be used or it will attain link
      * from the lowest speeds starting from 10Mbps. The capability is used for
      * Dx transitions and states */
-    if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
+    if(ret_val)
         return ret_val;
 
     if(!active) {
         phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data)))
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+        if(ret_val)
             return ret_val;
 
         /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used during
          * Dx states where the power conservation is most important.  During
          * driver activity we should enable SmartSpeed, so performance is
          * maintained. */
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-                                          phy_data)))
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
+        if(ret_val)
             return ret_val;
 
     } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) ||
@@ -4979,17 +5119,18 @@ e1000_set_d3_lplu_state(struct e1000_hw 
               (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
 
         phy_data |= IGP01E1000_GMII_FLEX_SPD;
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data)))
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+        if(ret_val)
             return ret_val;
 
         /* When LPLU is enabled we should disable SmartSpeed */
-        if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-                                         &phy_data)))
+        ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
+        if(ret_val)
             return ret_val;
 
         phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
-        if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
-                                          phy_data)))
+        ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
+        if(ret_val)
             return ret_val;
 
     }
@@ -5020,36 +5161,66 @@ e1000_set_vco_speed(struct e1000_hw *hw)
 
     /* Set PHY register 30, page 5, bit 8 to 0 */
 
-    if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
-                                     &default_page)))
+    ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
+    if(ret_val)
         return ret_val;
 
-    if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005)))
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
+    if(ret_val)
         return ret_val;
 
-    if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+    if(ret_val)
         return ret_val;
 
     phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
-    if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data)))
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+    if(ret_val)
         return ret_val;
 
     /* Set PHY register 30, page 4, bit 11 to 1 */
 
-    if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004)))
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
+    if(ret_val)
         return ret_val;
 
-    if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data)))
+    ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
+    if(ret_val)
         return ret_val;
 
     phy_data |= M88E1000_PHY_VCO_REG_BIT11;
-    if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data)))
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
+    if(ret_val)
         return ret_val;
 
-    if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
-                                      default_page)))
+    ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
+    if(ret_val)
         return ret_val;
 
     return E1000_SUCCESS;
 }
 
+/******************************************************************************
+ * Verifies the hardware needs to allow ARPs to be processed by the host
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * returns: - TRUE/FALSE
+ *
+ *****************************************************************************/
+uint32_t
+e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+{
+    uint32_t manc;
+
+    if (hw->asf_firmware_present) {
+        manc = E1000_READ_REG(hw, MANC);
+
+        if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+            !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+            return FALSE;
+        if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+            return TRUE;
+    }
+    return FALSE;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000_hw.h linux-2.4.27-rc4/drivers/net/e1000/e1000_hw.h
--- linux-2.4.26/drivers/net/e1000/e1000_hw.h	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000_hw.h	2004-07-30 16:26:05.000000000 +0000
@@ -307,6 +307,7 @@ int32_t e1000_led_off(struct e1000_hw *h
 /* Adaptive IFS Functions */
 
 /* Everything else */
+uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
 void e1000_clear_hw_cntrs(struct e1000_hw *hw);
 void e1000_reset_adaptive(struct e1000_hw *hw);
 void e1000_update_adaptive(struct e1000_hw *hw);
@@ -369,6 +370,9 @@ int32_t e1000_set_d3_lplu_state(struct e
 
 #define E1000_82542_2_0_REV_ID 2
 #define E1000_82542_2_1_REV_ID 3
+#define E1000_REVISION_0       0
+#define E1000_REVISION_1       1
+#define E1000_REVISION_2       2
 
 #define SPEED_10    10
 #define SPEED_100   100
@@ -763,6 +767,7 @@ struct e1000_ffvt_entry {
 #define E1000_WUPL     0x05900  /* Wakeup Packet Length - RW */
 #define E1000_WUPM     0x05A00  /* Wakeup Packet Memory - RO A */
 #define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - RW Array */
+#define E1000_HOST_IF  0x08800  /* Host Interface */
 #define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
 #define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
 
@@ -899,6 +904,7 @@ struct e1000_ffvt_entry {
 #define E1000_82542_TDFT     0x08018
 #define E1000_82542_FFMT     E1000_FFMT
 #define E1000_82542_FFVT     E1000_FFVT
+#define E1000_82542_HOST_IF  E1000_HOST_IF
 
 /* Statistics counters collected by the MAC */
 struct e1000_hw_stats {
@@ -978,6 +984,7 @@ struct e1000_hw {
     e1000_ms_type master_slave;
     e1000_ms_type original_master_slave;
     e1000_ffe_config ffe_config_state;
+    uint32_t asf_firmware_present;
     unsigned long io_base;
     uint32_t phy_id;
     uint32_t phy_revision;
@@ -1434,6 +1441,10 @@ struct e1000_hw {
 #define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
 #define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_EN_MAC_ADDR_FILTER   0x00100000 /* Enable MAC address
+                                                    * filtering */
+#define E1000_MANC_EN_MNG2HOST   0x00200000 /* Enable MNG packets to host
+                                             * memory */
 #define E1000_MANC_SMB_REQ       0x01000000 /* SMBus Request */
 #define E1000_MANC_SMB_GNT       0x02000000 /* SMBus Grant */
 #define E1000_MANC_SMB_CLK_IN    0x04000000 /* SMBus Clock In */
@@ -1480,6 +1491,7 @@ struct e1000_hw {
 #define EEPROM_COMPAT                 0x0003
 #define EEPROM_ID_LED_SETTINGS        0x0004
 #define EEPROM_SERDES_AMPLITUDE       0x0006 /* For SERDES output amplitude adjustment. */
+#define EEPROM_PHY_CLASS_WORD         0x0007
 #define EEPROM_INIT_CONTROL1_REG      0x000A
 #define EEPROM_INIT_CONTROL2_REG      0x000F
 #define EEPROM_INIT_CONTROL3_PORT_B   0x0014
@@ -1513,6 +1525,9 @@ struct e1000_hw {
 /* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */
 #define EEPROM_SERDES_AMPLITUDE_MASK  0x000F
 
+/* Mask bit for PHY class in Word 7 of the EEPROM */
+#define EEPROM_PHY_CLASS_A   0x8000
+
 /* Mask bits for fields in Word 0x0a of the EEPROM */
 #define EEPROM_WORD0A_ILOS   0x0010
 #define EEPROM_WORD0A_SWDPIO 0x01E0
@@ -1540,7 +1555,7 @@ struct e1000_hw {
 #define PBA_SIZE 4
 
 /* Collision related configuration parameters */
-#define E1000_COLLISION_THRESHOLD       16
+#define E1000_COLLISION_THRESHOLD       15
 #define E1000_CT_SHIFT                  4
 #define E1000_COLLISION_DISTANCE        64
 #define E1000_FDX_COLLISION_DISTANCE    E1000_COLLISION_DISTANCE
@@ -2006,7 +2021,7 @@ struct e1000_hw {
 #define IGP01E1000_PSSR_MDIX_SHIFT             0x000B /* shift right 11 */
 
 /* IGP01E1000 Specific Port Control Register - R/W */
-#define IGP01E1000_PSCR_TP_LOOPBACK            0x0001
+#define IGP01E1000_PSCR_TP_LOOPBACK            0x0010
 #define IGP01E1000_PSCR_CORRECT_NC_SCMBLR      0x0200
 #define IGP01E1000_PSCR_TEN_CRS_SELECT         0x0400
 #define IGP01E1000_PSCR_FLIP_CHIP              0x0800
@@ -2016,16 +2031,18 @@ struct e1000_hw {
 /* IGP01E1000 Specific Port Link Health Register */
 #define IGP01E1000_PLHR_SS_DOWNGRADE           0x8000
 #define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR    0x4000
+#define IGP01E1000_PLHR_MASTER_FAULT           0x2000
+#define IGP01E1000_PLHR_MASTER_RESOLUTION      0x1000
 #define IGP01E1000_PLHR_GIG_REM_RCVR_NOK       0x0800 /* LH */
 #define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW   0x0400 /* LH */
 #define IGP01E1000_PLHR_DATA_ERR_1             0x0200 /* LH */
 #define IGP01E1000_PLHR_DATA_ERR_0             0x0100
-#define IGP01E1000_PLHR_AUTONEG_FAULT          0x0010
-#define IGP01E1000_PLHR_AUTONEG_ACTIVE         0x0008
-#define IGP01E1000_PLHR_VALID_CHANNEL_D        0x0004
-#define IGP01E1000_PLHR_VALID_CHANNEL_C        0x0002
-#define IGP01E1000_PLHR_VALID_CHANNEL_B        0x0001
-#define IGP01E1000_PLHR_VALID_CHANNEL_A        0x0000
+#define IGP01E1000_PLHR_AUTONEG_FAULT          0x0040
+#define IGP01E1000_PLHR_AUTONEG_ACTIVE         0x0010
+#define IGP01E1000_PLHR_VALID_CHANNEL_D        0x0008
+#define IGP01E1000_PLHR_VALID_CHANNEL_C        0x0004
+#define IGP01E1000_PLHR_VALID_CHANNEL_B        0x0002
+#define IGP01E1000_PLHR_VALID_CHANNEL_A        0x0001
 
 /* IGP01E1000 Channel Quality Register */
 #define IGP01E1000_MSE_CHANNEL_D        0x000F
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000_main.c linux-2.4.27-rc4/drivers/net/e1000/e1000_main.c
--- linux-2.4.26/drivers/net/e1000/e1000_main.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000_main.c	2004-07-30 16:27:48.000000000 +0000
@@ -27,47 +27,32 @@
 *******************************************************************************/
 
 #include "e1000.h"
+#include <linux/rtnetlink.h>
 
 /* Change Log
  *
- * 5.2.30.1	1/29/03
- *   o Set VLAN filtering to IEEE 802.1Q after reset so we don't break
- *     SoL connections that use VLANs.
- *   o Allow 1000/Full setting for AutoNeg param for Fiber connections
- *     Jon D Mason [jonmason@us.ibm.com].
- *   o Race between Tx queue and Tx clean fixed with a spin lock.
- *   o Added netpoll support.
- *   o Fixed endianess bug causing ethtool loopback diags to fail on ppc.
- *   o Use pdev->irq rather than netdev->irq in preparation for MSI support.
- *   o Report driver message on user override of InterruptThrottleRate
- *     module parameter.
- *   o Change I/O address storage from uint32_t to unsigned long.
- *
- * 5.2.22	10/15/03
- *   o Bug fix: SERDES devices might be connected to a back-plane
- *     switch that doesn't support auto-neg, so add the capability
- *     to force 1000/Full.  Also, since forcing 1000/Full, sample
- *     RxSynchronize bit to detect link state.
- *   o Bug fix: Flow control settings for hi/lo watermark didn't
- *     consider changes in the Rx FIFO size, which could occur with
- *     Jumbo Frames or with the reduced FIFO in 82547.
- *   o Better propagation of error codes. [Janice Girouard 
- *     (janiceg@us.ibm.com)].
- *   o Bug fix: hang under heavy Tx stress when running out of Tx
- *     descriptors; wasn't clearing context descriptor when backing
- *     out of send because of no-resource condition.
- *   o Bug fix: check netif_running in dev->poll so we don't have to
- *     hang in dev->close until all polls are finished.  [Robert
- *     Ollson (robert.olsson@data.slu.se)].
- *   o Revert TxDescriptor ring size back to 256 since change to 1024
- *     wasn't accepted into the kernel.
- *
- * 5.2.16	8/8/03
+ * 5.2.51   5/14/04
+ *   o set default configuration to 'NAPI disabled'. NAPI enabled driver
+ *     causes kernel panic when the interface is shutdown while data is being
+ *     transferred.
+ * 5.2.47   5/04/04
+ *   o fixed ethtool -t implementation
+ * 5.2.45   4/29/04
+ *   o fixed ethtool -e implementation
+ *   o Support for ethtool ops [Stephen Hemminger (shemminger@osdl.org)]
+ * 5.2.42   4/26/04
+ *   o Added support for the DPRINTK macro for enhanced error logging.  Some
+ *     parts of the patch were supplied by Jon Mason.
+ *   o Move the register_netdevice() donw in the probe routine due to a 
+ *     loading/unloading test issue.
+ *   o Added a long RX byte count the the extra ethtool data members for BER
+ *     testing purposes.
+ * 5.2.39	3/12/04
  */
 
 char e1000_driver_name[] = "e1000";
 char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
-char e1000_driver_version[] = "5.2.30.1-k1";
+char e1000_driver_version[] = "5.2.52-k3";
 char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -162,6 +147,7 @@ static void e1000_alloc_rx_buffers(struc
 static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
 static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
 			   int cmd);
+void set_ethtool_ops(struct net_device *netdev);
 static void e1000_enter_82542_rst(struct e1000_adapter *adapter);
 static void e1000_leave_82542_rst(struct e1000_adapter *adapter);
 static inline void e1000_rx_checksum(struct e1000_adapter *adapter,
@@ -198,7 +184,7 @@ struct notifier_block e1000_notifier_reb
 /* Exported from other modules */
 
 extern void e1000_check_options(struct e1000_adapter *adapter);
-extern int e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr);
+
 
 static struct pci_driver e1000_driver = {
 	.name     = e1000_driver_name,
@@ -216,6 +202,10 @@ MODULE_AUTHOR("Intel Corporation, <linux
 MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver");
 MODULE_LICENSE("GPL");
 
+static int debug = 3;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 /**
  * e1000_init_module - Driver Registration Routine
  *
@@ -309,7 +299,7 @@ e1000_down(struct e1000_adapter *adapter
 void
 e1000_reset(struct e1000_adapter *adapter)
 {
-	uint32_t pba;
+	uint32_t pba, manc;
 	/* Repartition Pba for greater than 9k mtu
 	 * To take effect CTRL.RST is required.
 	 */
@@ -327,14 +317,16 @@ e1000_reset(struct e1000_adapter *adapte
 		adapter->tx_fifo_head = 0;
 		adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
 		adapter->tx_fifo_size =
-			(E1000_PBA_40K - pba) << E1000_TX_FIFO_SIZE_SHIFT;
+			(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
 		atomic_set(&adapter->tx_fifo_stall, 0);
 	}
 	E1000_WRITE_REG(&adapter->hw, PBA, pba);
 
 	/* flow control settings */
-	adapter->hw.fc_high_water = pba - E1000_FC_HIGH_DIFF;
-	adapter->hw.fc_low_water = pba - E1000_FC_LOW_DIFF;
+	adapter->hw.fc_high_water =
+		(pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_HIGH_DIFF;
+	adapter->hw.fc_low_water =
+		(pba << E1000_PBA_BYTES_SHIFT) - E1000_FC_LOW_DIFF;
 	adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
 	adapter->hw.fc_send_xon = 1;
 	adapter->hw.fc = adapter->hw.original_fc;
@@ -349,6 +341,12 @@ e1000_reset(struct e1000_adapter *adapte
 
 	e1000_reset_adaptive(&adapter->hw);
 	e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+
+	if(adapter->en_mng_pt) {
+		manc = E1000_READ_REG(&adapter->hw, MANC);
+		manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
+		E1000_WRITE_REG(&adapter->hw, MANC, manc);
+	}
 }
 
 /**
@@ -402,12 +400,19 @@ e1000_probe(struct pci_dev *pdev,
 	}
 
 	SET_MODULE_OWNER(netdev);
+	SET_NETDEV_DEV(netdev, &pdev->dev);
 
 	pci_set_drvdata(pdev, netdev);
 	adapter = netdev->priv;
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
 	adapter->hw.back = adapter;
+	adapter->msg_enable = (1 << debug) - 1;
+
+	rtnl_lock();
+	/* we need to set the name early since the DPRINTK macro needs it set */
+	if (dev_alloc_name(netdev, netdev->name) < 0) 
+		goto err_free_unlock;
 
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
@@ -435,6 +440,7 @@ e1000_probe(struct pci_dev *pdev,
 	netdev->set_mac_address = &e1000_set_mac;
 	netdev->change_mtu = &e1000_change_mtu;
 	netdev->do_ioctl = &e1000_ioctl;
+	set_ethtool_ops(netdev);
 	netdev->tx_timeout = &e1000_tx_timeout;
 	netdev->watchdog_timeo = 5 * HZ;
 #ifdef CONFIG_E1000_NAPI
@@ -470,14 +476,21 @@ e1000_probe(struct pci_dev *pdev,
 	}
 
 #ifdef NETIF_F_TSO
+#ifdef BROKEN_ON_NON_IA_ARCHS
+	/* Disbaled for now until root-cause is found for
+	 * hangs reported against non-IA archs.  TSO can be
+	 * enabled using ethtool -K eth<x> tso on */
 	if((adapter->hw.mac_type >= e1000_82544) &&
 	   (adapter->hw.mac_type != e1000_82547))
 		netdev->features |= NETIF_F_TSO;
 #endif
+#endif
 
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+
 	/* before reading the EEPROM, reset the controller to 
 	 * put the device in a known good starting state */
 	
@@ -486,7 +499,7 @@ e1000_probe(struct pci_dev *pdev,
 	/* make sure the EEPROM is good */
 
 	if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) {
-		printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
+		DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
 		err = -EIO;
 		goto err_eeprom;
 	}
@@ -520,15 +533,12 @@ e1000_probe(struct pci_dev *pdev,
 	INIT_TQUEUE(&adapter->tx_timeout_task,
 		(void (*)(void *))e1000_tx_timeout_task, netdev);
 
-	register_netdev(netdev);
-
 	/* we're going to reset, so assume we have no link for now */
 
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	printk(KERN_INFO "%s: Intel(R) PRO/1000 Network Connection\n",
-	       netdev->name);
+	DPRINTK(PROBE, INFO, "Intel(R) PRO/1000 Network Connection\n");
 	e1000_check_options(adapter);
 
 	/* Initial Wake on LAN setting
@@ -562,13 +572,21 @@ e1000_probe(struct pci_dev *pdev,
 
 	e1000_reset(adapter);
 
+	/* since we are holding the rtnl lock already, call the no-lock version */
+	if((err = register_netdevice(netdev)))
+		goto err_register;
+
 	cards_found++;
+	rtnl_unlock();
 	return 0;
 
+err_register:
 err_sw_init:
 err_eeprom:
 	iounmap(adapter->hw.hw_addr);
 err_ioremap:
+err_free_unlock:
+	rtnl_unlock();
 	free_netdev(netdev);
 err_alloc_etherdev:
 	pci_release_regions(pdev);
@@ -646,7 +664,7 @@ e1000_sw_init(struct e1000_adapter *adap
 	/* identify the MAC */
 
 	if (e1000_set_mac_type(hw)) {
-		E1000_ERR("Unknown MAC Type\n");
+		DPRINTK(PROBE, ERR, "Unknown MAC Type\n");
 		return -EIO;
 	}
 
@@ -1373,9 +1391,8 @@ e1000_watchdog(unsigned long data)
 			                           &adapter->link_speed,
 			                           &adapter->link_duplex);
 
-			printk(KERN_INFO
-			       "e1000: %s NIC Link is Up %d Mbps %s\n",
-			       netdev->name, adapter->link_speed,
+			DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s\n",
+			       adapter->link_speed,
 			       adapter->link_duplex == FULL_DUPLEX ?
 			       "Full Duplex" : "Half Duplex");
 
@@ -1388,9 +1405,7 @@ e1000_watchdog(unsigned long data)
 		if(netif_carrier_ok(netdev)) {
 			adapter->link_speed = 0;
 			adapter->link_duplex = 0;
-			printk(KERN_INFO
-			       "e1000: %s NIC Link is Down\n",
-			       netdev->name);
+			DPRINTK(LINK, INFO, "NIC Link is Down\n");
 			netif_carrier_off(netdev);
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ);
@@ -1542,33 +1557,17 @@ e1000_tx_csum(struct e1000_adapter *adap
 
 static inline int
 e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
-	unsigned int first)
+	unsigned int first, unsigned int max_per_txd,
+	unsigned int nr_frags, unsigned int mss)
 {
 	struct e1000_desc_ring *tx_ring = &adapter->tx_ring;
-	struct e1000_tx_desc *tx_desc;
 	struct e1000_buffer *buffer_info;
-	unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD;
+	unsigned int len = skb->len;
 	unsigned int offset = 0, size, count = 0, i;
-#ifdef NETIF_F_TSO
-	unsigned int mss;
-#endif
-	unsigned int nr_frags;
 	unsigned int f;
-
-#ifdef NETIF_F_TSO
-	mss = skb_shinfo(skb)->tso_size;
-	/* The controller does a simple calculation to 
-	 * make sure there is enough room in the FIFO before
-	 * initiating the DMA for each buffer.  The calc is:
-	 * 4 = ceil(buffer len/mss).  To make sure we don't
-	 * overrun the FIFO, adjust the max buffer len if mss
-	 * drops. */
-	if(mss)
-		max_per_txd = min(mss << 2, max_per_txd);
-#endif
-	nr_frags = skb_shinfo(skb)->nr_frags;
 	len -= skb->data_len;
 
+
 	i = tx_ring->next_to_use;
 
 	while(len) {
@@ -1640,46 +1639,6 @@ e1000_tx_map(struct e1000_adapter *adapt
 			if(++i == tx_ring->count) i = 0;
 		}
 	}
-
-	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2) {
-
-		/* There aren't enough descriptors available to queue up
-		 * this send (need: count + 1 context desc + 1 desc gap
-		 * to keep tail from touching head), so undo the mapping
-		 * and abort the send.  We could have done the check before
-		 * we mapped the skb, but because of all the workarounds
-		 * (above), it's too difficult to predict how many we're
-		 * going to need.*/
-		i = adapter->tx_ring.next_to_use;
-
-		if(i == first) {
-			/* Cleanup after e1000_tx_[csum|tso] scribbling
-			 * on descriptors. */
-			tx_desc = E1000_TX_DESC(*tx_ring, first);
-			tx_desc->buffer_addr = 0;
-			tx_desc->lower.data = 0;
-			tx_desc->upper.data = 0;
-		}
-
-		while(count--) {
-			buffer_info = &tx_ring->buffer_info[i];
-
-			if(buffer_info->dma) {
-				pci_unmap_page(adapter->pdev,
-					       buffer_info->dma,
-					       buffer_info->length,
-					       PCI_DMA_TODEVICE);
-				buffer_info->dma = 0;
-			}
-
-			if(++i == tx_ring->count) i = 0;
-		}
-
-		adapter->tx_ring.next_to_use = first;
-
-		return 0;
-	}
-
 	i = (i == 0) ? tx_ring->count - 1 : i - 1;
 	tx_ring->buffer_info[i].skb = skb;
 	tx_ring->buffer_info[first].next_to_watch = i;
@@ -1774,27 +1733,72 @@ no_fifo_stall_required:
 	return 0;
 }
 
+#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) 
 static int
 e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev->priv;
-	unsigned int first;
+	unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD;
+	unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
 	unsigned int tx_flags = 0;
 	unsigned long flags;
-	int count;
-
+	unsigned int len = skb->len;
+	int count = 0;
+	unsigned int mss = 0;
+	unsigned int nr_frags = 0;
+	unsigned int f;
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	len -= skb->data_len;
 	if(skb->len <= 0) {
 		dev_kfree_skb_any(skb);
 		return 0;
 	}
 
+#ifdef NETIF_F_TSO
+	mss = skb_shinfo(skb)->tso_size;
+	/* The controller does a simple calculation to 
+	 * make sure there is enough room in the FIFO before
+	 * initiating the DMA for each buffer.  The calc is:
+	 * 4 = ceil(buffer len/mss).  To make sure we don't
+	 * overrun the FIFO, adjust the max buffer len if mss
+	 * drops. */
+	if(mss) {
+		max_per_txd = min(mss << 2, max_per_txd);
+		max_txd_pwr = fls(max_per_txd) - 1;
+	}
+	if((mss) || (skb->ip_summed == CHECKSUM_HW))
+		count++;
+	count++;	/*for sentinel desc*/
+#else
+	if(skb->ip_summed == CHECKSUM_HW)
+		count++;
+#endif
+
+	count += TXD_USE_COUNT(len, max_txd_pwr);
+	if(adapter->pcix_82544)
+		count++;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	for(f = 0; f < nr_frags; f++)
+		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
+		                       max_txd_pwr);
+	if(adapter->pcix_82544)
+		count += nr_frags;
+	
 	spin_lock_irqsave(&adapter->tx_lock, flags);
+	/* need: count +  2 desc gap to keep tail from touching 
+	 * head, otherwise try next time */
+	if(E1000_DESC_UNUSED(&adapter->tx_ring) < count + 2 ) {
+		netif_stop_queue(netdev);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+		return 1;
+	}
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
 
 	if(adapter->hw.mac_type == e1000_82547) {
 		if(e1000_82547_fifo_workaround(adapter, skb)) {
 			netif_stop_queue(netdev);
 			mod_timer(&adapter->tx_fifo_stall_timer, jiffies);
-			spin_unlock_irqrestore(&adapter->tx_lock, flags);
 			return 1;
 		}
 	}
@@ -1811,18 +1815,12 @@ e1000_xmit_frame(struct sk_buff *skb, st
 	else if(e1000_tx_csum(adapter, skb))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
-	if((count = e1000_tx_map(adapter, skb, first)))
-		e1000_tx_queue(adapter, count, tx_flags);
-	else {
-		netif_stop_queue(netdev);
-		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		return 1;
-	}
+	e1000_tx_queue(adapter, 
+		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss), 
+		tx_flags);
 
 	netdev->trans_start = jiffies;
 
-	spin_unlock_irqrestore(&adapter->tx_lock, flags);
-	
 	return 0;
 }
 
@@ -1885,7 +1883,7 @@ e1000_change_mtu(struct net_device *netd
 
 	if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
 	   (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		E1000_ERR("Invalid MTU setting\n");
+		DPRINTK(PROBE, ERR, "Invalid MTU setting\n");
 		return -EINVAL;
 	}
 
@@ -1893,7 +1891,7 @@ e1000_change_mtu(struct net_device *netd
 		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
 
 	} else if(adapter->hw.mac_type < e1000_82543) {
-		E1000_ERR("Jumbo Frames not supported on 82542\n");
+		DPRINTK(PROBE, ERR, "Jumbo Frames not supported on 82542\n");
 		return -EINVAL;
 
 	} else if(max_frame <= E1000_RXBUFFER_4096) {
@@ -2122,26 +2120,10 @@ e1000_intr(int irq, void *data, struct p
 		__netif_rx_schedule(netdev);
 	}
 #else
-        /* Writing IMC and IMS is needed for 82547.
-	   Due to Hub Link bus being occupied, an interrupt 
-	   de-assertion message is not able to be sent. 
-	   When an interrupt assertion message is generated later,
-	   two messages are re-ordered and sent out.
-	   That causes APIC to think 82547 is in de-assertion
-	   state, while 82547 is in assertion state, resulting 
-	   in dead lock. Writing IMC forces 82547 into 
-	   de-assertion state.
-        */
-	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
-		e1000_irq_disable(adapter);
-
 	for(i = 0; i < E1000_MAX_INTR; i++)
 		if(!e1000_clean_rx_irq(adapter) &
 		   !e1000_clean_tx_irq(adapter))
 			break;
-
-	if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2)
-		e1000_irq_enable(adapter);
 #endif
 
 	return IRQ_HANDLED;
@@ -2169,6 +2151,7 @@ e1000_clean(struct net_device *netdev, i
 	if(work_done < work_to_do || !netif_running(netdev)) {
 		netif_rx_complete(netdev);
 		e1000_irq_enable(adapter);
+		return 0;
 	}
 
 	return (work_done >= work_to_do);
@@ -2191,7 +2174,6 @@ e1000_clean_tx_irq(struct e1000_adapter 
 	unsigned int i, eop;
 	boolean_t cleaned = FALSE;
 
-	spin_lock(&adapter->tx_lock);
 
 	i = tx_ring->next_to_clean;
 	eop = tx_ring->buffer_info[i].next_to_watch;
@@ -2234,6 +2216,8 @@ e1000_clean_tx_irq(struct e1000_adapter 
 
 	tx_ring->next_to_clean = i;
 
+	spin_lock(&adapter->tx_lock);
+
 	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev))
 		netif_wake_queue(netdev);
 
@@ -2294,7 +2278,8 @@ e1000_clean_rx_irq(struct e1000_adapter 
 
 			/* All receives must fit into a single buffer */
 
-			E1000_DBG("Receive packet consumed multiple buffers\n");
+			E1000_DBG("%s: Receive packet consumed multiple buffers\n",
+				netdev->name);
 
 			dev_kfree_skb_irq(skb);
 			rx_desc->status = 0;
@@ -2511,8 +2496,6 @@ e1000_ioctl(struct net_device *netdev, s
 	case SIOCGMIIREG:
 	case SIOCSMIIREG:
 		return e1000_mii_ioctl(netdev, ifr, cmd);
-	case SIOCETHTOOL:
-		return e1000_ethtool_ioctl(netdev, ifr);
 	default:
 		return -EOPNOTSUPP;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000_osdep.h linux-2.4.27-rc4/drivers/net/e1000/e1000_osdep.h
--- linux-2.4.26/drivers/net/e1000/e1000_osdep.h	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000_osdep.h	2004-07-30 16:26:55.000000000 +0000
@@ -47,7 +47,7 @@
 	                	BUG(); \
 			} else { \
 				set_current_state(TASK_UNINTERRUPTIBLE); \
-				schedule_timeout((x * HZ)/1000); \
+				schedule_timeout((x * HZ)/1000 + 2); \
 			} } while(0)
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/e1000/e1000_param.c linux-2.4.27-rc4/drivers/net/e1000/e1000_param.c
--- linux-2.4.26/drivers/net/e1000/e1000_param.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/e1000/e1000_param.c	2004-07-30 16:25:53.000000000 +0000
@@ -107,7 +107,7 @@ E1000_PARAM(Duplex, "Duplex setting");
 
 /* Auto-negotiation Advertisement Override
  *
- * Valid Range: 0x01-0x0F, 0x20-0x2F
+ * Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
  *
  * The AutoNeg value is a bit mask describing which speed and duplex
  * combinations should be advertised during auto-negotiation.
@@ -117,7 +117,7 @@ E1000_PARAM(Duplex, "Duplex setting");
  * Speed (Mbps)  N/A   N/A   1000   N/A    100   100   10     10
  * Duplex                    Full          Full  Half  Full   Half
  *
- * Default Value: 0x2F
+ * Default Value: 0x2F (copper); 0x20 (fiber)
  */
 
 E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
@@ -234,7 +234,8 @@ struct e1000_option {
 };
 
 static int __devinit
-e1000_validate_option(int *value, struct e1000_option *opt)
+e1000_validate_option(int *value, struct e1000_option *opt,
+	struct e1000_adapter *adapter)
 {
 	if(*value == OPTION_UNSET) {
 		*value = opt->def;
@@ -245,16 +246,17 @@ e1000_validate_option(int *value, struct
 	case enable_option:
 		switch (*value) {
 		case OPTION_ENABLED:
-			printk(KERN_INFO "%s Enabled\n", opt->name);
+			DPRINTK(PROBE, INFO, "%s Enabled\n", opt->name);
 			return 0;
 		case OPTION_DISABLED:
-			printk(KERN_INFO "%s Disabled\n", opt->name);
+			DPRINTK(PROBE, INFO, "%s Disabled\n", opt->name);
 			return 0;
 		}
 		break;
 	case range_option:
 		if(*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
-			printk(KERN_INFO "%s set to %i\n", opt->name, *value);
+			DPRINTK(PROBE, INFO,
+				"%s set to %i\n", opt->name, *value);
 			return 0;
 		}
 		break;
@@ -266,7 +268,7 @@ e1000_validate_option(int *value, struct
 			ent = &opt->arg.l.p[i];
 			if(*value == ent->i) {
 				if(ent->str[0] != '\0')
-					printk(KERN_INFO "%s\n", ent->str);
+					DPRINTK(PROBE, INFO, "%s\n", ent->str);
 				return 0;
 			}
 		}
@@ -276,7 +278,7 @@ e1000_validate_option(int *value, struct
 		BUG();
 	}
 
-	printk(KERN_INFO "Invalid %s specified (%i) %s\n",
+	DPRINTK(PROBE, INFO, "Invalid %s specified (%i) %s\n",
 	       opt->name, *value, opt->err);
 	*value = opt->def;
 	return -1;
@@ -300,9 +302,9 @@ e1000_check_options(struct e1000_adapter
 {
 	int bd = adapter->bd_number;
 	if(bd >= E1000_MAX_NIC) {
-		printk(KERN_NOTICE
+		DPRINTK(PROBE, NOTICE,
 		       "Warning: no configuration for board #%i\n", bd);
-		printk(KERN_NOTICE "Using defaults for all values\n");
+		DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
 		bd = E1000_MAX_NIC;
 	}
 
@@ -321,7 +323,7 @@ e1000_check_options(struct e1000_adapter
 			E1000_MAX_TXD : E1000_MAX_82544_TXD;
 
 		tx_ring->count = TxDescriptors[bd];
-		e1000_validate_option(&tx_ring->count, &opt);
+		e1000_validate_option(&tx_ring->count, &opt, adapter);
 		E1000_ROUNDUP(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
 	}
 	{ /* Receive Descriptor Count */
@@ -339,7 +341,7 @@ e1000_check_options(struct e1000_adapter
 			E1000_MAX_82544_RXD;
 
 		rx_ring->count = RxDescriptors[bd];
-		e1000_validate_option(&rx_ring->count, &opt);
+		e1000_validate_option(&rx_ring->count, &opt, adapter);
 		E1000_ROUNDUP(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE);
 	}
 	{ /* Checksum Offload Enable/Disable */
@@ -351,7 +353,7 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		int rx_csum = XsumRX[bd];
-		e1000_validate_option(&rx_csum, &opt);
+		e1000_validate_option(&rx_csum, &opt, adapter);
 		adapter->rx_csum = rx_csum;
 	}
 	{ /* Flow Control */
@@ -373,7 +375,7 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		int fc = FlowControl[bd];
-		e1000_validate_option(&fc, &opt);
+		e1000_validate_option(&fc, &opt, adapter);
 		adapter->hw.fc = adapter->hw.original_fc = fc;
 	}
 	{ /* Transmit Interrupt Delay */
@@ -387,7 +389,7 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		adapter->tx_int_delay = TxIntDelay[bd];
-		e1000_validate_option(&adapter->tx_int_delay, &opt);
+		e1000_validate_option(&adapter->tx_int_delay, &opt, adapter);
 	}
 	{ /* Transmit Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -400,7 +402,7 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->tx_abs_int_delay, &opt);
+		e1000_validate_option(&adapter->tx_abs_int_delay, &opt, adapter);
 	}
 	{ /* Receive Interrupt Delay */
 		struct e1000_option opt = {
@@ -413,7 +415,7 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		adapter->rx_int_delay = RxIntDelay[bd];
-		e1000_validate_option(&adapter->rx_int_delay, &opt);
+		e1000_validate_option(&adapter->rx_int_delay, &opt, adapter);
 	}
 	{ /* Receive Absolute Interrupt Delay */
 		struct e1000_option opt = {
@@ -426,7 +428,7 @@ e1000_check_options(struct e1000_adapter
 		};
 
 		adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
-		e1000_validate_option(&adapter->rx_abs_int_delay, &opt);
+		e1000_validate_option(&adapter->rx_abs_int_delay, &opt, adapter);
 	}
 	{ /* Interrupt Throttling Rate */
 		struct e1000_option opt = {
@@ -444,13 +446,14 @@ e1000_check_options(struct e1000_adapter
 			adapter->itr = 1;
 			break;
 		case 0:
-			printk(KERN_INFO "%s turned off\n", opt.name);
+			DPRINTK(PROBE, INFO, "%s turned off\n", opt.name);
 			break;
 		case 1:
-			printk(KERN_INFO "%s set to dynamic mode\n", opt.name);
+			DPRINTK(PROBE, INFO,
+				"%s set to dynamic mode\n", opt.name);
 			break;
 		default:
-			e1000_validate_option(&adapter->itr, &opt);
+			e1000_validate_option(&adapter->itr, &opt, adapter);
 			break;
 		}
 	}
@@ -482,15 +485,15 @@ e1000_check_fiber_options(struct e1000_a
 	bd = bd > E1000_MAX_NIC ? E1000_MAX_NIC : bd;
 
 	if((Speed[bd] != OPTION_UNSET)) {
-		printk(KERN_INFO "Speed not valid for fiber adapters, "
+		DPRINTK(PROBE, INFO, "Speed not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
 	if((Duplex[bd] != OPTION_UNSET)) {
-		printk(KERN_INFO "Duplex not valid for fiber adapters, "
+		DPRINTK(PROBE, INFO, "Duplex not valid for fiber adapters, "
 		       "parameter ignored\n");
 	}
 	if((AutoNeg[bd] != OPTION_UNSET) && (AutoNeg[bd] != 0x20)) {
-		printk(KERN_INFO "AutoNeg other than Full/1000 is "
+		DPRINTK(PROBE, INFO, "AutoNeg other than Full/1000 is "
 		       "not valid for fiber adapters, parameter ignored\n");
 	}
 }
@@ -525,7 +528,7 @@ e1000_check_copper_options(struct e1000_
 		};
 
 		speed = Speed[bd];
-		e1000_validate_option(&speed, &opt);
+		e1000_validate_option(&speed, &opt, adapter);
 	}
 	{ /* Duplex */
 		struct e1000_opt_list dplx_list[] = {{           0, "" },
@@ -542,11 +545,11 @@ e1000_check_copper_options(struct e1000_
 		};
 
 		dplx = Duplex[bd];
-		e1000_validate_option(&dplx, &opt);
+		e1000_validate_option(&dplx, &opt, adapter);
 	}
 
 	if(AutoNeg[bd] != OPTION_UNSET && (speed != 0 || dplx != 0)) {
-		printk(KERN_INFO
+		DPRINTK(PROBE, INFO,
 		       "AutoNeg specified along with Speed or Duplex, "
 		       "parameter ignored\n");
 		adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
@@ -595,7 +598,7 @@ e1000_check_copper_options(struct e1000_
 		};
 
 		int an = AutoNeg[bd];
-		e1000_validate_option(&an, &opt);
+		e1000_validate_option(&an, &opt, adapter);
 		adapter->hw.autoneg_advertised = an;
 	}
 
@@ -603,78 +606,85 @@ e1000_check_copper_options(struct e1000_
 	case 0:
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET)
-			printk(KERN_INFO
+			DPRINTK(PROBE, INFO,
 			       "Speed and duplex autonegotiation enabled\n");
 		break;
 	case HALF_DUPLEX:
-		printk(KERN_INFO "Half Duplex specified without Speed\n");
-		printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n");
+		DPRINTK(PROBE, INFO, "Half Duplex specified without Speed\n");
+		DPRINTK(PROBE, INFO,
+			"Using Autonegotiation at Half Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
 		                                 ADVERTISE_100_HALF;
 		break;
 	case FULL_DUPLEX:
-		printk(KERN_INFO "Full Duplex specified without Speed\n");
-		printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n");
+		DPRINTK(PROBE, INFO, "Full Duplex specified without Speed\n");
+		DPRINTK(PROBE, INFO,
+			"Using Autonegotiation at Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
 		                                 ADVERTISE_100_FULL |
 		                                 ADVERTISE_1000_FULL;
 		break;
 	case SPEED_10:
-		printk(KERN_INFO "10 Mbps Speed specified without Duplex\n");
-		printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n");
+		DPRINTK(PROBE, INFO,
+			"10 Mbps Speed specified without Duplex\n");
+		DPRINTK(PROBE, INFO, "Using Autonegotiation at 10 Mbps only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
 		                                 ADVERTISE_10_FULL;
 		break;
 	case SPEED_10 + HALF_DUPLEX:
-		printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n");
+		DPRINTK(PROBE, INFO, "Forcing to 10 Mbps Half Duplex\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 0;
 		adapter->hw.forced_speed_duplex = e1000_10_half;
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_10 + FULL_DUPLEX:
-		printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n");
+		DPRINTK(PROBE, INFO, "Forcing to 10 Mbps Full Duplex\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 0;
 		adapter->hw.forced_speed_duplex = e1000_10_full;
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_100:
-		printk(KERN_INFO "100 Mbps Speed specified without Duplex\n");
-		printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n");
+		DPRINTK(PROBE, INFO,
+			"100 Mbps Speed specified without Duplex\n");
+		DPRINTK(PROBE, INFO,
+			"Using Autonegotiation at 100 Mbps only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
 		                                 ADVERTISE_100_FULL;
 		break;
 	case SPEED_100 + HALF_DUPLEX:
-		printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n");
+		DPRINTK(PROBE, INFO, "Forcing to 100 Mbps Half Duplex\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 0;
 		adapter->hw.forced_speed_duplex = e1000_100_half;
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_100 + FULL_DUPLEX:
-		printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n");
+		DPRINTK(PROBE, INFO, "Forcing to 100 Mbps Full Duplex\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 0;
 		adapter->hw.forced_speed_duplex = e1000_100_full;
 		adapter->hw.autoneg_advertised = 0;
 		break;
 	case SPEED_1000:
-		printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n");
-		printk(KERN_INFO
+		DPRINTK(PROBE, INFO,
+			"1000 Mbps Speed specified without Duplex\n");
+		DPRINTK(PROBE, INFO,
 		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
 	case SPEED_1000 + HALF_DUPLEX:
-		printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n");
-		printk(KERN_INFO
+		DPRINTK(PROBE, INFO,
+			"Half Duplex is not supported at 1000 Mbps\n");
+		DPRINTK(PROBE, INFO,
 		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
 		break;
 	case SPEED_1000 + FULL_DUPLEX:
-		printk(KERN_INFO
+		DPRINTK(PROBE, INFO,
 		       "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
 		adapter->hw.autoneg = adapter->fc_autoneg = 1;
 		adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
@@ -685,7 +695,8 @@ e1000_check_copper_options(struct e1000_
 
 	/* Speed, AutoNeg and MDI/MDI-X must all play nice */
 	if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
-		printk(KERN_INFO "Speed, AutoNeg and MDI-X specifications are "
+		DPRINTK(PROBE, INFO,
+		       "Speed, AutoNeg and MDI-X specifications are "
 		       "incompatible. Setting MDI-X to a compatible value.\n");
 	}
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/eql.c linux-2.4.27-rc4/drivers/net/eql.c
--- linux-2.4.26/drivers/net/eql.c	2001-09-30 19:26:06.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/eql.c	2004-07-30 16:27:15.000000000 +0000
@@ -409,6 +409,8 @@ static int eql_enslave(struct net_device
 #endif  
 	master_dev = dev;		/* for "clarity" */
 	slave_dev  = __dev_get_by_name (srq.slave_name);
+	if (!slave_dev)
+		return -ENODEV;
 
 	if (master_dev != 0 && slave_dev != 0)
 	{
@@ -463,6 +465,8 @@ static int eql_emancipate(struct net_dev
 #endif
 	master_dev = dev;		/* for "clarity" */
 	slave_dev  = __dev_get_by_name (srq.slave_name);
+	if (!slave_dev)
+		return -ENODEV;
 
 	if ( eql_is_slave (slave_dev) )	/* really is a slave */
 	{
@@ -491,6 +495,8 @@ static int eql_g_slave_cfg(struct net_de
 #endif
 	eql = (equalizer_t *) dev->priv;
 	slave_dev = __dev_get_by_name (sc.slave_name);
+	if (!slave_dev)
+		return -ENODEV;
 
 	if ( eql_is_slave (slave_dev) )
 	{
@@ -525,6 +531,8 @@ static int eql_s_slave_cfg(struct net_de
 
 	eql = (equalizer_t *) dev->priv;
 	slave_dev = __dev_get_by_name (sc.slave_name);
+	if (!slave_dev)
+		return -ENODEV;
 
 	if ( eql_is_slave (slave_dev) )
 	{
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/fealnx.c linux-2.4.27-rc4/drivers/net/fealnx.c
--- linux-2.4.26/drivers/net/fealnx.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/fealnx.c	2004-07-30 16:29:54.000000000 +0000
@@ -85,6 +85,7 @@ static int full_duplex[MAX_UNITS] = { -1
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
+#include <linux/delay.h>
 
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/bitops.h>
@@ -234,15 +235,29 @@ enum intr_status_bits {
 	RxErr = 0x00000002,	/* receive error */
 };
 
-/* Bits in the NetworkConfig register. */
+/* Bits in the NetworkConfig register, W for writing, R for reading */
+/* FIXME: some names are invented by me. Marked with (name?) */
+/* If you have docs and know bit names, please fix 'em */
 enum rx_mode_bits {
-	RxModeMask = 0xe0,
-	PROM = 0x80,		/* promiscuous mode */
-	AB = 0x40,		/* accept broadcast */
-	AM = 0x20,		/* accept mutlicast */
-	ARP = 0x08,		/* receive runt pkt */
-	ALP = 0x04,		/* receive long pkt */
-	SEP = 0x02,		/* receive error pkt */
+	CR_W_ENH	= 0x02000000,	/* enhanced mode (name?) */
+	CR_W_FD		= 0x00100000,	/* full duplex */
+	CR_W_PS10	= 0x00080000,	/* 10 mbit */
+	CR_W_TXEN	= 0x00040000,	/* tx enable (name?) */
+	CR_W_PS1000	= 0x00010000,	/* 1000 mbit */
+     /* CR_W_RXBURSTMASK= 0x00000e00, Im unsure about this */
+	CR_W_RXMODEMASK	= 0x000000e0,
+	CR_W_PROM	= 0x00000080,	/* promiscuous mode */
+	CR_W_AB		= 0x00000040,	/* accept broadcast */
+	CR_W_AM		= 0x00000020,	/* accept mutlicast */
+	CR_W_ARP	= 0x00000008,	/* receive runt pkt */
+	CR_W_ALP	= 0x00000004,	/* receive long pkt */
+	CR_W_SEP	= 0x00000002,	/* receive error pkt */
+	CR_W_RXEN	= 0x00000001,	/* rx enable (unicast?) (name?) */
+
+	CR_R_TXSTOP	= 0x04000000,	/* tx stopped (name?) */
+	CR_R_FD		= 0x00100000,	/* full duplex detected */
+	CR_R_PS10	= 0x00080000,	/* 10 mbit detected */
+	CR_R_RXSTOP	= 0x00008000,	/* rx stopped (name?) */
 };
 
 /* The Tulip Rx and Tx buffer descriptors. */
@@ -376,10 +391,7 @@ enum tx_desc_control_bits {
 #define LXT1000_Full    0x200
 // 89/12/29 add, for phy specific status register, levelone phy, (end)
 
-/* for 3-in-1 case */
-#define PS10            0x00080000
-#define FD              0x00100000
-#define PS1000          0x00010000
+/* for 3-in-1 case, BMCRSR register */
 #define LinkIsUp2	0x00040000
 
 /* for PHY */
@@ -401,6 +413,12 @@ struct netdev_private {
 	/* Media monitoring timer. */
 	struct timer_list timer;
 
+	/* Reset timer */
+	struct timer_list reset_timer;
+	int reset_timer_armed;
+	unsigned long crvalue_sv;
+	unsigned long imrvalue_sv;
+
 	/* Frequently used values: keep some adjacent for cache effect. */
 	int flags;
 	struct pci_dev *pci_dev;
@@ -436,49 +454,44 @@ static int netdev_open(struct net_device
 static void getlinktype(struct net_device *dev);
 static void getlinkstatus(struct net_device *dev);
 static void netdev_timer(unsigned long data);
+static void reset_timer(unsigned long data);
 static void tx_timeout(struct net_device *dev);
 static void init_ring(struct net_device *dev);
 static int start_tx(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
 static int netdev_rx(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+static void __set_rx_mode(struct net_device *dev);
 static struct net_device_stats *get_stats(struct net_device *dev);
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static int netdev_close(struct net_device *dev);
 static void reset_rx_descriptors(struct net_device *dev);
+static void reset_tx_descriptors(struct net_device *dev);
 
-void stop_nic_tx(long ioaddr, long crvalue)
+static void stop_nic_rx(long ioaddr, long crvalue)
 {
-	writel(crvalue & (~0x40000), ioaddr + TCRRCR);
-
-	/* wait for tx stop */
-	{
-		int i = 0, delay = 0x1000;
-
-		while ((!(readl(ioaddr + TCRRCR) & 0x04000000)) && (i < delay)) {
-			++i;
-		}
+	int delay = 0x1000;
+	writel(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR);
+	while (--delay) {
+		if ( (readl(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP)
+			break;
 	}
 }
 
 
-void stop_nic_rx(long ioaddr, long crvalue)
+static void stop_nic_rxtx(long ioaddr, long crvalue)
 {
-	writel(crvalue & (~0x1), ioaddr + TCRRCR);
-
-	/* wait for rx stop */
-	{
-		int i = 0, delay = 0x1000;
-
-		while ((!(readl(ioaddr + TCRRCR) & 0x00008000)) && (i < delay)) {
-			++i;
-		}
+	int delay = 0x1000;
+	writel(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR);
+	while (--delay) {
+		if ( (readl(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP))
+					    == (CR_R_RXSTOP+CR_R_TXSTOP) )
+			break;
 	}
 }
 
 
-
 static int __devinit fealnx_init_one(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
@@ -496,7 +509,7 @@ static int __devinit fealnx_init_one(str
 #ifndef MODULE
 	static int printed_version;
 	if (!printed_version++)
-		printk (version);
+		printk(version);
 #endif
 	
 	card_idx++;
@@ -622,7 +635,7 @@ static int __devinit fealnx_init_one(str
 		np->phys[0] = 32;
 /* 89/6/23 add, (begin) */
 		/* get phy type */
-		if (readl(dev->base_addr + PHYIDENTIFIER) == MysonPHYID)
+		if (readl(ioaddr + PHYIDENTIFIER) == MysonPHYID)
 			np->PHYType = MysonPHY;
 		else
 			np->PHYType = OtherPHY;
@@ -657,7 +670,7 @@ static int __devinit fealnx_init_one(str
 		if (np->flags == HAS_MII_XCVR)
 			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		else
-			writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);
+			writel(ADVERTISE_FULL, ioaddr + ANARANLPAR);
 		np->mii.force_media = 1;
 	}
 
@@ -669,7 +682,7 @@ static int __devinit fealnx_init_one(str
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &mii_ioctl;
 	dev->ethtool_ops = &netdev_ethtool_ops;
-	dev->tx_timeout = tx_timeout;
+	dev->tx_timeout = &tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	
 	err = register_netdev(dev);
@@ -699,6 +712,7 @@ err_out_res:
 	return err;
 }
 
+
 static void __devexit fealnx_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -721,42 +735,6 @@ static void __devexit fealnx_remove_one(
 		printk(KERN_ERR "fealnx: remove for unknown device\n");
 }
 
-unsigned int m80x_read_tick(void)
-/* function: Reads the Timer tick count register which decrements by 2 from  */
-/*           65536 to 0 every 1/36.414 of a second. Each 2 decrements of the *//*           count represents 838 nsec's.                                    */
-/* input   : none.                                                           */
-/* output  : none.                                                           */
-{
-	unsigned char tmp;
-	int value;
-
-	writeb((char) 0x06, 0x43);	// Command 8254 to latch T0's count
-
-	// now read the count.
-	tmp = (unsigned char) readb(0x40);
-	value = ((int) tmp) << 8;
-	tmp = (unsigned char) readb(0x40);
-	value |= (((int) tmp) & 0xff);
-	return (value);
-}
-
-
-void m80x_delay(unsigned int interval)
-/* function: to wait for a specified time.                                   */
-/* input   : interval ... the specified time.                                */
-/* output  : none.                                                           */
-{
-	unsigned int interval1, interval2, i = 0;
-
-	interval1 = m80x_read_tick();	// get initial value
-	do {
-		interval2 = m80x_read_tick();
-		if (interval1 < interval2)
-			interval1 = interval2;
-		++i;
-	} while (((interval1 - interval2) < (ushort) interval) && (i < 65535));
-}
-
 
 static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
 {
@@ -796,7 +774,7 @@ static ulong m80x_send_cmd_to_phy(long m
 		/* high MDC */
 		miir |= MASK_MIIR_MII_MDC;
 		writel(miir, miiport);
-		m80x_delay(30);
+		udelay(30);
 
 		/* next */
 		mask >>= 1;
@@ -831,7 +809,7 @@ static int mdio_read(struct net_device *
 		/* high MDC, and wait */
 		miir |= MASK_MIIR_MII_MDC;
 		writel(miir, miiport);
-		m80x_delay((int) 30);
+		udelay(30);
 
 		/* next */
 		mask >>= 1;
@@ -873,8 +851,6 @@ static void mdio_write(struct net_device
 	/* low MDC */
 	miir &= ~MASK_MIIR_MII_MDC;
 	writel(miir, miiport);
-
-	return;
 }
 
 
@@ -949,7 +925,7 @@ static int netdev_open(struct net_device
 	np->imrvalue = TUNF | CNTOVF | RBU | TI | RI;
 	if (np->pci_dev->device == 0x891) {
 		np->bcrvalue |= 0x200;	/* set PROG bit */
-		np->crvalue |= 0x02000000;	/* set enhanced bit */
+		np->crvalue |= CR_W_ENH;	/* set enhanced bit */
 		np->imrvalue |= ETI;
 	}
 	writel(np->bcrvalue, ioaddr + BCR);
@@ -957,7 +933,7 @@ static int netdev_open(struct net_device
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	writel(0, dev->base_addr + RXPDR);
+	writel(0, ioaddr + RXPDR);
 // 89/9/1 modify,
 //   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
 	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
@@ -965,7 +941,7 @@ static int netdev_open(struct net_device
 	getlinkstatus(dev);
 	if (np->linkok)
 		getlinktype(dev);
-	set_rx_mode(dev);
+	__set_rx_mode(dev);
 
 	netif_start_queue(dev);
 
@@ -985,6 +961,11 @@ static int netdev_open(struct net_device
 	/* timer handler */
 	add_timer(&np->timer);
 
+	init_timer(&np->reset_timer);
+	np->reset_timer.data = (unsigned long) dev;
+	np->reset_timer.function = &reset_timer;
+	np->reset_timer_armed = 0;
+
 	return 0;
 }
 
@@ -1005,8 +986,7 @@ static void getlinkstatus(struct net_dev
 				np->linkok = 1;
 				return;
 			}
-			// delay
-			m80x_delay(100);
+			udelay(100);
 		}
 	} else {
 		for (i = 0; i < DelayTime; ++i) {
@@ -1014,8 +994,7 @@ static void getlinkstatus(struct net_dev
 				np->linkok = 1;
 				return;
 			}
-			// delay
-			m80x_delay(100);
+			udelay(100);
 		}
 	}
 }
@@ -1026,11 +1005,11 @@ static void getlinktype(struct net_devic
 	struct netdev_private *np = dev->priv;
 
 	if (np->PHYType == MysonPHY) {	/* 3-in-1 case */
-		if (readl(dev->base_addr + TCRRCR) & FD)
+		if (readl(dev->base_addr + TCRRCR) & CR_R_FD)
 			np->duplexmode = 2;	/* full duplex */
 		else
 			np->duplexmode = 1;	/* half duplex */
-		if (readl(dev->base_addr + TCRRCR) & PS10)
+		if (readl(dev->base_addr + TCRRCR) & CR_R_PS10)
 			np->line_speed = 1;	/* 10M */
 		else
 			np->line_speed = 2;	/* 100M */
@@ -1112,19 +1091,18 @@ static void getlinktype(struct net_devic
 			else
 				np->line_speed = 1;	/* 10M */
 		}
-		// chage crvalue
-		// np->crvalue&=(~PS10)&(~FD);
-		np->crvalue &= (~PS10) & (~FD) & (~PS1000);
+		np->crvalue &= (~CR_W_PS10) & (~CR_W_FD) & (~CR_W_PS1000);
 		if (np->line_speed == 1)
-			np->crvalue |= PS10;
+			np->crvalue |= CR_W_PS10;
 		else if (np->line_speed == 3)
-			np->crvalue |= PS1000;
+			np->crvalue |= CR_W_PS1000;
 		if (np->duplexmode == 2)
-			np->crvalue |= FD;
+			np->crvalue |= CR_W_FD;
 	}
 }
 
 
+/* Take lock before calling this */
 static void allocate_rx_buffers(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
@@ -1134,15 +1112,17 @@ static void allocate_rx_buffers(struct n
 		struct sk_buff *skb;
 
 		skb = dev_alloc_skb(np->rx_buf_sz);
-		np->lack_rxbuf->skbuff = skb;
-
 		if (skb == NULL)
 			break;	/* Better luck next round. */
 
+		while (np->lack_rxbuf->skbuff)
+			np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+
 		skb->dev = dev;	/* Mark as being used by this device. */
+		np->lack_rxbuf->skbuff = skb;
 		np->lack_rxbuf->buffer = pci_map_single(np->pci_dev, skb->tail,
 			np->rx_buf_sz, PCI_DMA_FROMDEVICE);
-		np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+		np->lack_rxbuf->status = RXOWN;
 		++np->really_rx_count;
 	}
 }
@@ -1153,22 +1133,23 @@ static void netdev_timer(unsigned long d
 	struct net_device *dev = (struct net_device *) data;
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	int next_tick = 10 * HZ;
 	int old_crvalue = np->crvalue;
 	unsigned int old_linkok = np->linkok;
+	unsigned long flags;
 
 	if (debug)
 		printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "
 		       "config %8.8x.\n", dev->name, readl(ioaddr + ISR),
 		       readl(ioaddr + TCRRCR));
 
+	spin_lock_irqsave(&np->lock, flags);
+
 	if (np->flags == HAS_MII_XCVR) {
 		getlinkstatus(dev);
 		if ((old_linkok == 0) && (np->linkok == 1)) {	/* we need to detect the media type again */
 			getlinktype(dev);
 			if (np->crvalue != old_crvalue) {
-				stop_nic_tx(ioaddr, np->crvalue);
-				stop_nic_rx(ioaddr, np->crvalue & (~0x40000));
+				stop_nic_rxtx(ioaddr, np->crvalue);
 				writel(np->crvalue, ioaddr + TCRRCR);
 			}
 		}
@@ -1176,69 +1157,120 @@ static void netdev_timer(unsigned long d
 
 	allocate_rx_buffers(dev);
 
-	np->timer.expires = RUN_AT(next_tick);
+	spin_unlock_irqrestore(&np->lock, flags);
+
+	np->timer.expires = RUN_AT(10 * HZ);
 	add_timer(&np->timer);
 }
 
 
-static void tx_timeout(struct net_device *dev)
+/* Take lock before calling */
+/* Reset chip and disable rx, tx and interrupts */
+static void reset_and_disable_rxtx(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	int i;
-
-	printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
-	       " resetting...\n", dev->name, readl(ioaddr + ISR));
-
-	{
-
-		printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
-		for (i = 0; i < RX_RING_SIZE; i++)
-			printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
-		printk("\n" KERN_DEBUG "  Tx ring %p: ", np->tx_ring);
-		for (i = 0; i < TX_RING_SIZE; i++)
-			printk(" %4.4x", np->tx_ring[i].status);
-		printk("\n");
-	}
-
-	/* Reinit. Gross */
+	int delay=51;
 
 	/* Reset the chip's Tx and Rx processes. */
-	stop_nic_tx(ioaddr, 0);
-	reset_rx_descriptors(dev);
+	stop_nic_rxtx(ioaddr, 0);
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	writel(0x0000, ioaddr + IMR);
+	writel(0, ioaddr + IMR);
 
 	/* Reset the chip to erase previous misconfiguration. */
 	writel(0x00000001, ioaddr + BCR);
 
 	/* Ueimor: wait for 50 PCI cycles (and flush posted writes btw). 
-	   We surely wait too long (address+data phase). Who cares ? */
-	for (i = 0; i < 50; i++) {
+	   We surely wait too long (address+data phase). Who cares? */
+	while (--delay) {
 		readl(ioaddr + BCR);
 		rmb();
 	}
+}
+
+
+/* Take lock before calling */
+/* Restore chip after reset */
+static void enable_rxtx(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	reset_rx_descriptors(dev);
 
-	writel((np->cur_tx - np->tx_ring)*sizeof(struct fealnx_desc) +
-		np->tx_ring_dma, ioaddr + TXLBA);
-	writel((np->cur_rx - np->rx_ring)*sizeof(struct fealnx_desc) +
-		np->rx_ring_dma, ioaddr + RXLBA);
+	writel(np->tx_ring_dma + ((char*)np->cur_tx - (char*)np->tx_ring),
+		ioaddr + TXLBA);
+	writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
+		ioaddr + RXLBA);
 
 	writel(np->bcrvalue, ioaddr + BCR);
 
-	writel(0, dev->base_addr + RXPDR);
-	set_rx_mode(dev);
+	writel(0, ioaddr + RXPDR);
+	__set_rx_mode(dev); /* changes np->crvalue, writes it into TCRRCR */
+
 	/* Clear and Enable interrupts by setting the interrupt mask. */
 	writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
 	writel(np->imrvalue, ioaddr + IMR);
 
-	writel(0, dev->base_addr + TXPDR);
+	writel(0, ioaddr + TXPDR);
+}
+
+
+static void reset_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct netdev_private *np = dev->priv;
+	unsigned long flags;
+
+	printk(KERN_WARNING "%s: resetting tx and rx machinery\n", dev->name);
+
+	spin_lock_irqsave(&np->lock, flags);
+	np->crvalue = np->crvalue_sv;
+	np->imrvalue = np->imrvalue_sv;
+
+	reset_and_disable_rxtx(dev);
+	/* works for me without this:
+	reset_tx_descriptors(dev); */
+	enable_rxtx(dev);
+	netif_start_queue(dev); /* FIXME: or netif_wake_queue(dev); ? */
+		
+	np->reset_timer_armed = 0;
+
+	spin_unlock_irqrestore(&np->lock, flags);
+}
+
+
+static void tx_timeout(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	unsigned long flags;
+	int i;
+
+	printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
+	       " resetting...\n", dev->name, readl(ioaddr + ISR));
+
+	{
+		printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
+		for (i = 0; i < RX_RING_SIZE; i++)
+			printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
+		printk("\n" KERN_DEBUG "  Tx ring %p: ", np->tx_ring);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk(" %4.4x", np->tx_ring[i].status);
+		printk("\n");
+	}
+	
+	spin_lock_irqsave(&np->lock, flags);
+
+	reset_and_disable_rxtx(dev);
+	reset_tx_descriptors(dev);
+	enable_rxtx(dev);
+
+	spin_unlock_irqrestore(&np->lock, flags);
 
 	dev->trans_start = jiffies;
 	np->stats.tx_errors++;
-
-	return;
+	netif_wake_queue(dev); /* or .._start_.. ?? */
 }
 
 
@@ -1251,7 +1283,7 @@ static void init_ring(struct net_device 
 	/* initialize rx variables */
 	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 	np->cur_rx = &np->rx_ring[0];
-	np->lack_rxbuf = NULL;
+	np->lack_rxbuf = np->rx_ring;
 	np->really_rx_count = 0;
 
 	/* initial rx descriptors. */
@@ -1294,6 +1326,7 @@ static void init_ring(struct net_device 
 
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		np->tx_ring[i].status = 0;
+		/* do we need np->tx_ring[i].control = XXX; ?? */
 		np->tx_ring[i].next_desc = np->tx_ring_dma +
 			(i + 1)*sizeof(struct fealnx_desc);
 		np->tx_ring[i].next_desc_logical = &np->tx_ring[i + 1];
@@ -1303,8 +1336,6 @@ static void init_ring(struct net_device 
 	/* for the last tx descriptor */
 	np->tx_ring[i - 1].next_desc = np->tx_ring_dma;
 	np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0];
-
-	return;
 }
 
 
@@ -1340,7 +1371,7 @@ static int start_tx(struct sk_buff *skb,
 		np->cur_tx_copy->control |= (BPT << TBSShift);	/* buffer size */
 
 		/* for the last descriptor */
-		next = (struct fealnx *) np->cur_tx_copy.next_desc_logical;
+		next = np->cur_tx_copy->next_desc_logical;
 		next->skbuff = skb;
 		next->control = TXIC | TXLD | CRCEnable | PADEnable;
 		next->control |= (skb->len << PKTSShift);	/* pkt size */
@@ -1381,35 +1412,59 @@ static int start_tx(struct sk_buff *skb,
 }
 
 
-void free_one_rx_descriptor(struct netdev_private *np)
+/* Take lock before calling */
+/* Chip probably hosed tx ring. Clean up. */
+static void reset_tx_descriptors(struct net_device *dev)
 {
-	if (np->really_rx_count == RX_RING_SIZE)
-		np->cur_rx->status = RXOWN;
-	else {
-		np->lack_rxbuf->skbuff = np->cur_rx->skbuff;
-		np->lack_rxbuf->buffer = np->cur_rx->buffer;
-		np->lack_rxbuf->status = RXOWN;
-		++np->really_rx_count;
-		np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+	struct netdev_private *np = dev->priv;
+	struct fealnx_desc *cur;
+	int i;
+
+	/* initialize tx variables */
+	np->cur_tx = &np->tx_ring[0];
+	np->cur_tx_copy = &np->tx_ring[0];
+	np->really_tx_count = 0;
+	np->free_tx_count = TX_RING_SIZE;
+
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		cur = &np->tx_ring[i];
+		if (cur->skbuff) {
+			pci_unmap_single(np->pci_dev, cur->buffer,
+				cur->skbuff->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb(cur->skbuff);
+			/* or dev_kfree_skb_irq(cur->skbuff); ? */
+			cur->skbuff = NULL;
+		}
+		cur->status = 0;
+		cur->control = 0;	/* needed? */
+		/* probably not needed. We do it for purely paranoid reasons */
+		cur->next_desc = np->tx_ring_dma +
+			(i + 1)*sizeof(struct fealnx_desc);
+		cur->next_desc_logical = &np->tx_ring[i + 1];
 	}
-	np->cur_rx = np->cur_rx->next_desc_logical;
+	/* for the last tx descriptor */
+	np->tx_ring[TX_RING_SIZE - 1].next_desc = np->tx_ring_dma;
+	np->tx_ring[TX_RING_SIZE - 1].next_desc_logical = &np->tx_ring[0];
 }
 
 
-void reset_rx_descriptors(struct net_device *dev)
+/* Take lock and stop rx before calling this */
+static void reset_rx_descriptors(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
-
-	stop_nic_rx(dev->base_addr, np->crvalue);
-
-	while (!(np->cur_rx->status & RXOWN))
-		free_one_rx_descriptor(np);
+	struct fealnx_desc *cur = np->cur_rx;
+	int i;
 
 	allocate_rx_buffers(dev);
 
-	writel(np->rx_ring_dma + (np->cur_rx - np->rx_ring),
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		if (cur->skbuff)
+			cur->status = RXOWN;
+		cur = cur->next_desc_logical;
+	}
+
+	writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
 		dev->base_addr + RXLBA);
-	writel(np->crvalue, dev->base_addr + TCRRCR);
 }
 
 
@@ -1419,14 +1474,14 @@ static irqreturn_t intr_handler(int irq,
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct netdev_private *np = dev->priv;
-	long ioaddr, boguscnt = max_interrupt_work;
+	long ioaddr = dev->base_addr;
+	long boguscnt = max_interrupt_work;
 	unsigned int num_tx = 0;
 	int handled = 0;
 
-	writel(0, dev->base_addr + IMR);
+	spin_lock(&np->lock);
 
-	ioaddr = dev->base_addr;
-	np = (struct netdev_private *) dev->priv;
+	writel(0, ioaddr + IMR);
 
 	do {
 		u32 intr_status = readl(ioaddr + ISR);
@@ -1467,8 +1522,11 @@ static irqreturn_t intr_handler(int irq,
 		if (intr_status & (RI | RBU)) {
 			if (intr_status & RI)
 				netdev_rx(dev);
-			else
+			else {
+				stop_nic_rx(ioaddr, np->crvalue);
 				reset_rx_descriptors(dev);
+				writel(np->crvalue, ioaddr + TCRRCR);
+			}				
 		}
 
 		while (np->really_tx_count) {
@@ -1486,7 +1544,7 @@ static irqreturn_t intr_handler(int irq,
 			if (tx_status & TXOWN)
 				break;
 
-			if (!(np->crvalue & 0x02000000)) {
+			if (!(np->crvalue & CR_W_ENH)) {
 				if (tx_status & (CSL | LC | EC | UDF | HF)) {
 					np->stats.tx_errors++;
 					if (tx_status & EC)
@@ -1535,7 +1593,7 @@ static irqreturn_t intr_handler(int irq,
 			netif_wake_queue(dev);
 
 		/* read transmit status for enhanced mode only */
-		if (np->crvalue & 0x02000000) {
+		if (np->crvalue & CR_W_ENH) {
 			long data;
 
 			data = readl(ioaddr + TSR);
@@ -1548,6 +1606,20 @@ static irqreturn_t intr_handler(int irq,
 		if (--boguscnt < 0) {
 			printk(KERN_WARNING "%s: Too much work at interrupt, "
 			       "status=0x%4.4x.\n", dev->name, intr_status);
+			if (!np->reset_timer_armed) {
+				np->reset_timer_armed = 1;
+				np->reset_timer.expires = RUN_AT(HZ/2);
+				add_timer(&np->reset_timer);
+				stop_nic_rxtx(ioaddr, 0);
+				netif_stop_queue(dev);
+				/* or netif_tx_disable(dev); ?? */
+				/* Prevent other paths from enabling tx,rx,intrs */
+				np->crvalue_sv = np->crvalue;
+				np->imrvalue_sv = np->imrvalue;
+				np->crvalue &= ~(CR_W_TXEN | CR_W_RXEN); /* or simply = 0? */
+				np->imrvalue = 0;
+			}
+
 			break;
 		}
 	} while (1);
@@ -1565,6 +1637,8 @@ static irqreturn_t intr_handler(int irq,
 
 	writel(np->imrvalue, ioaddr + IMR);
 
+	spin_unlock(&np->lock);
+
 	return IRQ_RETVAL(handled);
 }
 
@@ -1574,9 +1648,10 @@ static irqreturn_t intr_handler(int irq,
 static int netdev_rx(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
-	while (!(np->cur_rx->status & RXOWN)) {
+	while (!(np->cur_rx->status & RXOWN) && np->cur_rx->skbuff) {
 		s32 rx_status = np->cur_rx->status;
 
 		if (np->really_rx_count == 0)
@@ -1628,11 +1703,20 @@ static int netdev_rx(struct net_device *
 					np->stats.rx_length_errors++;
 
 					/* free all rx descriptors related this long pkt */
-					for (i = 0; i < desno; ++i)
-						free_one_rx_descriptor(np);
+					for (i = 0; i < desno; ++i) {
+						if (!np->cur_rx->skbuff) {
+							printk(KERN_DEBUG
+								"%s: I'm scared\n", dev->name);
+							break;
+						}
+						np->cur_rx->status = RXOWN;
+						np->cur_rx = np->cur_rx->next_desc_logical;
+					}
 					continue;
-				} else {	/* something error, need to reset this chip */
+				} else {        /* rx error, need to reset this chip */
+					stop_nic_rx(ioaddr, np->crvalue);
 					reset_rx_descriptors(dev);
+					writel(np->crvalue, ioaddr + TCRRCR);
 				}
 				break;	/* exit the while loop */
 			}
@@ -1671,8 +1755,6 @@ static int netdev_rx(struct net_device *
 			} else {
 				skb_put(skb = np->cur_rx->skbuff, pkt_len);
 				np->cur_rx->skbuff = NULL;
-				if (np->really_rx_count == RX_RING_SIZE)
-					np->lack_rxbuf = np->cur_rx;
 				--np->really_rx_count;
 			}
 			skb->protocol = eth_type_trans(skb, dev);
@@ -1682,22 +1764,7 @@ static int netdev_rx(struct net_device *
 			np->stats.rx_bytes += pkt_len;
 		}
 
-		if (np->cur_rx->skbuff == NULL) {
-			struct sk_buff *skb;
-
-			skb = dev_alloc_skb(np->rx_buf_sz);
-
-			if (skb != NULL) {
-				skb->dev = dev;	/* Mark as being used by this device. */
-				np->cur_rx->buffer = pci_map_single(np->pci_dev, skb->tail,
-					np->rx_buf_sz, PCI_DMA_FROMDEVICE);
-				np->cur_rx->skbuff = skb;
-				++np->really_rx_count;
-			}
-		}
-
-		if (np->cur_rx->skbuff != NULL)
-			free_one_rx_descriptor(np);
+		np->cur_rx = np->cur_rx->next_desc_logical;
 	}			/* end of while loop */
 
 	/*  allocate skb for rx buffers */
@@ -1721,8 +1788,21 @@ static struct net_device_stats *get_stat
 	return &np->stats;
 }
 
+
+/* for dev->set_multicast_list */
 static void set_rx_mode(struct net_device *dev)
 {
+	spinlock_t *lp = &((struct netdev_private *)dev->priv)->lock;
+	unsigned long flags;
+	spin_lock_irqsave(lp, flags);
+	__set_rx_mode(dev);
+	spin_unlock_irqrestore(&lp, flags);
+}
+
+
+/* Take lock before calling */
+static void __set_rx_mode(struct net_device *dev)
+{
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
 	u32 mc_filter[2];	/* Multicast hash filter */
@@ -1732,12 +1812,12 @@ static void set_rx_mode(struct net_devic
 		/* Unconditionally log net taps. */
 		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
-		rx_mode = PROM | AB | AM;
+		rx_mode = CR_W_PROM | CR_W_AB | CR_W_AM;
 	} else if ((dev->mc_count > multicast_filter_limit)
 		   || (dev->flags & IFF_ALLMULTI)) {
 		/* Too many to match, or accept all multicasts. */
 		memset(mc_filter, 0xff, sizeof(mc_filter));
-		rx_mode = AB | AM;
+		rx_mode = CR_W_AB | CR_W_AM;
 	} else {
 		struct dev_mc_list *mclist;
 		int i;
@@ -1749,26 +1829,25 @@ static void set_rx_mode(struct net_devic
 			bit = (ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F;
 			mc_filter[bit >> 5] |= (1 << bit);
 		}
-		rx_mode = AB | AM;
+		rx_mode = CR_W_AB | CR_W_AM;
 	}
 
-	stop_nic_tx(ioaddr, np->crvalue);
-	stop_nic_rx(ioaddr, np->crvalue & (~0x40000));
+	stop_nic_rxtx(ioaddr, np->crvalue);
 
 	writel(mc_filter[0], ioaddr + MAR0);
 	writel(mc_filter[1], ioaddr + MAR1);
-	np->crvalue &= ~RxModeMask;
+	np->crvalue &= ~CR_W_RXMODEMASK;
 	np->crvalue |= rx_mode;
 	writel(np->crvalue, ioaddr + TCRRCR);
 }
 
-static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
+static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct netdev_private *np = dev->priv;
 
-	strcpy (info->driver, DRV_NAME);
-	strcpy (info->version, DRV_VERSION);
-	strcpy (info->bus_info, pci_name(np->pci_dev));
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, pci_name(np->pci_dev));
 }
 
 static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -1858,10 +1937,10 @@ static int netdev_close(struct net_devic
 	writel(0x0000, ioaddr + IMR);
 
 	/* Stop the chip's Tx and Rx processes. */
-	stop_nic_tx(ioaddr, 0);
-	stop_nic_rx(ioaddr, 0);
+	stop_nic_rxtx(ioaddr, 0);
 
 	del_timer_sync(&np->timer);
+	del_timer_sync(&np->reset_timer);
 
 	free_irq(dev->irq, dev);
 
@@ -1912,7 +1991,7 @@ static int __init fealnx_init(void)
 {
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
-	printk (version);
+	printk(version);
 #endif
 
 	return pci_module_init(&fealnx_driver);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/ibmveth.c linux-2.4.27-rc4/drivers/net/ibmveth.c
--- linux-2.4.26/drivers/net/ibmveth.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/ibmveth.c	2004-07-30 16:30:12.000000000 +0000
@@ -0,0 +1,1121 @@
+/**************************************************************************/
+/*                                                                        */
+/* IBM eServer i/pSeries Virtual Ethernet Device Driver                   */
+/* Copyright (C) 2003 Dave Larson (larson1@us.ibm.com), IBM Corp.         */
+/*                                                                        */
+/*  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  */
+/*                                                                        */
+/* This module contains the implementation of a virtual ethernet device   */
+/* for use with IBM i/pSeries LPAR Linux.  It utilizes the logical LAN    */
+/* option of the RS/6000 Platform Architechture to interface with virtual */
+/* ethernet NICs that are presented to the partition by the hypervisor.   */
+/*                                                                        */ 
+/**************************************************************************/
+/*
+  TODO:
+  - remove frag processing code - no longer needed
+  - add support for sysfs
+  - possibly remove procfs support
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.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/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/ethtool.h>
+#include <linux/proc_fs.h>
+#include <asm/semaphore.h>
+#include <asm/hvcall.h>
+#include <asm/atomic.h>
+#include <asm/pci_dma.h>
+#include <asm/vio.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "ibmveth.h"
+
+#define DEBUG 1
+
+#define ibmveth_printk(fmt, args...) \
+  printk(KERN_INFO "%s: " fmt, __FILE__, ## args)
+
+#define ibmveth_error_printk(fmt, args...) \
+  printk(KERN_ERR "(%s:%3.3d ua:%lx) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
+
+#ifdef DEBUG
+#define ibmveth_debug_printk_no_adapter(fmt, args...) \
+  printk(KERN_DEBUG "(%s:%3.3d): " fmt, __FILE__, __LINE__ , ## args)
+#define ibmveth_debug_printk(fmt, args...) \
+  printk(KERN_DEBUG "(%s:%3.3d ua:%lx): " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
+#define ibmveth_assert(expr) \
+  if(!(expr)) {                                   \
+    printk(KERN_DEBUG "assertion failed (%s:%3.3d ua:%lx): %s\n", __FILE__, __LINE__, adapter->vdev->unit_address, #expr); \
+    BUG(); \
+  }
+#else
+#define ibmveth_debug_printk_no_adapter(fmt, args...)
+#define ibmveth_debug_printk(fmt, args...)
+#define ibmveth_assert(expr) 
+#endif
+
+static int ibmveth_open(struct net_device *dev);
+static int ibmveth_close(struct net_device *dev);
+static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int ibmveth_poll(struct net_device *dev, int *budget);
+static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static struct net_device_stats *ibmveth_get_stats(struct net_device *dev);
+static void ibmveth_set_multicast_list(struct net_device *dev);
+static void ibmveth_proc_register_driver(void);
+static void ibmveth_proc_unregister_driver(void);
+static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter);
+static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
+
+#define IBMVETH_PROC_DIR "ibmveth"
+static struct proc_dir_entry *ibmveth_proc_dir;
+
+static const char ibmveth_driver_name[] = "ibmveth";
+static const char ibmveth_driver_string[] = "IBM i/pSeries Virtual Ethernet Driver";
+static const char ibmveth_driver_version[] = "1.0";
+
+MODULE_AUTHOR("Dave Larson <larson1@us.ibm.com>");
+MODULE_DESCRIPTION("IBM i/pSeries Virtual Ethernet Driver");
+MODULE_LICENSE("GPL");
+
+/* simple methods of getting data from the current rxq entry */
+static inline int ibmveth_rxq_pending_buffer(struct ibmveth_adapter *adapter)
+{
+	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].toggle == adapter->rx_queue.toggle);
+}
+
+static inline int ibmveth_rxq_buffer_valid(struct ibmveth_adapter *adapter)
+{
+	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].valid);
+}
+
+static inline int ibmveth_rxq_frame_offset(struct ibmveth_adapter *adapter)
+{
+	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].offset);
+}
+
+static inline int ibmveth_rxq_frame_length(struct ibmveth_adapter *adapter)
+{
+	return (adapter->rx_queue.queue_addr[adapter->rx_queue.index].length);
+}
+
+/* setup the initial settings for a buffer pool */
+static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size)
+{
+	pool->size = pool_size;
+	pool->index = pool_index;
+	pool->buff_size = buff_size;
+	pool->threshold = pool_size / 2;
+}
+
+/* allocate and setup an buffer pool - called during open */
+static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
+{
+	int i;
+
+	pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); 
+
+	if(!pool->free_map) {
+		return -1;
+	}
+
+	pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); 
+	if(!pool->dma_addr) {
+		kfree(pool->free_map);
+		pool->free_map = NULL;
+		return -1;
+	}
+
+	pool->skbuff = kmalloc(sizeof(void*) * pool->size, GFP_KERNEL);
+
+	if(!pool->skbuff) {
+		kfree(pool->dma_addr);
+		pool->dma_addr = NULL;
+
+		kfree(pool->free_map);
+		pool->free_map = NULL;
+		return -1;
+	}
+
+	memset(pool->skbuff, 0, sizeof(void*) * pool->size);
+	memset(pool->dma_addr, 0, sizeof(dma_addr_t) * pool->size);
+
+	for(i = 0; i < pool->size; ++i) {
+		pool->free_map[i] = i;
+	}
+
+	atomic_set(&pool->available, 0);
+	pool->producer_index = 0;
+	pool->consumer_index = 0;
+
+	return 0;
+}
+
+/* replenish the buffers for a pool.  note that we don't need to
+ * skb_reserve these since they are used for incoming...
+ */
+static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
+{
+	u32 i;
+	u32 count = pool->size - atomic_read(&pool->available);
+	u32 buffers_added = 0;
+
+	mb();
+
+	for(i = 0; i < count; ++i) {
+		struct sk_buff *skb;
+		unsigned int free_index, index;
+		u64 correlator;
+		union ibmveth_buf_desc desc;
+		unsigned long lpar_rc;
+		dma_addr_t dma_addr;
+
+		skb = alloc_skb(pool->buff_size, GFP_ATOMIC);
+
+		if(!skb) {
+			ibmveth_debug_printk("replenish: unable to allocate skb\n");
+			adapter->replenish_no_mem++;
+			break;
+		}
+
+		free_index = pool->consumer_index++ % pool->size;
+		index = pool->free_map[free_index];
+	
+		ibmveth_assert(index != 0xffff);
+		ibmveth_assert(pool->skbuff[index] == NULL);
+
+		dma_addr = vio_map_single(adapter->vdev, skb->data, pool->buff_size, PCI_DMA_FROMDEVICE);
+
+		pool->dma_addr[index] = dma_addr;
+		pool->skbuff[index] = skb;
+
+		correlator = ((u64)pool->index << 32) | index;
+		*(u64*)skb->data = correlator;
+
+		desc.desc = 0;
+		desc.fields.valid = 1;
+		desc.fields.length = pool->buff_size;
+		desc.fields.address = dma_addr; 
+
+		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
+		    
+		if(lpar_rc != H_Success) {
+			pool->skbuff[index] = NULL;
+			pool->consumer_index--;
+			vio_unmap_single(adapter->vdev, pool->dma_addr[index], pool->buff_size, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb_any(skb);
+			adapter->replenish_add_buff_failure++;
+			break;
+		} else {
+			pool->free_map[free_index] = 0xffff;
+			buffers_added++;
+			adapter->replenish_add_buff_success++;
+		}
+	}
+    
+	atomic_add(buffers_added, &(pool->available));
+}
+
+/* check if replenishing is needed.  */
+static inline int ibmveth_is_replenishing_needed(struct ibmveth_adapter *adapter)
+{
+	return ((atomic_read(&adapter->rx_buff_pool[0].available) < adapter->rx_buff_pool[0].threshold) ||
+		(atomic_read(&adapter->rx_buff_pool[1].available) < adapter->rx_buff_pool[1].threshold) ||
+		(atomic_read(&adapter->rx_buff_pool[2].available) < adapter->rx_buff_pool[2].threshold));
+}
+
+/* replenish tasklet routine */
+static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) 
+{
+	adapter->replenish_task_cycles++;
+
+	ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[0]);
+	ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[1]);
+	ibmveth_replenish_buffer_pool(adapter, &adapter->rx_buff_pool[2]);
+
+	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
+}
+
+/* kick the replenish tasklet if we need replenishing and it isn't already running */
+static inline void ibmveth_schedule_replenishing(struct ibmveth_adapter *adapter)
+{
+	if(ibmveth_is_replenishing_needed(adapter)) {	
+		tasklet_schedule(&adapter->replenish_task);
+	}
+}
+
+/* empty and free ana buffer pool - also used to do cleanup in error paths */
+static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter, struct ibmveth_buff_pool *pool)
+{
+	int i;
+
+	if(pool->free_map) {
+		kfree(pool->free_map);
+		pool->free_map  = NULL;
+	}
+
+	if(pool->skbuff && pool->dma_addr) {
+		for(i = 0; i < pool->size; ++i) {
+			struct sk_buff *skb = pool->skbuff[i];
+			if(skb) {
+				vio_unmap_single(adapter->vdev,
+						 pool->dma_addr[i],
+						 pool->buff_size,
+						 PCI_DMA_FROMDEVICE);
+				dev_kfree_skb_any(skb);
+				pool->skbuff[i] = NULL;
+			}
+		}
+	}
+
+	if(pool->dma_addr) {
+		kfree(pool->dma_addr);
+		pool->dma_addr = NULL;
+	}
+
+	if(pool->skbuff) {
+		kfree(pool->skbuff);
+		pool->skbuff = NULL;
+	}
+}
+
+/* remove a buffer from a pool */
+static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 correlator)
+{
+	unsigned int pool  = correlator >> 32;
+	unsigned int index = correlator & 0xffffffffUL;
+	unsigned int free_index;
+	struct sk_buff *skb;
+
+	ibmveth_assert(pool < IbmVethNumBufferPools);
+	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+
+	skb = adapter->rx_buff_pool[pool].skbuff[index];
+
+	ibmveth_assert(skb != NULL);
+
+	adapter->rx_buff_pool[pool].skbuff[index] = NULL;
+
+	vio_unmap_single(adapter->vdev,
+			 adapter->rx_buff_pool[pool].dma_addr[index],
+			 adapter->rx_buff_pool[pool].buff_size,
+			 PCI_DMA_FROMDEVICE);
+
+	free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size;
+	adapter->rx_buff_pool[pool].free_map[free_index] = index;
+
+	mb();
+
+	atomic_dec(&(adapter->rx_buff_pool[pool].available));
+}
+
+/* get the current buffer on the rx queue */
+static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *adapter)
+{
+	u64 correlator = adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator;
+	unsigned int pool = correlator >> 32;
+	unsigned int index = correlator & 0xffffffffUL;
+
+	ibmveth_assert(pool < IbmVethNumBufferPools);
+	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+
+	return adapter->rx_buff_pool[pool].skbuff[index];
+}
+
+/* recycle the current buffer on the rx queue */
+static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
+{
+	u32 q_index = adapter->rx_queue.index;
+	u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator;
+	unsigned int pool = correlator >> 32;
+	unsigned int index = correlator & 0xffffffffUL;
+	union ibmveth_buf_desc desc;
+	unsigned long lpar_rc;
+
+	ibmveth_assert(pool < IbmVethNumBufferPools);
+	ibmveth_assert(index < adapter->rx_buff_pool[pool].size);
+
+	desc.desc = 0;
+	desc.fields.valid = 1;
+	desc.fields.length = adapter->rx_buff_pool[pool].buff_size;
+	desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index];
+
+	lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
+		    
+	if(lpar_rc != H_Success) {
+		ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
+		ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
+	}
+
+	if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
+		adapter->rx_queue.index = 0;
+		adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
+	}
+}
+
+static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
+{
+	ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
+
+	if(++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
+		adapter->rx_queue.index = 0;
+		adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
+	}
+}
+
+static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
+{
+	if(adapter->buffer_list_addr != NULL) {
+		if(adapter->buffer_list_dma != NO_TCE) {
+			vio_unmap_single(adapter->vdev, adapter->buffer_list_dma, 4096, PCI_DMA_BIDIRECTIONAL);
+			adapter->buffer_list_dma = NO_TCE;
+		}
+		free_page((unsigned long)adapter->buffer_list_addr);
+		adapter->buffer_list_addr = NULL;
+	} 
+
+	if(adapter->filter_list_addr != NULL) {
+		if(adapter->filter_list_dma != NO_TCE) {
+			vio_unmap_single(adapter->vdev, adapter->filter_list_dma, 4096, PCI_DMA_BIDIRECTIONAL);
+			adapter->filter_list_dma = NO_TCE;
+		}
+		free_page((unsigned long)adapter->filter_list_addr);
+		adapter->filter_list_addr = NULL;
+	}
+
+	if(adapter->rx_queue.queue_addr != NULL) {
+		if(adapter->rx_queue.queue_dma != NO_TCE) {
+			vio_unmap_single(adapter->vdev, adapter->rx_queue.queue_dma, adapter->rx_queue.queue_len, PCI_DMA_BIDIRECTIONAL);
+			adapter->rx_queue.queue_dma = NO_TCE;
+		}
+		kfree(adapter->rx_queue.queue_addr);
+		adapter->rx_queue.queue_addr = NULL;
+	}
+
+	ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[0]);
+	ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[1]);
+	ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[2]);
+}
+
+static int ibmveth_open(struct net_device *netdev)
+{
+	struct ibmveth_adapter *adapter = netdev->priv;
+	u64 mac_address = 0;
+	int rxq_entries;
+	unsigned long lpar_rc;
+	int rc;
+	union ibmveth_buf_desc rxq_desc;
+
+	ibmveth_debug_printk("open starting\n");
+
+	rxq_entries =
+		adapter->rx_buff_pool[0].size +
+		adapter->rx_buff_pool[1].size +
+		adapter->rx_buff_pool[2].size + 1;
+    
+	adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
+	adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
+ 
+	if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
+		ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
+		ibmveth_cleanup(adapter);
+		return -ENOMEM;
+	}
+
+	adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries;
+	adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, GFP_KERNEL);
+
+	if(!adapter->rx_queue.queue_addr) {
+		ibmveth_error_printk("unable to allocate rx queue pages\n");
+		ibmveth_cleanup(adapter);
+		return -ENOMEM;
+	}
+
+	adapter->buffer_list_dma = vio_map_single(adapter->vdev, adapter->buffer_list_addr, 4096, PCI_DMA_BIDIRECTIONAL);
+	adapter->filter_list_dma = vio_map_single(adapter->vdev, adapter->filter_list_addr, 4096, PCI_DMA_BIDIRECTIONAL);
+	adapter->rx_queue.queue_dma = vio_map_single(adapter->vdev, adapter->rx_queue.queue_addr, adapter->rx_queue.queue_len, PCI_DMA_BIDIRECTIONAL);
+
+	if((adapter->buffer_list_dma == NO_TCE) || 
+	   (adapter->filter_list_dma == NO_TCE) || 
+	   (adapter->rx_queue.queue_dma == NO_TCE)) {
+		ibmveth_error_printk("unable to map filter or buffer list pages\n");
+		ibmveth_cleanup(adapter);
+		return -ENOMEM;
+	}
+
+	adapter->rx_queue.index = 0;
+	adapter->rx_queue.num_slots = rxq_entries;
+	adapter->rx_queue.toggle = 1;
+
+	if(ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0]) ||
+	   ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[1]) ||
+	   ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[2]))
+	{
+		ibmveth_error_printk("unable to allocate buffer pools\n");
+		ibmveth_cleanup(adapter);
+		return -ENOMEM;
+	}
+
+	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
+	mac_address = mac_address >> 16;
+
+	rxq_desc.desc = 0;
+	rxq_desc.fields.valid = 1;
+	rxq_desc.fields.length = adapter->rx_queue.queue_len;
+	rxq_desc.fields.address = adapter->rx_queue.queue_dma;
+
+	ibmveth_debug_printk("buffer list @ 0x%p\n", adapter->buffer_list_addr);
+	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
+	ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
+
+    
+	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
+					 adapter->buffer_list_dma,
+					 rxq_desc.desc,
+					 adapter->filter_list_dma,
+					 mac_address);
+
+	if(lpar_rc != H_Success) {
+		ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc);
+		ibmveth_error_printk("buffer TCE:0x%x filter TCE:0x%x rxq desc:0x%lx MAC:0x%lx\n",
+				     adapter->buffer_list_dma,
+				     adapter->filter_list_dma,
+				     rxq_desc.desc,
+				     mac_address);
+		ibmveth_cleanup(adapter);
+		return -ENONET; 
+	}
+
+	ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
+	if((rc = request_irq(netdev->irq, &ibmveth_interrupt, 0, netdev->name, netdev)) != 0) {
+		ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc);
+		h_free_logical_lan(adapter->vdev->unit_address);
+		ibmveth_cleanup(adapter);
+		return rc;
+	}
+
+	netif_start_queue(netdev);
+
+	ibmveth_debug_printk("scheduling initial replenish cycle\n");
+	ibmveth_schedule_replenishing(adapter);
+
+	ibmveth_debug_printk("open complete\n");
+
+	return 0;
+}
+
+static int ibmveth_close(struct net_device *netdev)
+{
+	struct ibmveth_adapter *adapter = netdev->priv;
+	long lpar_rc;
+    
+	ibmveth_debug_printk("close starting\n");
+
+	netif_stop_queue(netdev);
+
+	free_irq(netdev->irq, netdev);
+
+	tasklet_kill(&adapter->replenish_task);
+
+	lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
+
+	if(lpar_rc != H_Success)
+	{
+		ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n",
+				     lpar_rc);
+	}
+
+	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
+
+	ibmveth_cleanup(adapter);
+
+	ibmveth_debug_printk("close complete\n");
+
+	return 0;
+}
+
+static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
+	cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+	cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg | ADVERTISED_FIBRE);
+	cmd->speed = SPEED_1000;
+	cmd->duplex = DUPLEX_FULL;
+	cmd->port = PORT_FIBRE;
+	cmd->phy_address = 0;
+	cmd->transceiver = XCVR_INTERNAL;
+	cmd->autoneg = AUTONEG_ENABLE;
+	cmd->maxtxpkt = 0;
+	cmd->maxrxpkt = 1;
+	return 0;
+}
+
+static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info) {
+	strncpy(info->driver, ibmveth_driver_name, sizeof(info->driver) - 1);
+	strncpy(info->version, ibmveth_driver_version, sizeof(info->version) - 1);
+}
+
+static u32 netdev_get_link(struct net_device *dev) {
+	return 0;
+}
+
+static struct ethtool_ops netdev_ethtool_ops = {
+	.get_drvinfo		= netdev_get_drvinfo,
+	.get_settings		= netdev_get_settings,
+	.get_link		= netdev_get_link,
+	.get_sg			= ethtool_op_get_sg,
+	.get_tx_csum		= ethtool_op_get_tx_csum,
+};
+
+static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	return -EOPNOTSUPP;
+}
+
+#define page_offset(v) ((unsigned long)(v) & ((1 << 12) - 1))
+
+static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ibmveth_adapter *adapter = netdev->priv;
+	union ibmveth_buf_desc desc[IbmVethMaxSendFrags];
+	unsigned long lpar_rc;
+	int nfrags = 0, curfrag;
+
+	if ((skb_shinfo(skb)->nr_frags + 1) > IbmVethMaxSendFrags) {
+		adapter->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	memset(&desc, 0, sizeof(desc));
+
+	/* nfrags = number of frags after the initial fragment */
+	nfrags = skb_shinfo(skb)->nr_frags;
+
+	if(nfrags)
+		adapter->tx_multidesc_send++;
+
+	/* map the initial fragment */
+	desc[0].fields.length  = nfrags ? skb->len - skb->data_len : skb->len;
+	desc[0].fields.address = vio_map_single(adapter->vdev, skb->data, desc[0].fields.length, PCI_DMA_TODEVICE);
+	desc[0].fields.valid   = 1;
+
+	if(desc[0].fields.address == NO_TCE) {
+		ibmveth_error_printk("tx: unable to map initial fragment\n");
+		adapter->tx_map_failed++;
+		adapter->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+	curfrag = nfrags;
+
+	/* map fragments past the initial portion if there are any */
+	while(curfrag--) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[curfrag];
+		desc[curfrag+1].fields.address = vio_map_single(adapter->vdev,
+								page_address(frag->page) + frag->page_offset,
+								frag->size, PCI_DMA_TODEVICE);
+		desc[curfrag+1].fields.length = frag->size;
+		desc[curfrag+1].fields.valid  = 1;
+
+		if(desc[curfrag+1].fields.address == NO_TCE) {
+			ibmveth_error_printk("tx: unable to map fragment %d\n", curfrag);
+			adapter->tx_map_failed++;
+			adapter->stats.tx_dropped++;
+			/* Free all the mappings we just created */
+			while(curfrag < nfrags) {
+				vio_unmap_single(adapter->vdev,
+						 desc[curfrag+1].fields.address,
+						 desc[curfrag+1].fields.length,
+						 PCI_DMA_TODEVICE);
+				curfrag++;
+			}
+			dev_kfree_skb(skb);
+			return 0;
+		}
+	}
+
+	/* send the frame. Arbitrarily set retrycount to 1024 */
+	unsigned long correlator = 0;
+	unsigned int retry_count = 1024;
+	do {
+		lpar_rc = h_send_logical_lan(adapter->vdev->unit_address,
+					     desc[0].desc,
+					     desc[1].desc,
+					     desc[2].desc,
+					     desc[3].desc,
+					     desc[4].desc,
+					     desc[5].desc,
+					     correlator);
+	} while ((lpar_rc == H_Busy) && (retry_count--));
+    
+	if(lpar_rc != H_Success && lpar_rc != H_Dropped) {
+		int i;
+		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
+		for(i = 0; i < 6; i++) {
+			ibmveth_error_printk("tx: desc[%i] valid=%d, len=%d, address=0x%d\n", i,
+					     desc[i].fields.valid, desc[i].fields.length, desc[i].fields.address);
+		}
+		adapter->tx_send_failed++;
+		adapter->stats.tx_dropped++;
+	} else {
+		adapter->stats.tx_packets++;
+		adapter->stats.tx_bytes += skb->len;
+	}
+
+	do {
+		vio_unmap_single(adapter->vdev, desc[nfrags].fields.address, desc[nfrags].fields.length, PCI_DMA_TODEVICE);
+	} while(--nfrags >= 0);
+
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+static int ibmveth_poll(struct net_device *netdev, int *budget)
+{
+	struct ibmveth_adapter *adapter = netdev->priv;
+	int max_frames_to_process = netdev->quota;
+	int frames_processed = 0;
+	int more_work = 1;
+	unsigned long lpar_rc;
+
+ restart_poll:
+	do {
+		struct net_device *netdev = adapter->netdev;
+
+		if(ibmveth_rxq_pending_buffer(adapter)) {
+			struct sk_buff *skb;
+
+			if(!ibmveth_rxq_buffer_valid(adapter)) {
+				wmb(); /* suggested by larson1 */
+				adapter->rx_invalid_buffer++;
+				ibmveth_debug_printk("recycling invalid buffer\n");
+				ibmveth_rxq_recycle_buffer(adapter);
+			} else {
+				int length = ibmveth_rxq_frame_length(adapter);
+				int offset = ibmveth_rxq_frame_offset(adapter);
+				skb = ibmveth_rxq_get_buffer(adapter);
+
+				ibmveth_rxq_harvest_buffer(adapter);
+
+				skb_reserve(skb, offset);
+				skb_put(skb, length);
+				skb->dev = netdev;
+				skb->protocol = eth_type_trans(skb, netdev);
+
+				netif_receive_skb(skb);	/* send it up */
+
+				adapter->stats.rx_packets++;
+				adapter->stats.rx_bytes += length;
+				frames_processed++;
+			}
+		} else {
+			more_work = 0;
+		}
+	} while(more_work && (frames_processed < max_frames_to_process));
+
+	ibmveth_schedule_replenishing(adapter);
+
+	if(more_work) {
+		/* more work to do - return that we are not done yet */
+		netdev->quota -= frames_processed;
+		*budget -= frames_processed;
+		return 1; 
+	}
+
+	/* we think we are done - reenable interrupts, then check once more to make sure we are done */
+	lpar_rc = h_vio_signal(adapter->vdev->unit_address, IbmVethIntsEnabled);
+	ibmveth_assert(lpar_rc == H_Success);
+
+	netif_rx_complete(netdev);
+
+	if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed))
+	{
+		lpar_rc = h_vio_signal(adapter->vdev->unit_address, IbmVethIntsDisabled);
+		ibmveth_assert(lpar_rc == H_Success);
+		more_work = 1;
+		goto restart_poll;
+	}
+
+	netdev->quota -= frames_processed;
+	*budget -= frames_processed;
+
+	/* we really are done */
+	return 0;
+}
+
+static void ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{   
+	struct net_device *netdev = dev_instance;
+	struct ibmveth_adapter *adapter = netdev->priv;
+	unsigned long lpar_rc;
+
+	if(netif_rx_schedule_prep(netdev)) {
+		lpar_rc = h_vio_signal(adapter->vdev->unit_address, IbmVethIntsDisabled);
+		ibmveth_assert(lpar_rc == H_Success);
+		__netif_rx_schedule(netdev);
+	}
+}
+
+static struct net_device_stats *ibmveth_get_stats(struct net_device *dev)
+{
+	struct ibmveth_adapter *adapter = dev->priv;
+	return &adapter->stats;
+}
+
+static void ibmveth_set_multicast_list(struct net_device *netdev)
+{
+	struct ibmveth_adapter *adapter = netdev->priv;
+	unsigned long lpar_rc;
+
+	if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) {
+		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
+					   IbmVethMcastEnableRecv |
+					   IbmVethMcastDisableFiltering,
+					   0);
+		if(lpar_rc != H_Success) {
+			ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc);
+		}
+	} else {
+		struct dev_mc_list *mclist = netdev->mc_list;
+		int i;
+		/* clear the filter table & disable filtering */
+		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
+					   IbmVethMcastEnableRecv |
+					   IbmVethMcastDisableFiltering |
+					   IbmVethMcastClearFilterTable,
+					   0);
+		if(lpar_rc != H_Success) {
+			ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc);
+		}
+		/* add the addresses to the filter table */
+		for(i = 0; i < netdev->mc_count; ++i, mclist = mclist->next) {
+			// add the multicast address to the filter table
+			unsigned long mcast_addr = 0;
+			memcpy(((char *)&mcast_addr)+2, mclist->dmi_addr, 6);
+			lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
+						   IbmVethMcastAddFilter,
+						   mcast_addr);
+			if(lpar_rc != H_Success) {
+				ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
+			}
+		}
+	
+		/* re-enable filtering */
+		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
+					   IbmVethMcastEnableFiltering,
+					   0);
+		if(lpar_rc != H_Success) {
+			ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc);
+		}
+	}
+}
+
+static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
+{
+	int rc;
+	struct net_device *netdev;
+	struct ibmveth_adapter *adapter;
+
+	unsigned int *mac_addr_p;
+	unsigned int *mcastFilterSize_p;
+
+
+	ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%lx\n", 
+					dev->unit_address);
+
+	mac_addr_p = (unsigned int *) vio_get_attribute(dev, VETH_MAC_ADDR, 0);
+	if(!mac_addr_p) {
+		ibmveth_error_printk("Can't find VETH_MAC_ADDR attribute\n");
+		return 0;
+	}
+	
+	mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0);
+	if(!mcastFilterSize_p) {
+		ibmveth_error_printk("Can't find VETH_MCAST_FILTER_SIZE attribute\n");
+		return 0;
+	}
+	
+	netdev = alloc_etherdev(sizeof(struct ibmveth_adapter));
+
+	if(!netdev)
+		return -ENOMEM;
+
+	SET_MODULE_OWNER(netdev);
+
+	adapter = netdev->priv;
+	memset(adapter, 0, sizeof(adapter));
+	dev->driver_data = netdev;
+
+	adapter->vdev = dev;
+	adapter->netdev = netdev;
+	adapter->mcastFilterSize= *mcastFilterSize_p;
+	
+	/* 	Some older boxes running PHYP non-natively have an OF that
+		returns a 8-byte local-mac-address field (and the first 
+		2 bytes have to be ignored) while newer boxes' OF return
+		a 6-byte field. Note that IEEE 1275 specifies that 
+		local-mac-address must be a 6-byte field.
+		The RPA doc specifies that the first byte must be 10b, so 
+		we'll just look for it to solve this 8 vs. 6 byte field issue */
+
+	while (*((char*)mac_addr_p) != (char)(0x02))
+		((char*)mac_addr_p)++;
+
+	adapter->mac_addr = 0;
+	memcpy(&adapter->mac_addr, mac_addr_p, 6);
+
+	adapter->liobn = dev->tce_table->index;
+	
+	netdev->irq = dev->irq;
+	netdev->open               = ibmveth_open;
+	netdev->poll               = ibmveth_poll;
+	netdev->weight             = 16;
+	netdev->stop               = ibmveth_close;
+	netdev->hard_start_xmit    = ibmveth_start_xmit;
+	netdev->get_stats          = ibmveth_get_stats;
+	netdev->set_multicast_list = ibmveth_set_multicast_list;
+	netdev->do_ioctl           = ibmveth_ioctl;
+	netdev->ethtool_ops           = &netdev_ethtool_ops;
+
+	memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
+
+	ibmveth_init_buffer_pool(&adapter->rx_buff_pool[0], 0, IbmVethPool0DftCnt, IbmVethPool0DftSize);
+	ibmveth_init_buffer_pool(&adapter->rx_buff_pool[1], 1, IbmVethPool1DftCnt, IbmVethPool1DftSize);
+	ibmveth_init_buffer_pool(&adapter->rx_buff_pool[2], 2, IbmVethPool2DftCnt, IbmVethPool2DftSize);
+
+	ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
+
+	tasklet_init(&adapter->replenish_task, (void*)ibmveth_replenish_task, (unsigned long)adapter);
+
+	adapter->buffer_list_dma = NO_TCE;
+	adapter->filter_list_dma = NO_TCE;
+	adapter->rx_queue.queue_dma = NO_TCE;
+
+	ibmveth_debug_printk("registering netdev...\n");
+
+	rc = register_netdev(netdev);
+
+	if(rc) {
+		ibmveth_debug_printk("failed to register netdev rc=%d\n", rc);
+		free_netdev(netdev);
+		return rc;
+	}
+
+	ibmveth_debug_printk("registered\n");
+
+	ibmveth_proc_register_adapter(adapter);
+
+	return 0;
+}
+
+static void __devexit ibmveth_remove(struct vio_dev *dev)
+{
+	struct net_device *netdev = dev->driver_data;
+	struct ibmveth_adapter *adapter = netdev->priv;
+
+	unregister_netdev(netdev);
+
+	ibmveth_proc_unregister_adapter(adapter);
+
+	free_netdev(netdev);
+	return;
+}
+
+#ifdef CONFIG_PROC_FS
+static void ibmveth_proc_register_driver(void)
+{
+	ibmveth_proc_dir = create_proc_entry(IBMVETH_PROC_DIR, S_IFDIR, proc_net);
+	if (ibmveth_proc_dir) {
+		SET_MODULE_OWNER(ibmveth_proc_dir);
+	}
+}
+
+static void ibmveth_proc_unregister_driver(void)
+{
+	remove_proc_entry(IBMVETH_PROC_DIR, proc_net);
+}
+
+static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) 
+{
+	if (*pos == 0) {
+		return (void *)1;
+	} else {
+		return NULL;
+	}
+}
+
+static void *ibmveth_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void ibmveth_seq_stop(struct seq_file *seq, void *v) 
+{
+}
+
+static int ibmveth_seq_show(struct seq_file *seq, void *v) 
+{
+	struct ibmveth_adapter *adapter = seq->private;
+	char *current_mac = ((char*) &adapter->netdev->dev_addr);
+	char *firmware_mac = ((char*) &adapter->mac_addr) ;
+
+	seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
+	
+	seq_printf(seq, "Unit Address:    0x%lx\n", adapter->vdev->unit_address);
+	seq_printf(seq, "LIOBN:           0x%lx\n", adapter->liobn);
+	seq_printf(seq, "Current MAC:     %02X:%02X:%02X:%02X:%02X:%02X\n",
+		   current_mac[0], current_mac[1], current_mac[2],
+		   current_mac[3], current_mac[4], current_mac[5]);
+	seq_printf(seq, "Firmware MAC:    %02X:%02X:%02X:%02X:%02X:%02X\n",
+		   firmware_mac[0], firmware_mac[1], firmware_mac[2],
+		   firmware_mac[3], firmware_mac[4], firmware_mac[5]);
+	
+	seq_printf(seq, "\nAdapter Statistics:\n");
+	seq_printf(seq, "  TX:  skbuffs linearized:          %ld\n", adapter->tx_linearized);
+	seq_printf(seq, "       multi-descriptor sends:      %ld\n", adapter->tx_multidesc_send);
+	seq_printf(seq, "       skb_linearize failures:      %ld\n", adapter->tx_linearize_failed);
+	seq_printf(seq, "       vio_map_single failres:      %ld\n", adapter->tx_map_failed);
+	seq_printf(seq, "       send failures:               %ld\n", adapter->tx_send_failed);
+	seq_printf(seq, "  RX:  replenish task cycles:       %ld\n", adapter->replenish_task_cycles);
+	seq_printf(seq, "       alloc_skb_failures:          %ld\n", adapter->replenish_no_mem);
+	seq_printf(seq, "       add buffer failures:         %ld\n", adapter->replenish_add_buff_failure);
+	seq_printf(seq, "       invalid buffers:             %ld\n", adapter->rx_invalid_buffer);
+	seq_printf(seq, "       no buffers:                  %ld\n", adapter->rx_no_buffer);
+	
+	return 0;
+}
+static struct seq_operations ibmveth_seq_ops = {
+	.start = ibmveth_seq_start,
+	.next  = ibmveth_seq_next,
+	.stop  = ibmveth_seq_stop,
+	.show  = ibmveth_seq_show,
+};
+
+static int ibmveth_proc_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	struct proc_dir_entry *proc;
+	int rc;
+
+	rc = seq_open(file, &ibmveth_seq_ops);
+	if (!rc) {
+		/* recover the pointer buried in proc_dir_entry data */
+		seq = file->private_data;
+		proc = PDE(inode);
+		seq->private = proc->data;
+	}
+	return rc;
+}
+
+static struct file_operations ibmveth_proc_fops = {
+	.owner	 = THIS_MODULE,
+	.open    = ibmveth_proc_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
+static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
+{
+	struct proc_dir_entry *entry;
+	if (ibmveth_proc_dir) {
+		entry = create_proc_entry(adapter->netdev->name, S_IFREG, ibmveth_proc_dir);
+		if (!entry) {
+			ibmveth_error_printk("Cannot create adapter proc entry");
+		} else {
+			entry->data = (void *) adapter;
+			entry->proc_fops = &ibmveth_proc_fops;
+			SET_MODULE_OWNER(entry);
+		}
+	}
+	return;
+}
+
+static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
+{
+	if (ibmveth_proc_dir) {
+		remove_proc_entry(adapter->netdev->name, ibmveth_proc_dir);
+	}
+}
+
+#else /* CONFIG_PROC_FS */
+static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) 
+{
+}
+
+static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) 
+{
+}
+static void ibmveth_proc_register_driver(void)
+{
+}
+
+static void ibmveth_proc_unregister_driver(void)
+{
+}
+#endif /* CONFIG_PROC_FS */
+
+static struct vio_device_id ibmveth_device_table[] __devinitdata= {
+	{ "network", "IBM,l-lan"},
+	{ 0,}
+};
+
+MODULE_DEVICE_TABLE(vio, ibmveth_device_table);
+
+static struct vio_driver ibmveth_driver = {
+	.name        = (char *)ibmveth_driver_name,
+	.id_table    = ibmveth_device_table,
+	.probe       = ibmveth_probe,
+	.remove      = ibmveth_remove
+};
+
+static int __init ibmveth_module_init(void)
+{
+	int rc;
+
+	ibmveth_printk("%s: %s %s\n", ibmveth_driver_name, ibmveth_driver_string, ibmveth_driver_version);
+
+	ibmveth_proc_register_driver();
+
+	rc = vio_module_init(&ibmveth_driver);
+
+	return rc;
+}
+
+static void __exit ibmveth_module_exit(void)
+{
+	vio_unregister_driver(&ibmveth_driver);
+	ibmveth_proc_unregister_driver();
+}	
+
+module_init(ibmveth_module_init);
+module_exit(ibmveth_module_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/ibmveth.h linux-2.4.27-rc4/drivers/net/ibmveth.h
--- linux-2.4.26/drivers/net/ibmveth.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/ibmveth.h	2004-07-30 16:24:26.000000000 +0000
@@ -0,0 +1,158 @@
+/**************************************************************************/
+/*                                                                        */
+/* IBM eServer i/[Series Virtual Ethernet Device Driver                   */
+/* Copyright (C) 2003 Dave Larson (larson1@us.ibm.com), IBM Corp.         */
+/*                                                                        */
+/*  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 _IBMVETH_H
+#define _IBMVETH_H
+
+#define IbmVethMaxSendFrags 6
+
+/* constants for H_MULTICAST_CTRL */
+#define IbmVethMcastReceptionModifyBit     0x80000UL
+#define IbmVethMcastReceptionEnableBit     0x20000UL
+#define IbmVethMcastFilterModifyBit        0x40000UL
+#define IbmVethMcastFilterEnableBit        0x10000UL
+
+#define IbmVethMcastEnableRecv       (IbmVethMcastReceptionModifyBit | IbmVethMcastReceptionEnableBit)
+#define IbmVethMcastDisableRecv      (IbmVethMcastReceptionModifyBit)
+#define IbmVethMcastEnableFiltering  (IbmVethMcastFilterModifyBit | IbmVethMcastFilterEnableBit)
+#define IbmVethMcastDisableFiltering (IbmVethMcastFilterModifyBit)
+#define IbmVethMcastAddFilter        0x1UL
+#define IbmVethMcastRemoveFilter     0x2UL
+#define IbmVethMcastClearFilterTable 0x3UL
+
+/* constants for H_VIO_SIGNAL */
+#define IbmVethIntsDisabled          0x0UL
+#define IbmVethIntsEnabled           0x1UL
+
+/* hcall numbers */
+#define H_VIO_SIGNAL             0x104
+#define H_REGISTER_LOGICAL_LAN   0x114
+#define H_FREE_LOGICAL_LAN       0x118
+#define H_ADD_LOGICAL_LAN_BUFFER 0x11C
+#define H_SEND_LOGICAL_LAN       0x120
+#define H_MULTICAST_CTRL         0x130
+#define H_CHANGE_LOGICAL_LAN_MAC 0x14C
+
+/* hcall macros */
+#define h_vio_signal(ua, mode) \
+  plpar_hcall_norets(H_VIO_SIGNAL, ua, mode)
+
+#define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \
+  plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac)
+
+#define h_free_logical_lan(ua) \
+  plpar_hcall_norets(H_FREE_LOGICAL_LAN, ua)
+
+#define h_add_logical_lan_buffer(ua, buf) \
+  plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, ua, buf)
+
+#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \
+  plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator, &correlator)
+
+#define h_multicast_ctrl(ua, cmd, mac) \
+  plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac)
+
+#define h_change_logical_lan_mac(ua, mac) \
+  plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
+
+#define IbmVethNumBufferPools 3
+#define IbmVethPool0DftSize (1024 * 2)
+#define IbmVethPool1DftSize (1024 * 4)
+#define IbmVethPool2DftSize (1024 * 10)
+#define IbmVethPool0DftCnt  256
+#define IbmVethPool1DftCnt  256
+#define IbmVethPool2DftCnt  256
+
+struct ibmveth_buff_pool {
+    u32 size;
+    u32 index;
+    u32 buff_size;
+    u32 threshold;
+    atomic_t available;
+    u32 consumer_index;
+    u32 producer_index;
+    u16 *free_map;
+    dma_addr_t *dma_addr;
+    struct sk_buff **skbuff;
+};
+
+struct ibmveth_rx_q {
+    u64        index;
+    u64        num_slots;
+    u64        toggle;
+    dma_addr_t queue_dma;
+    u32        queue_len;
+    struct ibmveth_rx_q_entry *queue_addr;
+};
+
+struct ibmveth_adapter {
+    struct vio_dev *vdev;
+    struct net_device *netdev;
+    struct net_device_stats stats;
+    unsigned int mcastFilterSize;
+    unsigned long mac_addr;
+    unsigned long liobn;
+    void * buffer_list_addr;
+    void * filter_list_addr;
+    dma_addr_t buffer_list_dma;
+    dma_addr_t filter_list_dma;
+    struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
+    struct ibmveth_rx_q rx_queue;
+    /* helper tasks */
+    struct tasklet_struct replenish_task;
+    /* adapter specific stats */
+    u64 replenish_task_cycles;
+    u64 replenish_no_mem;
+    u64 replenish_add_buff_failure;
+    u64 replenish_add_buff_success;
+    u64 rx_invalid_buffer;
+    u64 rx_no_buffer;
+    u64 tx_multidesc_send;
+    u64 tx_linearized;
+    u64 tx_linearize_failed;
+    u64 tx_map_failed;
+    u64 tx_send_failed;
+};
+
+struct ibmveth_buf_desc_fields {	
+    u32 valid : 1;
+    u32 toggle : 1;
+    u32 reserved : 6;
+    u32 length : 24;
+    u32 address;
+};
+
+union ibmveth_buf_desc {
+    u64 desc;	
+    struct ibmveth_buf_desc_fields fields;
+};
+
+struct ibmveth_rx_q_entry {
+    u16 toggle : 1;
+    u16 valid : 1;
+    u16 reserved : 14;
+    u16 offset;
+    u32 length;
+    u64 correlator;
+};
+
+#endif /* _IBMVETH_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/irda/via-ircc.c linux-2.4.27-rc4/drivers/net/irda/via-ircc.c
--- linux-2.4.26/drivers/net/irda/via-ircc.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/irda/via-ircc.c	2004-07-30 16:29:40.000000000 +0000
@@ -1142,13 +1142,16 @@ F01_E */
 		st_fifo->head++;
 		st_fifo->len--;
 
-		skb = dev_alloc_skb(len + 1 - 4);
 		/*
-		 * if frame size,data ptr,or skb ptr are wrong ,the get next
+		 * if frame size or data ptr are wrong ,then get next
 		 * entry.
 		 */
-		if ((skb == NULL) || (skb->data == NULL)
-		    || (self->rx_buff.data == NULL) || (len < 6)) {
+		if ((self->rx_buff.data == NULL) || (len < 6)) {
+			self->stats.rx_dropped++;
+			return TRUE;
+		}
+		skb = dev_alloc_skb(len + 1 - 4);
+		if (!skb) {
 			self->stats.rx_dropped++;
 			return TRUE;
 		}
@@ -1194,8 +1197,12 @@ static int upload_rxdata(struct via_ircc
 #ifdef	DBGMSG
 	DBG(printk(KERN_INFO "upload_rxdata: len=%x\n", len));
 #endif
+	if ((len - 4) < 2) {
+		self->stats.rx_dropped++;
+		return FALSE;
+	}
 	skb = dev_alloc_skb(len + 1);
-	if ((skb == NULL) || ((len - 4) < 2)) {
+	if (!skb) {
 		self->stats.rx_dropped++;
 		return FALSE;
 	}
@@ -1258,13 +1265,17 @@ static int RxTimerHandler(struct via_irc
 			st_fifo->head++;
 			st_fifo->len--;
 
-			skb = dev_alloc_skb(len + 1 - 4);
 			/*
-			 * if frame size, data ptr, or skb ptr are wrong,
+			 * if frame size or data ptr are wrong,
 			 * then get next entry.
 			 */
-			if ((skb == NULL) || (skb->data == NULL)
-			    || (self->rx_buff.data == NULL) || (len < 6)) {
+			if ((self->rx_buff.data == NULL) || (len < 6)) {
+				self->stats.rx_dropped++;
+				continue;
+			}
+
+			skb = dev_alloc_skb(len + 1 - 4);
+			if (!skb) {
 				self->stats.rx_dropped++;
 				continue;
 			}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/macsonic.c linux-2.4.27-rc4/drivers/net/macsonic.c
--- linux-2.4.26/drivers/net/macsonic.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/macsonic.c	2004-07-30 16:25:38.000000000 +0000
@@ -199,6 +199,7 @@ int __init macsonic_init(struct net_devi
 	if ((lp->rba = (char *)
 	     kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL | GFP_DMA)) == NULL) {
 		printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
+		kfree(lp);
 		return -ENOMEM;
 	}
 
@@ -635,19 +636,14 @@ int __init mac_nubus_sonic_probe(struct 
 }
 
 #ifdef MODULE
-static char namespace[16] = "";
 static struct net_device dev_macsonic;
 
 MODULE_PARM(sonic_debug, "i");
 MODULE_PARM_DESC(sonic_debug, "macsonic debug level (1-4)");
-MODULE_LICENSE("GPL");
-
-EXPORT_NO_SYMBOLS;
 
 int
 init_module(void)
 {
-        dev_macsonic.name = namespace;
         dev_macsonic.init = macsonic_probe;
 
         if (register_netdev(&dev_macsonic) != 0) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/natsemi.c linux-2.4.27-rc4/drivers/net/natsemi.c
--- linux-2.4.26/drivers/net/natsemi.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/natsemi.c	2004-07-30 16:25:11.000000000 +0000
@@ -387,7 +387,7 @@ enum register_offsets {
 	IntrStatus		= 0x10,
 	IntrMask		= 0x14,
 	IntrEnable		= 0x18,
-	IntrHoldoff		= 0x16, /* DP83816 only */
+	IntrHoldoff		= 0x1C, /* DP83816 only */
 	TxRingPtr		= 0x20,
 	TxConfig		= 0x24,
 	RxRingPtr		= 0x30,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/pcnet32.c linux-2.4.27-rc4/drivers/net/pcnet32.c
--- linux-2.4.26/drivers/net/pcnet32.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/pcnet32.c	2004-07-30 16:26:55.000000000 +0000
@@ -1,12 +1,12 @@
 /* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */
 /*
  *	Copyright 1996-1999 Thomas Bogendoerfer
- * 
+ *
  *	Derived from the lance driver written 1993,1994,1995 by Donald Becker.
- * 
+ *
  *	Copyright 1993 United States Government as represented by the
  *	Director, National Security Agency.
- * 
+ *
  *	This software may be used and distributed according to the terms
  *	of the GNU General Public License, incorporated herein by reference.
  *
@@ -22,19 +22,16 @@
  *************************************************************************/
 
 #define DRV_NAME	"pcnet32"
-#define DRV_VERSION	"1.28"
-#define DRV_RELDATE	"02.20.2004"
+#define DRV_VERSION	"1.30c"
+#define DRV_RELDATE	"05.25.2004"
 #define PFX		DRV_NAME ": "
 
 static const char *version =
 DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
 
 #include <linux/module.h>
-
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
@@ -45,16 +42,17 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELD
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/crc32.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/uaccess.h>
-
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 
+#include <asm/bitops.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+
 /*
  * PCI device identifiers for "new style" Linux PCI Device Drivers
  */
@@ -74,10 +72,10 @@ MODULE_DEVICE_TABLE (pci, pcnet32_pci_tb
 
 static int cards_found __devinitdata;
 
-/* 
- * VLB I/O addresses 
+/*
+ * VLB I/O addresses
  */
-static unsigned int pcnet32_portlist[] __initdata = 
+static unsigned int pcnet32_portlist[] __initdata =
 	{ 0x300, 0x320, 0x340, 0x360, 0 };
 
 
@@ -88,7 +86,7 @@ static int pcnet32vlb;	 /* check for VLB
 
 static struct net_device *pcnet32_dev;
 
-static int max_interrupt_work = 80;
+static int max_interrupt_work = 2;
 static int rx_copybreak = 200;
 
 #define PCNET32_PORT_AUI      0x00
@@ -103,6 +101,9 @@ static int rx_copybreak = 200;
 
 #define PCNET32_DMA_MASK 0xffffffff
 
+#define PCNET32_WATCHDOG_TIMEOUT (jiffies + (2 * HZ))
+#define PCNET32_BLINK_TIMEOUT	(jiffies + (HZ/4))
+
 /*
  * table to translate option values from tulip
  * to internal options
@@ -110,7 +111,7 @@ static int rx_copybreak = 200;
 static unsigned char options_mapping[] = {
     PCNET32_PORT_ASEL,			   /*  0 Auto-select	  */
     PCNET32_PORT_AUI,			   /*  1 BNC/AUI	  */
-    PCNET32_PORT_AUI,			   /*  2 AUI/BNC	  */ 
+    PCNET32_PORT_AUI,			   /*  2 AUI/BNC	  */
     PCNET32_PORT_ASEL,			   /*  3 not supported	  */
     PCNET32_PORT_10BT | PCNET32_PORT_FD,   /*  4 10baseT-FD	  */
     PCNET32_PORT_ASEL,			   /*  5 not supported	  */
@@ -131,20 +132,22 @@ static const char pcnet32_gstrings_test[
 };
 #define PCNET32_TEST_LEN (sizeof(pcnet32_gstrings_test) / ETH_GSTRING_LEN)
 
+#define PCNET32_NUM_REGS 168
+
 #define MAX_UNITS 8	/* More are supported, limit only on options */
 static int options[MAX_UNITS];
 static int full_duplex[MAX_UNITS];
 
 /*
  *				Theory of Operation
- * 
+ *
  * This driver uses the same software structure as the normal lance
  * driver. So look for a verbose description in lance.c. The differences
  * to the normal lance driver is the use of the 32bit mode of PCnet32
  * and PCnetPCI chips. Because these chips are 32bit chips, there is no
  * 16MB limitation and we don't need bounce buffers.
  */
- 
+
 /*
  * History:
  * v0.01:  Initial version
@@ -198,7 +201,7 @@ static int full_duplex[MAX_UNITS];
  * v1.22:  changed pci scanning code to make PPC people happy
  *	   fixed switching to 32bit mode in pcnet32_open() (thanks
  *	   to Michael Richard <mcr@solidum.com> for noticing this one)
- *	   added sub vendor/device id matching (thanks again to 
+ *	   added sub vendor/device id matching (thanks again to
  *	   Michael Richard <mcr@solidum.com>)
  *	   added chip id for 79c973/975 (thanks to Zach Brown <zab@zabbo.net>)
  * v1.23   fixed small bug, when manual selecting MII speed/duplex
@@ -216,13 +219,15 @@ static int full_duplex[MAX_UNITS];
  * v1.26p  Fix oops on rmmod+insmod; plug i/o resource leak - Paul Gortmaker
  * v1.27   improved CSR/PROM address detection, lots of cleanups,
  * 	   new pcnet32vlb module option, HP-PARISC support,
- * 	   added module parameter descriptions, 
+ * 	   added module parameter descriptions,
  * 	   initial ethtool support - Helge Deller <deller@gmx.de>
  * v1.27a  Sun Feb 10 2002 Go Taniguchi <go@turbolinux.co.jp>
  *	   use alloc_etherdev and register_netdev
  *	   fix pci probe not increment cards_found
  *	   FD auto negotiate error workaround for xSeries250
  *	   clean up and using new mii module
+ * v1.27b  Sep 30 2002 Kent Yoder <yoder1@us.ibm.com>
+ * 	   Added timer for cable connection state changes.
  * v1.28   20 Feb 2004 Don Fry <brazilnut@us.ibm.com>
  *	   Jon Mason <jonmason@us.ibm.com>, Chinmay Albal <albal@in.ibm.com>
  *	   Now uses ethtool_ops, netif_msg_* and generic_mii_ioctl.
@@ -230,6 +235,16 @@ static int full_duplex[MAX_UNITS];
  *	   length errors, and transmit hangs.  Cleans up after errors in open.
  *	   Jim Lewis <jklewis@us.ibm.com> added ethernet loopback test.
  *	   Thomas Munck Steenholdt <tmus@tmus.dk> non-mii ioctl corrections.
+ * v1.29   6 Apr 2004 Jim Lewis <jklewis@us.ibm.com> added physical
+ *	   identification code (blink led's) and register dump.
+ *	   Don Fry added timer for 971/972 so skbufs don't remain on tx ring
+ *	   forever.
+ * v1.30   18 May 2004 Don Fry removed timer and Last Transmit Interrupt
+ *	   (ltint) as they added complexity and didn't give good throughput.
+ * v1.30a  22 May 2004 Don Fry limit frames received during interrupt.
+ * v1.30b  24 May 2004 Don Fry fix bogus tx carrier errors with 79c973,
+ *	   assisted by Bruce Penrod <bmpenrod@endruntechnologies.com>.
+ * v1.30c  25 May 2004 Don Fry added netif_wake_queue after pcnet32_restart.
  */
 
 
@@ -270,11 +285,11 @@ static int full_duplex[MAX_UNITS];
 struct pcnet32_rx_head {
     u32 base;
     s16 buf_length;
-    s16 status;	   
+    s16 status;
     u32 msg_length;
     u32 reserved;
 };
-	
+
 struct pcnet32_tx_head {
     u32 base;
     s16 length;
@@ -290,7 +305,7 @@ struct pcnet32_init_block {
     u8	phys_addr[6];
     u16 reserved;
     u32 filter[2];
-    /* Receive and transmit ring base, along with extra bits. */    
+    /* Receive and transmit ring base, along with extra bits. */
     u32 rx_ring;
     u32 tx_ring;
 };
@@ -307,7 +322,7 @@ struct pcnet32_access {
 };
 
 /*
- * The first three fields of pcnet32_private are read by the ethernet device 
+ * The first three fields of pcnet32_private are read by the ethernet device
  * so we allocate the structure should be allocated by pci_alloc_consistent().
  */
 struct pcnet32_private {
@@ -315,16 +330,18 @@ struct pcnet32_private {
     struct pcnet32_rx_head    rx_ring[RX_RING_SIZE];
     struct pcnet32_tx_head    tx_ring[TX_RING_SIZE];
     struct pcnet32_init_block init_block;
-    dma_addr_t 		dma_addr;	/* DMA address of beginning of this object, 
-					   returned by pci_alloc_consistent */
-    struct pci_dev	*pci_dev;	/* Pointer to the associated pci device structure */
+    dma_addr_t		dma_addr;	/* DMA address of beginning of this
+					   object, returned by
+					   pci_alloc_consistent */
+    struct pci_dev	*pci_dev;	/* Pointer to the associated pci device
+					   structure */
     const char		*name;
     /* The saved address of a sent-in-place packet/buffer, for skfree(). */
     struct sk_buff	*tx_skbuff[TX_RING_SIZE];
     struct sk_buff	*rx_skbuff[RX_RING_SIZE];
     dma_addr_t		tx_dma_addr[TX_RING_SIZE];
     dma_addr_t		rx_dma_addr[RX_RING_SIZE];
-    struct pcnet32_access a;
+    struct pcnet32_access	a;
     spinlock_t		lock;		/* Guard lock */
     unsigned int	cur_rx, cur_tx;	/* The next free ring entry */
     unsigned int	dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
@@ -332,11 +349,12 @@ struct pcnet32_private {
     char		tx_full;
     int			options;
     int	shared_irq:1,			/* shared irq possible */
-	ltint:1,			/* enable TxDone-intr inhibitor */
 	dxsuflo:1,			/* disable transmit stop on uflo */
 	mii:1;				/* mii port available */
     struct net_device	*next;
-    struct mii_if_info mii_if;
+    struct mii_if_info	mii_if;
+    struct timer_list	watchdog_timer;
+    struct timer_list	blink_timer;
     u32			msg_enable;	/* debug message level */
 };
 
@@ -351,14 +369,21 @@ static void pcnet32_tx_timeout (struct n
 static void pcnet32_interrupt(int, void *, struct pt_regs *);
 static int  pcnet32_close(struct net_device *);
 static struct net_device_stats *pcnet32_get_stats(struct net_device *);
+static void pcnet32_load_multicast(struct net_device *dev);
 static void pcnet32_set_multicast_list(struct net_device *);
 static int  pcnet32_ioctl(struct net_device *, struct ifreq *, int);
+static void pcnet32_watchdog(struct net_device *);
 static int mdio_read(struct net_device *dev, int phy_id, int reg_num);
 static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val);
 static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);
 static void pcnet32_ethtool_test(struct net_device *dev,
 	struct ethtool_test *eth_test, u64 *data);
 static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1);
+static int pcnet32_phys_id(struct net_device *dev, u32 data);
+static void pcnet32_led_blink_callback(struct net_device *dev);
+static int pcnet32_get_regs_len(struct net_device *dev);
+static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+	void *ptr);
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -476,6 +501,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
 
 
 static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -509,14 +542,14 @@ static int pcnet32_set_settings(struct n
 
 static void pcnet32_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct pcnet32_private *lp = dev->priv;
-  
-	strcpy (info->driver, DRV_NAME);
-	strcpy (info->version, DRV_VERSION);
-	if (lp->pci_dev)
-		strcpy (info->bus_info, pci_name(lp->pci_dev));
-	else
-		sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
+    struct pcnet32_private *lp = dev->priv;
+
+    strcpy (info->driver, DRV_NAME);
+    strcpy (info->version, DRV_VERSION);
+    if (lp->pci_dev)
+	strcpy (info->bus_info, pci_name(lp->pci_dev));
+    else
+	sprintf(info->bus_info, "VLB 0x%lx", dev->base_addr);
 }
 
 static u32 pcnet32_get_link(struct net_device *dev)
@@ -539,16 +572,16 @@ static u32 pcnet32_get_link(struct net_d
 
 static u32 pcnet32_get_msglevel(struct net_device *dev)
 {
-	struct pcnet32_private *lp = dev->priv;
-	return lp->msg_enable;
+    struct pcnet32_private *lp = dev->priv;
+    return lp->msg_enable;
 }
-  
+
 static void pcnet32_set_msglevel(struct net_device *dev, u32 value)
 {
-	struct pcnet32_private *lp = dev->priv;
-	lp->msg_enable = value;
+    struct pcnet32_private *lp = dev->priv;
+    lp->msg_enable = value;
 }
-  
+
 static int pcnet32_nway_reset(struct net_device *dev)
 {
     struct pcnet32_private *lp = dev->priv;
@@ -565,12 +598,12 @@ static int pcnet32_nway_reset(struct net
 
 static void pcnet32_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
-	struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_private *lp = dev->priv;
 
-	ering->tx_max_pending = TX_RING_SIZE - 1;
-	ering->tx_pending = lp->cur_tx - lp->dirty_tx;
-	ering->rx_max_pending = RX_RING_SIZE - 1;
-	ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
+    ering->tx_max_pending = TX_RING_SIZE - 1;
+    ering->tx_pending = lp->cur_tx - lp->dirty_tx;
+    ering->rx_max_pending = RX_RING_SIZE - 1;
+    ering->rx_pending = lp->cur_rx & RX_RING_MOD_MASK;
 }
 
 static void pcnet32_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -597,7 +630,7 @@ static void pcnet32_ethtool_test(struct 
 	    test->flags |= ETH_TEST_FL_FAILED;
 	} else if (netif_msg_hw(lp))
 	    printk(KERN_DEBUG "%s: Loopback test passed.\n", dev->name);
-    } else
+    } else if (netif_msg_hw(lp))
 	printk(KERN_DEBUG "%s: No tests to run (specify 'Offline' on ethtool).",	    dev->name);
 } /* end pcnet32_ethtool_test */
 
@@ -607,32 +640,40 @@ static int pcnet32_loopback_test(struct 
     struct pcnet32_access *a = &lp->a;	/* access to registers */
     ulong ioaddr = dev->base_addr;	/* card base I/O address */
     struct sk_buff *skb;		/* sk buff */
-    int x, y, i;			/* counters */
+    int x, i;				/* counters */
     int numbuffs = 4;			/* number of TX/RX buffers and descs */
     u16 status = 0x8300;		/* TX ring status */
+    u16 teststatus;			/* test of ring status */
     int rc;				/* return code */
     int size;				/* size of packets */
     unsigned char *packet;		/* source packet data */
     static int data_len = 60;		/* length of source packets */
     unsigned long flags;
+    unsigned long ticks;
 
     *data1 = 1;			/* status of test, default to fail */
     rc = 1;			/* default to fail */
 
+    if (netif_running(dev))
+	pcnet32_close(dev);
+
     spin_lock_irqsave(&lp->lock, flags);
-    lp->a.write_csr(ioaddr, 0, 0x7904);
 
-    netif_stop_queue(dev);
+    /* Reset the PCNET32 */
+    lp->a.reset (ioaddr);
+
+    /* switch pcnet32 to 32bit mode */
+    lp->a.write_bcr (ioaddr, 20, 2);
+
+    lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
+    lp->init_block.filter[0] = 0;
+    lp->init_block.filter[1] = 0;
 
     /* purge & init rings but don't actually restart */
     pcnet32_restart(dev, 0x0000);
 
     lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */
 
-    x = a->read_bcr(ioaddr, 32);	/* set internal loopback in BSR32 */
-    x = x | 0x00000002;
-    a->write_bcr(ioaddr, 32, x);
-
     /* Initialize Transmit buffers. */
     size = data_len + 15;
     for (x=0; x<numbuffs; x++) {
@@ -646,19 +687,21 @@ static int pcnet32_loopback_test(struct 
 	    skb_put(skb, size);		/* create space for data */
 	    lp->tx_skbuff[x] = skb;
 	    lp->tx_ring[x].length = le16_to_cpu(-skb->len);
-	    lp->tx_ring[x].misc = 0x00000000;
+	    lp->tx_ring[x].misc = 0;
 
-	    /* put DA and SA into the skb */
-	    for (i=0; i<12; i++)
-		*packet++ = 0xff;
+            /* put DA and SA into the skb */
+	    for (i=0; i<6; i++)
+		*packet++ = dev->dev_addr[i];
+	    for (i=0; i<6; i++)
+		*packet++ = dev->dev_addr[i];
 	    /* type */
 	    *packet++ = 0x08;
 	    *packet++ = 0x06;
 	    /* packet number */
 	    *packet++ = x;
 	    /* fill packet with data */
-	    for (y=0; y<data_len; y++)
-		*packet++ = y;
+	    for (i=0; i<data_len; i++)
+		*packet++ = i;
 
 	    lp->tx_dma_addr[x] = pci_map_single(lp->pci_dev, skb->data,
 		    skb->len, PCI_DMA_TODEVICE);
@@ -668,20 +711,41 @@ static int pcnet32_loopback_test(struct 
 	}
     }
 
-    lp->a.write_csr(ioaddr, 0, 0x0002);	/* Set STRT bit */
-    spin_unlock_irqrestore(&lp->lock, flags);
+    x = a->read_bcr(ioaddr, 32);	/* set internal loopback in BSR32 */
+    x = x | 0x0002;
+    a->write_bcr(ioaddr, 32, x);
 
-    mdelay(50);				/* wait a bit */
+    lp->a.write_csr (ioaddr, 15, 0x0044);	/* set int loopback in CSR15 */
 
-    spin_lock_irqsave(&lp->lock, flags);
-    lp->a.write_csr(ioaddr, 0, 0x0004);	/* Set STOP bit */
+    teststatus = le16_to_cpu(0x8000);
+    lp->a.write_csr(ioaddr, 0, 0x0002);		/* Set STRT bit */
+
+    /* Check status of descriptors */
+    for (x=0; x<numbuffs; x++) {
+	ticks = 0;
+	rmb();
+	while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
+	    spin_unlock_irqrestore(&lp->lock, flags);
+	    mdelay(1);
+	    spin_lock_irqsave(&lp->lock, flags);
+	    rmb();
+	    ticks++;
+	}
+	if (ticks == 200) {
+	    if (netif_msg_hw(lp))
+		printk("%s: Desc %d failed to reset!\n",dev->name,x);
+	    break;
+	}
+    }
 
+    lp->a.write_csr(ioaddr, 0, 0x0004);		/* Set STOP bit */
+    wmb();
     if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
 	printk(KERN_DEBUG "%s: RX loopback packets:\n", dev->name);
 
 	for (x=0; x<numbuffs; x++) {
 	    printk(KERN_DEBUG "%s: Packet %d:\n", dev->name, x);
-	    skb=lp->rx_skbuff[x];
+	    skb = lp->rx_skbuff[x];
 	    for (i=0; i<size; i++) {
 		printk("%02x ", *(skb->data+i));
 	    }
@@ -714,20 +778,153 @@ clean_up:
     a->write_csr(ioaddr, 15, (x & ~0x0044));	/* reset bits 6 and 2 */
 
     x = a->read_bcr(ioaddr, 32);		/* reset internal loopback */
-    x = x & ~0x00000002;
+    x = x & ~0x0002;
     a->write_bcr(ioaddr, 32, x);
 
-    pcnet32_restart(dev, 0x0042);		/* resume normal operation */
-
-    netif_wake_queue(dev);
-
-    /* Clear interrupts, and set interrupt enable. */
-    lp->a.write_csr(ioaddr, 0, 0x7940);
     spin_unlock_irqrestore(&lp->lock, flags);
 
+    if (netif_running(dev)) {
+	pcnet32_open(dev);
+    } else {
+	lp->a.write_bcr (ioaddr, 20, 4);	/* return to 16bit mode */
+    }
+
     return(rc);
 } /* end pcnet32_loopback_test  */
 
+static void pcnet32_led_blink_callback(struct net_device *dev)
+{
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;
+    ulong ioaddr = dev->base_addr;
+    unsigned long flags;
+    int i;
+
+    spin_lock_irqsave(&lp->lock, flags);
+    for (i=4; i<8; i++) {
+	a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT);
+}
+
+static int pcnet32_phys_id(struct net_device *dev, u32 data)
+{
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;
+    ulong ioaddr = dev->base_addr;
+    unsigned long flags;
+    int i, regs[4];
+
+    if (!lp->blink_timer.function) {
+	init_timer(&lp->blink_timer);
+	lp->blink_timer.function = (void *) pcnet32_led_blink_callback;
+	lp->blink_timer.data = (unsigned long) dev;
+    }
+
+    /* Save the current value of the bcrs */
+    spin_lock_irqsave(&lp->lock, flags);
+    for (i=4; i<8; i++) {
+	regs[i-4] = a->read_bcr(ioaddr, i);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    mod_timer(&lp->blink_timer, jiffies);
+    set_current_state(TASK_INTERRUPTIBLE);
+
+    if ((!data) || (data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)))
+    data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+    schedule_timeout(data * HZ);
+    del_timer_sync(&lp->blink_timer);
+
+    /* Restore the original value of the bcrs */
+    spin_lock_irqsave(&lp->lock, flags);
+    for (i=4; i<8; i++) {
+	a->write_bcr(ioaddr, i, regs[i-4]);
+    }
+    spin_unlock_irqrestore(&lp->lock, flags);
+
+    return 0;
+}
+
+static int pcnet32_get_regs_len(struct net_device *dev)
+{
+    return(PCNET32_NUM_REGS * sizeof(u16));
+}
+
+static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+	void *ptr)
+{
+    int i, csr0;
+    u16 *buff = ptr;
+    struct pcnet32_private *lp = dev->priv;
+    struct pcnet32_access *a = &lp->a;
+    ulong ioaddr = dev->base_addr;
+    int ticks;
+    unsigned long flags;
+
+    spin_lock_irqsave(&lp->lock, flags);
+
+    csr0 = a->read_csr(ioaddr, 0);
+    if (!(csr0 & 0x0004)) {	/* If not stopped */
+	/* set SUSPEND (SPND) - CSR5 bit 0 */
+	a->write_csr(ioaddr, 5, 0x0001);
+
+	/* poll waiting for bit to be set */
+	ticks = 0;
+	while (!(a->read_csr(ioaddr, 5) & 0x0001)) {
+	    spin_unlock_irqrestore(&lp->lock, flags);
+	    mdelay(1);
+	    spin_lock_irqsave(&lp->lock, flags);
+	    ticks++;
+	    if (ticks > 200) {
+		if (netif_msg_hw(lp))
+		    printk(KERN_DEBUG "%s: Error getting into suspend!\n",
+			    dev->name);
+		break;
+	    }
+	}
+    }
+
+    /* read address PROM */
+    for (i=0; i<16; i += 2)
+	*buff++ = inw(ioaddr + i);
+
+    /* read control and status registers */
+    for (i=0; i<90; i++) {
+	*buff++ = a->read_csr(ioaddr, i);
+    }
+
+    *buff++ = a->read_csr(ioaddr, 112);
+    *buff++ = a->read_csr(ioaddr, 114);
+
+    /* read bus configuration registers */
+    for (i=0; i<36; i++) {
+	*buff++ = a->read_bcr(ioaddr, i);
+    }
+
+    /* read mii phy registers */
+    if (lp->mii) {
+	for (i=0; i<32; i++) {
+	    lp->a.write_bcr(ioaddr, 33, ((lp->mii_if.phy_id) << 5) | i);
+	    *buff++ = lp->a.read_bcr(ioaddr, 34);
+	}
+    }
+
+    if (!(csr0 & 0x0004)) {	/* If not stopped */
+	/* clear SUSPEND (SPND) - CSR5 bit 0 */
+	a->write_csr(ioaddr, 5, 0x0000);
+    }
+
+    i = buff - (u16 *)ptr;
+    for (; i < PCNET32_NUM_REGS; i++)
+	*buff++ = 0;
+
+    spin_unlock_irqrestore(&lp->lock, flags);
+}
+
 static struct ethtool_ops pcnet32_ethtool_ops = {
     .get_settings	= pcnet32_get_settings,
     .set_settings	= pcnet32_set_settings,
@@ -742,22 +939,28 @@ static struct ethtool_ops pcnet32_ethtoo
     .get_strings	= pcnet32_get_strings,
     .self_test_count	= pcnet32_self_test_count,
     .self_test		= pcnet32_ethtool_test,
+    .phys_id		= pcnet32_phys_id,
+    .get_regs_len	= pcnet32_get_regs_len,
+    .get_regs		= pcnet32_get_regs,
 };
 
-/* only probes for non-PCI devices, the rest are handled by 
+/* only probes for non-PCI devices, the rest are handled by
  * pci_register_driver via pcnet32_probe_pci */
 
 static void __devinit
 pcnet32_probe_vlbus(void)
 {
     unsigned int *port, ioaddr;
-    
+
     /* search for PCnet32 VLB cards at known addresses */
     for (port = pcnet32_portlist; (ioaddr = *port); port++) {
-	if (!check_region(ioaddr, PCNET32_TOTAL_SIZE)) {
+	if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_vlbus")) {
 	    /* check if there is really a pcnet chip on that ioaddr */
-	    if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57))
+	    if ((inb(ioaddr + 14) == 0x57) && (inb(ioaddr + 15) == 0x57)) {
 		pcnet32_probe1(ioaddr, 0, 0, NULL);
+	    } else {
+		release_region(ioaddr, PCNET32_TOTAL_SIZE);
+	    }
 	}
     }
 }
@@ -771,28 +974,36 @@ pcnet32_probe_pci(struct pci_dev *pdev, 
 
     err = pci_enable_device(pdev);
     if (err < 0) {
-	printk(KERN_ERR PFX "failed to enable device -- err=%d\n", err);
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_ERR PFX "failed to enable device -- err=%d\n", err);
 	return err;
     }
     pci_set_master(pdev);
 
     ioaddr = pci_resource_start (pdev, 0);
     if (!ioaddr) {
-        printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n");
-        return -ENODEV;
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk (KERN_ERR PFX "card has no PCI IO resources, aborting\n");
+	return -ENODEV;
     }
-    
+
     if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) {
-	printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n");
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n");
 	return -ENODEV;
     }
+    if (request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci") == NULL) {
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_ERR PFX "io address range already allocated\n");
+	return -EBUSY;
+    }
 
     return pcnet32_probe1(ioaddr, pdev->irq, 1, pdev);
 }
 
 
-/* pcnet32_probe1 
- *  Called from both pcnet32_probe_vlbus and pcnet_probe_pci.  
+/* pcnet32_probe1
+ *  Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
  *  pdev will be NULL when called from pcnet32_probe_vlbus.
  */
 static int __devinit
@@ -802,12 +1013,13 @@ pcnet32_probe1(unsigned long ioaddr, uns
     struct pcnet32_private *lp;
     dma_addr_t lp_dma_addr;
     int i, media;
-    int fdx, mii, fset, dxsuflo, ltint;
+    int fdx, mii, fset, dxsuflo;
     int chip_version;
     char *chipname;
     struct net_device *dev;
     struct pcnet32_access *a = NULL;
     u8 promaddr[6];
+    int ret = -ENODEV;
 
     /* reset the chip */
     pcnet32_wio_reset(ioaddr);
@@ -820,19 +1032,20 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	if (pcnet32_dwio_read_csr(ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) {
 	    a = &pcnet32_dwio;
 	} else
-	    return -ENODEV;
+	    goto err_release_region;
     }
 
     chip_version = a->read_csr(ioaddr, 88) | (a->read_csr(ioaddr,89) << 16);
-    if (pcnet32_debug & NETIF_MSG_PROBE)
+    if ((pcnet32_debug & NETIF_MSG_PROBE) && (pcnet32_debug & NETIF_MSG_HW))
 	printk(KERN_INFO "  PCnet chip version is %#x.\n", chip_version);
     if ((chip_version & 0xfff) != 0x003) {
-	printk(KERN_INFO PFX "Unsupported chip version.\n");
-	return -ENODEV;
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_INFO PFX "Unsupported chip version.\n");
+	goto err_release_region;
     }
-    
+
     /* initialize variables */
-    fdx = mii = fset = dxsuflo = ltint = 0;
+    fdx = mii = fset = dxsuflo = 0;
     chip_version = (chip_version >> 12) & 0xffff;
 
     switch (chip_version) {
@@ -852,7 +1065,6 @@ pcnet32_probe1(unsigned long ioaddr, uns
     case 0x2623:
 	chipname = "PCnet/FAST 79C971"; /* PCI */
 	fdx = 1; mii = 1; fset = 1;
-	ltint = 1;
 	break;
     case 0x2624:
 	chipname = "PCnet/FAST+ 79C972"; /* PCI */
@@ -865,7 +1077,7 @@ pcnet32_probe1(unsigned long ioaddr, uns
     case 0x2626:
 	chipname = "PCnet/Home 79C978"; /* PCI */
 	fdx = 1;
-	/* 
+	/*
 	 * This is based on specs published at www.amd.com.  This section
 	 * assumes that a card with a 79C978 wants to go into 1Mb HomePNA
 	 * mode.  The 79C978 can also go into standard ethernet, and there
@@ -874,12 +1086,6 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	 */
 	/* switch to home wiring mode */
 	media = a->read_bcr(ioaddr, 49);
-#if 0
-	if (pcnet32_debug > 2)
-	    printk(KERN_DEBUG PFX "media value %#x.\n",  media);
-	media &= ~3;
-	media |= 1;
-#endif
 	if (pcnet32_debug & NETIF_MSG_PROBE)
 	    printk(KERN_DEBUG PFX "media reset to %#x.\n",  media);
 	a->write_bcr(ioaddr, 49, media);
@@ -888,34 +1094,42 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	chipname = "PCnet/FAST III 79C975"; /* PCI */
 	fdx = 1; mii = 1;
 	break;
+    case 0x2628:
+	chipname = "PCnet/PRO 79C976";
+	fdx = 1; mii = 1;
+	break;
     default:
-	printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n",
-			chip_version);
-	return -ENODEV;
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_INFO PFX "PCnet version %#x, no PCnet32 chip.\n",
+		    chip_version);
+	goto err_release_region;
     }
 
     /*
      *	On selected chips turn on the BCR18:NOUFLO bit. This stops transmit
      *	starting until the packet is loaded. Strike one for reliability, lose
-     *	one for latency - although on PCI this isnt a big loss. Older chips 
+     *	one for latency - although on PCI this isnt a big loss. Older chips
      *	have FIFO's smaller than a packet, so you can't do this.
+     *	Turn on BCR18:BurstRdEn and BCR18:BurstWrEn.
      */
-	 
-    if(fset)
-    {
-	a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800));
+
+    if (fset) {
+	a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0860));
 	a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00);
 	dxsuflo = 1;
-	ltint = 1;
     }
-    
+
     dev = alloc_etherdev(0);
     if (!dev) {
-	printk(KERN_ERR PFX "Memory allocation failed.\n");
-	return -ENOMEM;
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_ERR PFX "Memory allocation failed.\n");
+	ret = -ENOMEM;
+	goto err_release_region;
     }
+    SET_NETDEV_DEV(dev, &pdev->dev);
 
-    printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
+    if (pcnet32_debug & NETIF_MSG_PROBE)
+	printk(KERN_INFO PFX "%s at %#3lx,", chipname, ioaddr);
 
     /* In most chips, after a chip reset, the ethernet address is read from the
      * station address PROM at the base address and programmed into the
@@ -935,60 +1149,63 @@ pcnet32_probe1(unsigned long ioaddr, uns
     /* read PROM address and compare with CSR address */
     for (i = 0; i < 6; i++)
 	promaddr[i] = inb(ioaddr + i);
-    
-    if( memcmp( promaddr, dev->dev_addr, 6)
-	|| !is_valid_ether_addr(dev->dev_addr) ) {
+
+    if (memcmp(promaddr, dev->dev_addr, 6)
+	|| !is_valid_ether_addr(dev->dev_addr)) {
 #ifndef __powerpc__
-	if( is_valid_ether_addr(promaddr) ){
+	if (is_valid_ether_addr(promaddr)) {
 #else
-	if( !is_valid_ether_addr(dev->dev_addr)
+	if (!is_valid_ether_addr(dev->dev_addr)
 	    && is_valid_ether_addr(promaddr)) {
 #endif
-	    printk(" warning: CSR address invalid,\n");
-	    printk(KERN_INFO "    using instead PROM address of");
+	    if (pcnet32_debug & NETIF_MSG_PROBE) {
+		printk(" warning: CSR address invalid,\n");
+		printk(KERN_INFO "    using instead PROM address of");
+	    }
 	    memcpy(dev->dev_addr, promaddr, 6);
 	}
     }
 
     /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */
-    if( !is_valid_ether_addr(dev->dev_addr) )
+    if (!is_valid_ether_addr(dev->dev_addr))
 	memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
 
-    for (i = 0; i < 6; i++)
-	printk(" %2.2x", dev->dev_addr[i] );
-
-    if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */
-	i = a->read_csr(ioaddr, 80) & 0x0C00;  /* Check tx_start_pt */
-	printk("\n" KERN_INFO "    tx_start_pt(0x%04x):",i);
-	switch(i>>10) {
-	    case 0: printk("  20 bytes,"); break;
-	    case 1: printk("  64 bytes,"); break;
-	    case 2: printk(" 128 bytes,"); break;
-	    case 3: printk("~220 bytes,"); break;
-	}
-	i = a->read_bcr(ioaddr, 18);  /* Check Burst/Bus control */
-	printk(" BCR18(%x):",i&0xffff);
-	if (i & (1<<5)) printk("BurstWrEn ");
-	if (i & (1<<6)) printk("BurstRdEn ");
-	if (i & (1<<7)) printk("DWordIO ");
-	if (i & (1<<11)) printk("NoUFlow ");
-	i = a->read_bcr(ioaddr, 25);
-	printk("\n" KERN_INFO "    SRAMSIZE=0x%04x,",i<<8);
-	i = a->read_bcr(ioaddr, 26);
-	printk(" SRAM_BND=0x%04x,",i<<8);
-	i = a->read_bcr(ioaddr, 27);
-	if (i & (1<<14)) printk("LowLatRx");
+    if (pcnet32_debug & NETIF_MSG_PROBE) {
+	for (i = 0; i < 6; i++)
+	    printk(" %2.2x", dev->dev_addr[i]);
+
+	/* Version 0x2623 - 0x2624 */
+	if (((chip_version + 1) & 0xfffe) == 0x2624) {
+	    i = a->read_csr(ioaddr, 80) & 0x0C00;  /* Check tx_start_pt */
+	    printk("\n" KERN_INFO "    tx_start_pt(0x%04x):",i);
+	    switch(i>>10) {
+		case 0: printk("  20 bytes,"); break;
+		case 1: printk("  64 bytes,"); break;
+		case 2: printk(" 128 bytes,"); break;
+		case 3: printk("~220 bytes,"); break;
+	    }
+	    i = a->read_bcr(ioaddr, 18);  /* Check Burst/Bus control */
+	    printk(" BCR18(%x):",i&0xffff);
+	    if (i & (1<<5)) printk("BurstWrEn ");
+	    if (i & (1<<6)) printk("BurstRdEn ");
+	    if (i & (1<<7)) printk("DWordIO ");
+	    if (i & (1<<11)) printk("NoUFlow ");
+	    i = a->read_bcr(ioaddr, 25);
+	    printk("\n" KERN_INFO "    SRAMSIZE=0x%04x,",i<<8);
+	    i = a->read_bcr(ioaddr, 26);
+	    printk(" SRAM_BND=0x%04x,",i<<8);
+	    i = a->read_bcr(ioaddr, 27);
+	    if (i & (1<<14)) printk("LowLatRx");
+	}
     }
 
     dev->base_addr = ioaddr;
-    if (request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname) == NULL)
-	return -EBUSY;
-    
     /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */
     if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {
-	printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
-	release_region(ioaddr, PCNET32_TOTAL_SIZE);
-	return -ENOMEM;
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_ERR PFX "Consistent memory allocation failed.\n");
+	ret = -ENOMEM;
+	goto err_free_netdev;
     }
 
     memset(lp, 0, sizeof(*lp));
@@ -996,7 +1213,9 @@ pcnet32_probe1(unsigned long ioaddr, uns
     lp->pci_dev = pdev;
 
     spin_lock_init(&lp->lock);
-    
+
+    SET_MODULE_OWNER(dev);
+    SET_NETDEV_DEV(dev, &pdev->dev);
     dev->priv = lp;
     lp->name = chipname;
     lp->shared_irq = shared;
@@ -1004,7 +1223,6 @@ pcnet32_probe1(unsigned long ioaddr, uns
     lp->mii_if.phy_id_mask = 0x1f;
     lp->mii_if.reg_num_mask = 0x1f;
     lp->dxsuflo = dxsuflo;
-    lp->ltint = ltint;
     lp->mii = mii;
     lp->msg_enable = pcnet32_debug;
     if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping)))
@@ -1014,47 +1232,53 @@ pcnet32_probe1(unsigned long ioaddr, uns
     lp->mii_if.dev = dev;
     lp->mii_if.mdio_read = mdio_read;
     lp->mii_if.mdio_write = mdio_write;
-    
-    if (fdx && !(lp->options & PCNET32_PORT_ASEL) && 
+
+    if (fdx && !(lp->options & PCNET32_PORT_ASEL) &&
 		((cards_found>=MAX_UNITS) || full_duplex[cards_found]))
 	lp->options |= PCNET32_PORT_FD;
-    
+
     if (!a) {
-      printk(KERN_ERR PFX "No access methods\n");
-      pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
-      release_region(ioaddr, PCNET32_TOTAL_SIZE);
-      return -ENODEV;
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(KERN_ERR PFX "No access methods\n");
+	ret = -ENODEV;
+	goto err_free_consistent;
     }
     lp->a = *a;
-    
+
     /* detect special T1/E1 WAN card by checking for MAC address */
-    if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75)
+    if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0
+	    && dev->dev_addr[2] == 0x75)
 	lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
 
     lp->init_block.mode = le16_to_cpu(0x0003);	/* Disable Rx and Tx. */
-    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS); 
+    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
     for (i = 0; i < 6; i++)
 	lp->init_block.phys_addr[i] = dev->dev_addr[i];
     lp->init_block.filter[0] = 0x00000000;
     lp->init_block.filter[1] = 0x00000000;
-    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring));
-    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring));
-    
+    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
+	    offsetof(struct pcnet32_private, rx_ring));
+    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
+	    offsetof(struct pcnet32_private, tx_ring));
+
     /* switch pcnet32 to 32bit mode */
-    a->write_bcr (ioaddr, 20, 2);
+    a->write_bcr(ioaddr, 20, 2);
+
+    a->write_csr(ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private,
+		    init_block)) & 0xffff);
+    a->write_csr(ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private,
+		    init_block)) >> 16);
 
-    a->write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) & 0xffff);
-    a->write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16);
-    
     if (irq_line) {
 	dev->irq = irq_line;
     }
-    
-    if (dev->irq >= 2)
-	printk(" assigned IRQ %d.\n", dev->irq);
-    else {
+
+    if (dev->irq >= 2) {
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(" assigned IRQ %d.\n", dev->irq);
+    } else {
 	unsigned long irq_mask = probe_irq_on();
-	
+
 	/*
 	 * To auto-IRQ we enable the initialization-done and DMA error
 	 * interrupts. For ISA boards we get a DMA error, but VLB and PCI
@@ -1063,22 +1287,26 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	/* Trigger an initialization just for the interrupt. */
 	a->write_csr (ioaddr, 0, 0x41);
 	mdelay (1);
-	
+
 	dev->irq = probe_irq_off (irq_mask);
-	if (dev->irq)
-	    printk(", probed IRQ %d.\n", dev->irq);
-	else {
-	    printk(", failed to detect IRQ line.\n");
-	    pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
-	    release_region(ioaddr, PCNET32_TOTAL_SIZE);
-	    return -ENODEV;
+	if (!dev->irq) {
+	    if (pcnet32_debug & NETIF_MSG_PROBE)
+		printk(", failed to detect IRQ line.\n");
+	    ret = -ENODEV;
+	    goto err_free_consistent;
 	}
+	if (pcnet32_debug & NETIF_MSG_PROBE)
+	    printk(", probed IRQ %d.\n", dev->irq);
     }
 
     /* Set the mii phy_id so that we can query the link state */
     if (lp->mii)
 	lp->mii_if.phy_id = ((lp->a.read_bcr (ioaddr, 33)) >> 5) & 0x1f;
-    
+
+    init_timer (&lp->watchdog_timer);
+    lp->watchdog_timer.data = (unsigned long) dev;
+    lp->watchdog_timer.function = (void *) &pcnet32_watchdog;
+
     /* The PCNET32-specific entries in the device structure. */
     dev->open = &pcnet32_open;
     dev->hard_start_xmit = &pcnet32_start_xmit;
@@ -1090,6 +1318,14 @@ 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;
+
     if (pdev) {
 	pci_set_drvdata(pdev, dev);
     } else {
@@ -1097,11 +1333,21 @@ pcnet32_probe1(unsigned long ioaddr, uns
 	pcnet32_dev = dev;
     }
 
-    /* Fill in the generic fields of the device structure. */
-    register_netdev(dev);
-    printk(KERN_INFO "%s: registered as %s\n",dev->name, lp->name);
+    if (pcnet32_debug & NETIF_MSG_PROBE)
+	printk(KERN_INFO "%s: registered as %s\n", dev->name, lp->name);
     cards_found++;
+
+    a->write_bcr(ioaddr, 2, 0x1002);	/* enable LED writes */
+
     return 0;
+
+err_free_consistent:
+    pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);
+err_free_netdev:
+    free_netdev(dev);
+err_release_region:
+    release_region(ioaddr, PCNET32_TOTAL_SIZE);
+    return ret;
 }
 
 
@@ -1113,13 +1359,15 @@ pcnet32_open(struct net_device *dev)
     u16 val;
     int i;
     int rc;
+    unsigned long flags;
 
     if (dev->irq == 0 ||
 	request_irq(dev->irq, &pcnet32_interrupt,
-		    lp->shared_irq ? SA_SHIRQ : 0, lp->name, (void *)dev)) {
+		    lp->shared_irq ? SA_SHIRQ : 0, dev->name, (void *)dev)) {
 	return -EAGAIN;
     }
 
+    spin_lock_irqsave(&lp->lock, flags);
     /* Check for a valid station address */
     if (!is_valid_ether_addr(dev->dev_addr)) {
 	rc = -EINVAL;
@@ -1138,13 +1386,13 @@ pcnet32_open(struct net_device *dev)
 	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),
 	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),
 	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));
-    
+
     /* set/reset autoselect bit */
     val = lp->a.read_bcr (ioaddr, 2) & ~2;
     if (lp->options & PCNET32_PORT_ASEL)
 	val |= 2;
     lp->a.write_bcr (ioaddr, 2, val);
-    
+
     /* handle full duplex setting */
     if (lp->mii_if.full_duplex) {
 	val = lp->a.read_bcr (ioaddr, 9) & ~3;
@@ -1154,34 +1402,38 @@ pcnet32_open(struct net_device *dev)
 		val |= 2;
 	} else if (lp->options & PCNET32_PORT_ASEL) {
 	/* workaround of xSeries250, turn on for 79C975 only */
-	    i = ((lp->a.read_csr(ioaddr, 88) | (lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff;
-	    if (i == 0x2627) val |= 3;
+	    i = ((lp->a.read_csr(ioaddr, 88) |
+			(lp->a.read_csr(ioaddr,89) << 16)) >> 12) & 0xffff;
+	    if (i == 0x2627)
+		val |= 3;
 	}
 	lp->a.write_bcr (ioaddr, 9, val);
     }
-    
+
     /* set/reset GPSI bit in test register */
     val = lp->a.read_csr (ioaddr, 124) & ~0x10;
     if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
 	val |= 0x10;
     lp->a.write_csr (ioaddr, 124, val);
-    
+
     if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
-	val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */
+	/* disable Auto Negotiation, set 10Mpbs, HD */
+	val = lp->a.read_bcr (ioaddr, 32) & ~0x38;
 	if (lp->options & PCNET32_PORT_FD)
 	    val |= 0x10;
 	if (lp->options & PCNET32_PORT_100)
 	    val |= 0x08;
 	lp->a.write_bcr (ioaddr, 32, val);
     } else {
-	if (lp->options & PCNET32_PORT_ASEL) {  /* enable auto negotiate, setup, disable fd */
-		val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
-		val |= 0x20;
-		lp->a.write_bcr(ioaddr, 32, val);
+	if (lp->options & PCNET32_PORT_ASEL) {
+	    /* enable auto negotiate, setup, disable fd */
+	    val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
+	    val |= 0x20;
+	    lp->a.write_bcr(ioaddr, 32, val);
 	}
     }
 
-#ifdef DO_DXSUFLO 
+#ifdef DO_DXSUFLO
     if (lp->dxsuflo) { /* Disable transmit stop on underflow */
 	val = lp->a.read_csr (ioaddr, 3);
 	val |= 0x40;
@@ -1189,34 +1441,36 @@ pcnet32_open(struct net_device *dev)
     }
 #endif
 
-    if (lp->ltint) { /* Enable TxDone-intr inhibitor */
-	val = lp->a.read_csr (ioaddr, 5);
-	val |= (1<<14);
-	lp->a.write_csr (ioaddr, 5, val);
-    }
-   
     lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
-    lp->init_block.filter[0] = 0x00000000;
-    lp->init_block.filter[1] = 0x00000000;
+    pcnet32_load_multicast(dev);
+
     if (pcnet32_init_ring(dev)) {
 	rc = -ENOMEM;
 	goto err_free_ring;
     }
-    
+
     /* Re-initialize the PCNET32, and start it when done. */
-    lp->a.write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) &0xffff);
-    lp->a.write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16);
+    lp->a.write_csr (ioaddr, 1, (lp->dma_addr +
+		offsetof(struct pcnet32_private, init_block)) &0xffff);
+    lp->a.write_csr (ioaddr, 2, (lp->dma_addr +
+		offsetof(struct pcnet32_private, init_block)) >> 16);
 
     lp->a.write_csr (ioaddr, 4, 0x0915);
     lp->a.write_csr (ioaddr, 0, 0x0001);
 
     netif_start_queue(dev);
 
+    /* If we have mii, print the link status and start the watchdog */
+    if (lp->mii) {
+	mii_check_media (&lp->mii_if, netif_msg_link(lp), 1);
+	mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+    }
+
     i = 0;
     while (i++ < 100)
 	if (lp->a.read_csr (ioaddr, 0) & 0x0100)
 	    break;
-    /* 
+    /*
      * We used to clear the InitDone bit, 0x0100, here but Mark Stockton
      * reports that doing so triggers a bug in the '974.
      */
@@ -1224,33 +1478,34 @@ pcnet32_open(struct net_device *dev)
 
     if (netif_msg_ifup(lp))
 	printk(KERN_DEBUG "%s: pcnet32 open after %d ticks, init block %#x csr0 %4.4x.\n",
-	       dev->name, i, (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)),
-	       lp->a.read_csr(ioaddr, 0));
+		dev->name, i, (u32) (lp->dma_addr +
+		    offsetof(struct pcnet32_private, init_block)),
+		lp->a.read_csr(ioaddr, 0));
 
+    spin_unlock_irqrestore(&lp->lock, flags);
 
-    MOD_INC_USE_COUNT;
-    
     return 0;	/* Always succeed */
 
 err_free_ring:
     /* free any allocated skbuffs */
     for (i = 0; i < RX_RING_SIZE; i++) {
-	lp->rx_ring[i].status = 0;			    
+	lp->rx_ring[i].status = 0;
 	if (lp->rx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+	    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;
-        lp->rx_dma_addr[i] = 0;
+	lp->rx_dma_addr[i] = 0;
     }
     /*
-     * Switch back to 16bit mode to avoid problems with dumb 
+     * Switch back to 16bit mode to avoid problems with dumb
      * DOS packet driver after a warm reboot
      */
     lp->a.write_bcr (ioaddr, 20, 4);
 
 err_free_irq:
+    spin_unlock_irqrestore(&lp->lock, flags);
     free_irq(dev->irq, dev);
     return rc;
 }
@@ -1268,7 +1523,7 @@ err_free_irq:
  * restarting the chip, but I'm too lazy to do so right now.  dplatt@3do.com
  */
 
-static void 
+static void
 pcnet32_purge_tx_ring(struct net_device *dev)
 {
     struct pcnet32_private *lp = dev->priv;
@@ -1276,10 +1531,11 @@ pcnet32_purge_tx_ring(struct net_device 
 
     for (i = 0; i < TX_RING_SIZE; i++) {
 	if (lp->tx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
-	    dev_kfree_skb_any(lp->tx_skbuff[i]); 
+	    pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
+		    lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
+	    dev_kfree_skb_any(lp->tx_skbuff[i]);
 	    lp->tx_skbuff[i] = NULL;
-            lp->tx_dma_addr[i] = 0;
+	    lp->tx_dma_addr[i] = 0;
 	}
     }
 }
@@ -1297,37 +1553,41 @@ pcnet32_init_ring(struct net_device *dev
     lp->dirty_rx = lp->dirty_tx = 0;
 
     for (i = 0; i < RX_RING_SIZE; i++) {
-        struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
+	struct sk_buff *rx_skbuff = lp->rx_skbuff[i];
 	if (rx_skbuff == NULL) {
 	    if (!(rx_skbuff = lp->rx_skbuff[i] = dev_alloc_skb (PKT_BUF_SZ))) {
 		/* there is not much, we can do at this point */
-		printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n",dev->name);
+		if (pcnet32_debug & NETIF_MSG_DRV)
+		    printk(KERN_ERR "%s: pcnet32_init_ring dev_alloc_skb failed.\n",
+			    dev->name);
 		return -1;
 	    }
 	    skb_reserve (rx_skbuff, 2);
 	}
 
-	if (lp->rx_dma_addr[i] == 0) 
-		lp->rx_dma_addr[i] = pci_map_single(lp->pci_dev,
-			rx_skbuff->tail, PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
+	if (lp->rx_dma_addr[i] == 0)
+	    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(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
-       the upper ownership bit. */
+     * the upper ownership bit. */
     for (i = 0; i < TX_RING_SIZE; i++) {
 	lp->tx_ring[i].base = 0;
 	lp->tx_ring[i].status = 0;
-        lp->tx_dma_addr[i] = 0;
+	lp->tx_dma_addr[i] = 0;
     }
     wmb(); /* Make sure all changes are visible */
 
     lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
     for (i = 0; i < 6; i++)
 	lp->init_block.phys_addr[i] = dev->dev_addr[i];
-    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring));
-    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring));
+    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr +
+	    offsetof(struct pcnet32_private, rx_ring));
+    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr +
+	    offsetof(struct pcnet32_private, tx_ring));
     return 0;
 }
 
@@ -1337,11 +1597,11 @@ pcnet32_restart(struct net_device *dev, 
     struct pcnet32_private *lp = dev->priv;
     unsigned long ioaddr = dev->base_addr;
     int i;
-    
+
     pcnet32_purge_tx_ring(dev);
     if (pcnet32_init_ring(dev))
 	return;
-    
+
     /* ReInit Ring */
     lp->a.write_csr (ioaddr, 0, 1);
     i = 0;
@@ -1361,31 +1621,36 @@ pcnet32_tx_timeout (struct net_device *d
 
     spin_lock_irqsave(&lp->lock, flags);
     /* Transmitter timeout, serious problems. */
+    if (pcnet32_debug & NETIF_MSG_DRV)
 	printk(KERN_ERR "%s: transmit timed out, status %4.4x, resetting.\n",
-	       dev->name, lp->a.read_csr(ioaddr, 0));
-	lp->a.write_csr (ioaddr, 0, 0x0004);
-	lp->stats.tx_errors++;
-	if (netif_msg_tx_err(lp)) {
-	    int i;
-	    printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
-	       lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
-	       lp->cur_rx);
-	    for (i = 0 ; i < RX_RING_SIZE; i++)
-	    printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
-		   lp->rx_ring[i].base, -lp->rx_ring[i].buf_length,
-		   lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status);
-	    for (i = 0 ; i < TX_RING_SIZE; i++)
-	    printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
-		   lp->tx_ring[i].base, -lp->tx_ring[i].length,
-		   lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status);
-	    printk("\n");
-	}
-	pcnet32_restart(dev, 0x0042);
+		dev->name, lp->a.read_csr(ioaddr, 0));
+    lp->a.write_csr (ioaddr, 0, 0x0004);
+    lp->stats.tx_errors++;
+    if (netif_msg_tx_err(lp)) {
+	int i;
+	printk(KERN_DEBUG " Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.",
+	   lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "",
+	   lp->cur_rx);
+	for (i = 0 ; i < RX_RING_SIZE; i++)
+	printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+	       le32_to_cpu(lp->rx_ring[i].base),
+	       (-le16_to_cpu(lp->rx_ring[i].buf_length)) & 0xffff,
+	       le32_to_cpu(lp->rx_ring[i].msg_length),
+	       le16_to_cpu(lp->rx_ring[i].status));
+	for (i = 0 ; i < TX_RING_SIZE; i++)
+	printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ",
+	       le32_to_cpu(lp->tx_ring[i].base),
+	       (-le16_to_cpu(lp->tx_ring[i].length)) & 0xffff,
+	       le32_to_cpu(lp->tx_ring[i].misc),
+	       le16_to_cpu(lp->tx_ring[i].status));
+	printk("\n");
+    }
+    pcnet32_restart(dev, 0x0042);
 
-	dev->trans_start = jiffies;
-	netif_wake_queue(dev);
+    dev->trans_start = jiffies;
+    netif_wake_queue(dev);
 
-	spin_unlock_irqrestore(&lp->lock, flags);
+    spin_unlock_irqrestore(&lp->lock, flags);
 }
 
 
@@ -1398,45 +1663,33 @@ pcnet32_start_xmit(struct sk_buff *skb, 
     int entry;
     unsigned long flags;
 
+    spin_lock_irqsave(&lp->lock, flags);
+
     if (netif_msg_tx_queued(lp)) {
 	printk(KERN_DEBUG "%s: pcnet32_start_xmit() called, csr0 %4.4x.\n",
 	       dev->name, lp->a.read_csr(ioaddr, 0));
     }
 
-    spin_lock_irqsave(&lp->lock, flags);
-
     /* Default status -- will not enable Successful-TxDone
      * interrupt when that option is available to us.
      */
     status = 0x8300;
-    entry = (lp->cur_tx - lp->dirty_tx) & TX_RING_MOD_MASK;
-    if ((lp->ltint) &&
-	((entry == TX_RING_SIZE/3) ||
-	 (entry == (TX_RING_SIZE*2)/3) ||
-	 (entry >= TX_RING_SIZE-2)))
-    {
-	/* Enable Successful-TxDone interrupt if we have
-	 * 1/3, 2/3 or nearly all of, our ring buffer Tx'd
-	 * but not yet cleaned up.  Thus, most of the time,
-	 * we will not enable Successful-TxDone interrupts.
-	 */
-	status = 0x9300;
-    }
-  
+
     /* Fill in a Tx ring entry */
-  
+
     /* Mask to ring buffer boundary. */
     entry = lp->cur_tx & TX_RING_MOD_MASK;
-  
+
     /* Caution: the write order is important here, set the status
-       with the "ownership" bits last. */
+     * with the "ownership" bits last. */
 
     lp->tx_ring[entry].length = le16_to_cpu(-skb->len);
 
     lp->tx_ring[entry].misc = 0x00000000;
 
     lp->tx_skbuff[entry] = skb;
-    lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE);
+    lp->tx_dma_addr[entry] = pci_map_single(lp->pci_dev, skb->data, skb->len,
+	    PCI_DMA_TODEVICE);
     lp->tx_ring[entry].base = (u32)le32_to_cpu(lp->tx_dma_addr[entry]);
     wmb(); /* Make sure owner changes after all others are visible */
     lp->tx_ring[entry].status = le16_to_cpu(status);
@@ -1469,16 +1722,17 @@ pcnet32_interrupt(int irq, void *dev_id,
     int must_restart;
 
     if (!dev) {
-	printk (KERN_DEBUG "%s(): irq %d for unknown device\n",
+	if (pcnet32_debug & NETIF_MSG_INTR)
+	    printk (KERN_DEBUG "%s(): irq %d for unknown device\n",
 		__FUNCTION__, irq);
 	return;
     }
 
     ioaddr = dev->base_addr;
     lp = dev->priv;
-    
+
     spin_lock(&lp->lock);
-    
+
     rap = lp->a.read_rap(ioaddr);
     while ((csr0 = lp->a.read_csr (ioaddr, 0)) & 0x8600 && --boguscnt >= 0) {
 	if (csr0 == 0xffff) {
@@ -1503,7 +1757,7 @@ pcnet32_interrupt(int irq, void *dev_id,
 	    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);
-			
+
 		if (status < 0)
 		    break;		/* It still hasn't been Txed */
 
@@ -1513,6 +1767,9 @@ pcnet32_interrupt(int irq, void *dev_id,
 		    /* There was an major error, log it. */
 		    int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
 		    lp->stats.tx_errors++;
+		    if (netif_msg_tx_err(lp))
+			printk(KERN_ERR "%s: Tx error status=%04x err_status=%08x\n",
+				dev->name, status, err_status);
 		    if (err_status & 0x04000000) lp->stats.tx_aborted_errors++;
 		    if (err_status & 0x08000000) lp->stats.tx_carrier_errors++;
 		    if (err_status & 0x10000000) lp->stats.tx_window_errors++;
@@ -1521,8 +1778,9 @@ pcnet32_interrupt(int irq, void *dev_id,
 			lp->stats.tx_fifo_errors++;
 			/* Ackk!  On FIFO errors the Tx unit is turned off! */
 			/* Remove this verbosity later! */
-			printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n",
-			       dev->name, csr0);
+			if (netif_msg_tx_err(lp))
+			    printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n",
+				    dev->name, csr0);
 			must_restart = 1;
 		    }
 #else
@@ -1531,8 +1789,9 @@ pcnet32_interrupt(int irq, void *dev_id,
 			if (! lp->dxsuflo) {  /* If controller doesn't recover ... */
 			    /* Ackk!  On FIFO errors the Tx unit is turned off! */
 			    /* Remove this verbosity later! */
-			    printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n",
-				   dev->name, csr0);
+			    if (netif_msg_tx_err(lp))
+				printk(KERN_ERR "%s: Tx FIFO error! CSR0=%4.4x\n",
+					dev->name, csr0);
 			    must_restart = 1;
 			}
 		    }
@@ -1545,19 +1804,20 @@ pcnet32_interrupt(int irq, void *dev_id,
 
 		/* We must free the original skb */
 		if (lp->tx_skbuff[entry]) {
-                    pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[entry],
+		    pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[entry],
 			lp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
 		    dev_kfree_skb_irq(lp->tx_skbuff[entry]);
 		    lp->tx_skbuff[entry] = 0;
-                    lp->tx_dma_addr[entry] = 0;
+		    lp->tx_dma_addr[entry] = 0;
 		}
 		dirty_tx++;
 	    }
 
 	    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);
+	    if (delta > TX_RING_SIZE) {
+		if (netif_msg_drv(lp))
+		    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;
 	    }
@@ -1578,18 +1838,20 @@ pcnet32_interrupt(int irq, void *dev_id,
 	    /*
 	     * this happens when our receive ring is full. This shouldn't
 	     * be a problem as we will see normal rx interrupts for the frames
-	     * in the receive ring. But there are some PCI chipsets (I can reproduce
-	     * this on SP3G with Intel saturn chipset) which have sometimes problems
-	     * and will fill up the receive ring with error descriptors. In this
-	     * situation we don't get a rx interrupt, but a missed frame interrupt sooner
-	     * or later. So we try to clean up our receive ring here.
+	     * in the receive ring. But there are some PCI chipsets (I can
+	     * reproduce this on SP3G with Intel saturn chipset) which have
+	     * sometimes problems and will fill up the receive ring with
+	     * error descriptors. In this situation we don't get a rx
+	     * interrupt, but a missed frame interrupt sooner or later.
+	     * So we try to clean up our receive ring here.
 	     */
 	    pcnet32_rx(dev);
 	    lp->stats.rx_errors++; /* Missed a Rx frame. */
 	}
 	if (csr0 & 0x0800) {
-	    printk(KERN_ERR "%s: Bus master arbitration failure, status %4.4x.\n",
-		   dev->name, csr0);
+	    if (netif_msg_drv(lp))
+		printk(KERN_ERR "%s: Bus master arbitration failure, status %4.4x.\n",
+			dev->name, csr0);
 	    /* unlike for the lance, there is no restart needed */
 	}
 
@@ -1597,16 +1859,17 @@ pcnet32_interrupt(int irq, void *dev_id,
 	    /* stop the chip to clear the error condition, then restart */
 	    lp->a.write_csr (ioaddr, 0, 0x0004);
 	    pcnet32_restart(dev, 0x0002);
+	    netif_wake_queue(dev);
 	}
     }
 
     /* Clear any other interrupt, and set interrupt enable. */
     lp->a.write_csr (ioaddr, 0, 0x7940);
     lp->a.write_rap (ioaddr,rap);
-    
+
     if (netif_msg_intr(lp))
 	printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n",
-	       dev->name, lp->a.read_csr (ioaddr, 0));
+		dev->name, lp->a.read_csr (ioaddr, 0));
 
     spin_unlock(&lp->lock);
 }
@@ -1616,13 +1879,14 @@ pcnet32_rx(struct net_device *dev)
 {
     struct pcnet32_private *lp = dev->priv;
     int entry = lp->cur_rx & RX_RING_MOD_MASK;
+    int boguscnt = RX_RING_SIZE / 2;
 
     /* If we own the next entry, it's a new packet. Send it up. */
     while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) {
 	int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8;
 
 	if (status != 0x03) {			/* There was an error. */
-	    /* 
+	    /*
 	     * There is a tricky error noted by John Murphy,
 	     * <murf@perftech.com> to Russ Nelson: Even with full-sized
 	     * buffers it's possible for a jabber packet to use two
@@ -1639,17 +1903,18 @@ pcnet32_rx(struct net_device *dev)
 	    /* Malloc up new buffer, compatible with net-2e. */
 	    short pkt_len = (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff)-4;
 	    struct sk_buff *skb;
-			
-	    if(pkt_len < 60) {
-		printk(KERN_ERR "%s: Runt packet!\n",dev->name);
+
+	    if (pkt_len < 60) {
+		if (netif_msg_rx_err(lp))
+		    printk(KERN_ERR "%s: Runt packet!\n", dev->name);
 		lp->stats.rx_errors++;
 	    } else {
 		int rx_in_place = 0;
 
 		if (pkt_len > rx_copybreak) {
 		    struct sk_buff *newskb;
-				
-		    if ((newskb = dev_alloc_skb (PKT_BUF_SZ))) {
+
+		    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],
@@ -1657,27 +1922,31 @@ pcnet32_rx(struct net_device *dev)
 			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,
-					PKT_BUF_SZ-2, PCI_DMA_FROMDEVICE);
+			lp->rx_dma_addr[entry] =
+			    pci_map_single(lp->pci_dev, newskb->tail,
+				    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
 			skb = NULL;
 		} else {
 		    skb = dev_alloc_skb(pkt_len+2);
-                }
-			    
+		}
+
 		if (skb == NULL) {
-                    int i;
-		    printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n", dev->name);
+		    int i;
+		    if (netif_msg_drv(lp))
+			printk(KERN_ERR "%s: Memory squeeze, deferring packet.\n",
+				dev->name);
 		    for (i = 0; i < RX_RING_SIZE; i++)
-			if ((short)le16_to_cpu(lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].status) < 0)
+			if ((short)le16_to_cpu(lp->rx_ring[(entry+i)
+				    & RX_RING_MOD_MASK].status) < 0)
 			    break;
 
 		    if (i > RX_RING_SIZE -2) {
 			lp->stats.rx_dropped++;
 			lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
+			wmb();	/* Make sure adapter sees owner change */
 			lp->cur_rx++;
 		    }
 		    break;
@@ -1691,8 +1960,8 @@ pcnet32_rx(struct net_device *dev)
 		                        PKT_BUF_SZ-2,
 		                        PCI_DMA_FROMDEVICE);
 		    eth_copy_and_sum(skb,
-				     (unsigned char *)(lp->rx_skbuff[entry]->tail),
-				     pkt_len,0);
+			    (unsigned char *)(lp->rx_skbuff[entry]->tail),
+			    pkt_len,0);
 		}
 		lp->stats.rx_bytes += skb->len;
 		skb->protocol=eth_type_trans(skb,dev);
@@ -1709,6 +1978,7 @@ pcnet32_rx(struct net_device *dev)
 	wmb(); /* Make sure owner changes after all others are visible */
 	lp->rx_ring[entry].status |= le16_to_cpu(0x8000);
 	entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+	if (--boguscnt <= 0) break;	/* don't stay in loop forever */
     }
 
     return 0;
@@ -1720,9 +1990,14 @@ pcnet32_close(struct net_device *dev)
     unsigned long ioaddr = dev->base_addr;
     struct pcnet32_private *lp = dev->priv;
     int i;
+    unsigned long flags;
+
+    del_timer_sync(&lp->watchdog_timer);
 
     netif_stop_queue(dev);
 
+    spin_lock_irqsave(&lp->lock, flags);
+
     lp->stats.rx_missed_errors = lp->a.read_csr (ioaddr, 112);
 
     if (netif_msg_ifdown(lp))
@@ -1733,35 +2008,43 @@ pcnet32_close(struct net_device *dev)
     lp->a.write_csr (ioaddr, 0, 0x0004);
 
     /*
-     * Switch back to 16bit mode to avoid problems with dumb 
+     * Switch back to 16bit mode to avoid problems with dumb
      * DOS packet driver after a warm reboot
      */
     lp->a.write_bcr (ioaddr, 20, 4);
 
+    spin_unlock_irqrestore(&lp->lock, flags);
+
     free_irq(dev->irq, dev);
-    
+
+    spin_lock_irqsave(&lp->lock, flags);
+
     /* free all allocated skbuffs */
     for (i = 0; i < RX_RING_SIZE; i++) {
-	lp->rx_ring[i].status = 0;			    
+	lp->rx_ring[i].status = 0;
+	wmb();		/* Make sure adapter sees owner change */
 	if (lp->rx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->rx_dma_addr[i], PKT_BUF_SZ-2,
+	    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;
-        lp->rx_dma_addr[i] = 0;
+	lp->rx_dma_addr[i] = 0;
     }
-    
+
     for (i = 0; i < TX_RING_SIZE; i++) {
+	lp->tx_ring[i].status = 0;	/* CPU owns buffer */
+	wmb();		/* Make sure adapter sees owner change */
 	if (lp->tx_skbuff[i]) {
-            pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i], lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
+	    pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[i],
+		    lp->tx_skbuff[i]->len, PCI_DMA_TODEVICE);
 	    dev_kfree_skb(lp->tx_skbuff[i]);
-        }
+	}
 	lp->tx_skbuff[i] = NULL;
-        lp->tx_dma_addr[i] = 0;
+	lp->tx_dma_addr[i] = 0;
     }
-    
-    MOD_DEC_USE_COUNT;
+
+    spin_unlock_irqrestore(&lp->lock, flags);
 
     return 0;
 }
@@ -1793,9 +2076,9 @@ static void pcnet32_load_multicast (stru
     char *addrs;
     int i;
     u32 crc;
-	
+
     /* set all multicast bits */
-    if (dev->flags & IFF_ALLMULTI){ 
+    if (dev->flags & IFF_ALLMULTI) {
 	ib->filter[0] = 0xffffffff;
 	ib->filter[1] = 0xffffffff;
 	return;
@@ -1805,19 +2088,18 @@ static void pcnet32_load_multicast (stru
     ib->filter[1] = 0;
 
     /* Add addresses */
-    for (i = 0; i < dev->mc_count; i++){
+    for (i = 0; i < dev->mc_count; i++) {
 	addrs = dmi->dmi_addr;
 	dmi   = dmi->next;
-	
+
 	/* multicast address? */
 	if (!(*addrs & 1))
 	    continue;
-	
+
 	crc = ether_crc_le(6, addrs);
 	crc = crc >> 26;
 	mcast_table [crc >> 4] = le16_to_cpu(
-		le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf))
-	);
+		le16_to_cpu(mcast_table [crc >> 4]) | (1 << (crc & 0xf)));
     }
     return;
 }
@@ -1829,62 +2111,58 @@ static void pcnet32_load_multicast (stru
 static void pcnet32_set_multicast_list(struct net_device *dev)
 {
     unsigned long ioaddr = dev->base_addr, flags;
-    struct pcnet32_private *lp = dev->priv;	 
+    struct pcnet32_private *lp = dev->priv;
 
     spin_lock_irqsave(&lp->lock, flags);
     if (dev->flags&IFF_PROMISC) {
 	/* Log any net taps. */
-	printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
+	if (netif_msg_hw(lp))
+	    printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 	lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7);
     } else {
 	lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
 	pcnet32_load_multicast (dev);
     }
-    
-    lp->a.write_csr (ioaddr, 0, 0x0004); /* Temporarily stop the lance. */
 
+    lp->a.write_csr (ioaddr, 0, 0x0004); /* Temporarily stop the lance. */
     pcnet32_restart(dev, 0x0042); /*  Resume normal operation */
+    netif_wake_queue(dev);
+
     spin_unlock_irqrestore(&lp->lock, flags);
 }
 
+/* This routine assumes that the lp->lock is held */
 static int mdio_read(struct net_device *dev, int phy_id, int reg_num)
 {
-	struct pcnet32_private *lp = dev->priv;
-	unsigned long ioaddr = dev->base_addr;
-	u16 val_out;
-	int phyaddr;
-
-	if (!lp->mii)
-		return 0;
-		
-	phyaddr = lp->a.read_bcr(ioaddr, 33);
-
-	lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
-	val_out = lp->a.read_bcr(ioaddr, 34);
-	lp->a.write_bcr(ioaddr, 33, phyaddr);
-	
-	return val_out;
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long ioaddr = dev->base_addr;
+    u16 val_out;
+
+    if (!lp->mii)
+	return 0;
+
+    lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+    val_out = lp->a.read_bcr(ioaddr, 34);
+
+    return val_out;
 }
 
+/* This routine assumes that the lp->lock is held */
 static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
 {
-	struct pcnet32_private *lp = dev->priv;
-	unsigned long ioaddr = dev->base_addr;
-	int phyaddr;
+    struct pcnet32_private *lp = dev->priv;
+    unsigned long ioaddr = dev->base_addr;
+
+    if (!lp->mii)
+	return;
 
-	if (!lp->mii)
-		return;
-		
-	phyaddr = lp->a.read_bcr(ioaddr, 33);
-
-	lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
-	lp->a.write_bcr(ioaddr, 34, val);
-	lp->a.write_bcr(ioaddr, 33, phyaddr);
+    lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+    lp->a.write_bcr(ioaddr, 34, val);
 }
 
 static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    struct pcnet32_private *lp = dev->priv;	 
+    struct pcnet32_private *lp = dev->priv;
     struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
     int rc;
     unsigned long flags;
@@ -1901,6 +2179,21 @@ static int pcnet32_ioctl(struct net_devi
     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) {
+	spin_lock_irqsave(&lp->lock, flags);
+	mii_check_media (&lp->mii_if, netif_msg_link(lp), 0);
+	spin_unlock_irqrestore(&lp->lock, flags);
+    }
+
+    mod_timer (&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT);
+}
+
 static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
 {
     struct net_device *dev = pci_get_drvdata(pdev);
@@ -1926,15 +2219,15 @@ static struct pci_driver pcnet32_driver 
 MODULE_PARM(debug, "i");
 MODULE_PARM_DESC(debug, DRV_NAME " debug level");
 MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt");  
+MODULE_PARM_DESC(max_interrupt_work, DRV_NAME " maximum events handled per interrupt");
 MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames"); 
+MODULE_PARM_DESC(rx_copybreak, DRV_NAME " copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM(tx_start_pt, "i");
-MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)"); 
+MODULE_PARM_DESC(tx_start_pt, DRV_NAME " transmit start point (0-3)");
 MODULE_PARM(pcnet32vlb, "i");
-MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)"); 
+MODULE_PARM_DESC(pcnet32vlb, DRV_NAME " Vesa local bus (VLB) support (0/1)");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)"); 
+MODULE_PARM_DESC(options, DRV_NAME " initial option setting(s) (0-15)");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM_DESC(full_duplex, DRV_NAME " full duplex setting(s) (1)");
 
@@ -1942,6 +2235,8 @@ MODULE_AUTHOR("Thomas Bogendoerfer");
 MODULE_DESCRIPTION("Driver for PCnet32 and PCnetPCI based ethercards");
 MODULE_LICENSE("GPL");
 
+#define PCNET32_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+
 /* An additional parameter that may be passed in... */
 static int debug = -1;
 static int tx_start_pt = -1;
@@ -1951,8 +2246,7 @@ static int __init pcnet32_init_module(vo
 {
     printk(KERN_INFO "%s", version);
 
-    if (debug >= 0 && debug < (sizeof(int) - 1))
-	pcnet32_debug = 1 << debug;
+    pcnet32_debug = netif_msg_init(debug, PCNET32_MSG_DEFAULT);
 
     if ((tx_start_pt >= 0) && (tx_start_pt <= 3))
 	tx_start = tx_start_pt;
@@ -1965,9 +2259,9 @@ static int __init pcnet32_init_module(vo
     if (pcnet32vlb)
 	pcnet32_probe_vlbus();
 
-    if (cards_found)
+    if (cards_found && (pcnet32_debug & NETIF_MSG_PROBE))
 	printk(KERN_INFO PFX "%d cards_found.\n", cards_found);
-    
+
     return (pcnet32_have_pci + cards_found) ? 0 : -ENODEV;
 }
 
@@ -1975,7 +2269,6 @@ static void __exit pcnet32_cleanup_modul
 {
     struct net_device *next_dev;
 
-    /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
     while (pcnet32_dev) {
 	struct pcnet32_private *lp = pcnet32_dev->priv;
 	next_dev = lp->next;
@@ -1985,6 +2278,7 @@ static void __exit pcnet32_cleanup_modul
 	free_netdev(pcnet32_dev);
 	pcnet32_dev = next_dev;
     }
+
     if (pcnet32_have_pci)
 	pci_unregister_driver(&pcnet32_driver);
 }
@@ -1994,7 +2288,6 @@ module_exit(pcnet32_cleanup_module);
 
 /*
  * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c pcnet32.c"
  *  c-indent-level: 4
  *  tab-width: 8
  * End:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/r8169.c linux-2.4.27-rc4/drivers/net/r8169.c
--- linux-2.4.26/drivers/net/r8169.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/r8169.c	2004-07-30 16:26:26.000000000 +0000
@@ -33,6 +33,9 @@ VERSION 1.2	<2002/11/30>
 	- Copy mc_filter setup code from 8139cp
 	  (includes an optimization, and avoids set_bit use)
 
+		<2003/11/30>
+
+	- Add new rtl8169_{suspend/resume}() support
 */
 
 #include <linux/module.h>
@@ -40,11 +43,15 @@ VERSION 1.2	<2002/11/30>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
+#include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
 
+#define DMA_64BIT_MASK 0xffffffffffffffffULL
+#define DMA_32BIT_MASK 0x00000000ffffffffULL
+
 #define RTL8169_VERSION "1.2"
 #define MODULENAME "r8169"
 #define RTL8169_DRIVER_NAME   MODULENAME " Gigabit Ethernet driver " RTL8169_VERSION
@@ -56,9 +63,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 +98,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,24 +113,52 @@ 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[] __devinitdata = {
+static struct pci_device_id rtl8169_pci_tbl[] = {
 	{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0,},
 };
 
 MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
 
+static int rx_copybreak = 200;
+
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
 	MAR0 = 8,		/* Multicast filter. */
-	TxDescStartAddr = 0x20,
-	TxHDescStartAddr = 0x28,
+	TxDescStartAddrLow = 0x20,
+	TxDescStartAddrHigh = 0x24,
+	TxHDescStartAddrLow = 0x28,
+	TxHDescStartAddrHigh = 0x2c,
 	FLASH = 0x30,
 	ERSR = 0x36,
 	ChipCmd = 0x37,
@@ -143,7 +183,8 @@ enum RTL8169_registers {
 	PHYstatus = 0x6C,
 	RxMaxSize = 0xDA,
 	CPlusCmd = 0xE0,
-	RxDescStartAddr = 0xE4,
+	RxDescAddrLow = 0xE4,
+	RxDescAddrHigh = 0xE8,
 	EarlyTxThres = 0xEC,
 	FuncEvent = 0xF0,
 	FuncEventMask = 0xF4,
@@ -195,7 +236,13 @@ enum RTL8169_register_content {
 
 	/*TxConfigBits */
 	TxInterFrameGapShift = 24,
-	TxDMAShift = 8,		/* DMA burst value (0-7) is shift this many bits */
+	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */
+
+	/* CPlusCmd p.31 */
+	RxVlan		= (1 << 6),
+	RxChkSum	= (1 << 5),
+	PCIDAC		= (1 << 4),
+	PCIMulRW	= (1 << 3),
 
 	/*rtl8169_PHYstatus */
 	TBI_Enable = 0x80,
@@ -242,14 +289,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,18 +296,18 @@ enum _DescStatusBit {
 	LSbit = 0x10000000,
 };
 
+#define RsvdMask	0x3fffc000
+
 struct TxDesc {
 	u32 status;
 	u32 vlan_tag;
-	u32 buf_addr;
-	u32 buf_Haddr;
+	u64 addr;
 };
 
 struct RxDesc {
 	u32 status;
 	u32 vlan_tag;
-	u32 buf_addr;
-	u32 buf_Haddr;
+	u64 addr;
 };
 
 struct rtl8169_private {
@@ -277,28 +316,34 @@ 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;
+	u16 cp_cmd;
 };
 
 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 void rtl8169_interrupt(int irq, void *dev_instance,
+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,13 +351,16 @@ 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);
 
-void
-mdio_write(void *ioaddr, int RegAddr, int value)
+#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
+
+static void mdio_write(void *ioaddr, int RegAddr, int value)
 {
 	int i;
 
@@ -329,8 +377,7 @@ mdio_write(void *ioaddr, int RegAddr, in
 	}
 }
 
-int
-mdio_read(void *ioaddr, int RegAddr)
+static int mdio_read(void *ioaddr, int RegAddr)
 {
 	int i, value = -1;
 
@@ -342,13 +389,272 @@ 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_get_drvinfo(struct net_device *dev,
+				struct ethtool_drvinfo *info)
+{
+	struct rtl8169_private *tp = dev->priv;
+
+	strcpy(info->driver, RTL8169_DRIVER_NAME);
+	strcpy(info->version, RTL8169_VERSION );
+	strcpy(info->bus_info, pci_name(tp->pci_dev));
+}
+
+static struct ethtool_ops rtl8169_ethtool_ops = {
+	.get_drvinfo		= rtl8169_get_drvinfo,
+};
+
+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, jiffies + 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 +662,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);
@@ -374,12 +680,27 @@ rtl8169_init_board(struct pci_dev *pdev,
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	tp = dev->priv;
 
 	// 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);
@@ -401,8 +722,24 @@ 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;
+	}
+
+	tp->cp_cmd = PCIMulRW | RxChkSum;
+
+	if ((sizeof(dma_addr_t) > 32) &&
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+		tp->cp_cmd |= PCIDAC;
+	else {
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (rc < 0) {
+			printk(KERN_ERR PFX "DMA configuration failed.\n");
+			goto err_out_free_res;
+		}
+	}
+
 
 	// enable PCI bus-mastering
 	pci_set_master(pdev);
@@ -419,30 +756,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",
-	       pdev->slot_name);
-	printk(KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n",
-	       pdev->slot_name, (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;
@@ -454,7 +793,7 @@ err_out_disable:
 	pci_disable_device(pdev);
 
 err_out:
-	kfree(dev);
+	free_netdev(dev);
 	return rc;
 }
 
@@ -495,10 +834,11 @@ rtl8169_init_one(struct pci_dev *pdev, c
 	dev->open = rtl8169_open;
 	dev->hard_start_xmit = rtl8169_start_xmit;
 	dev->get_stats = rtl8169_get_stats;
+	dev->ethtool_ops = &rtl8169_ethtool_ops;
 	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;
@@ -514,7 +854,7 @@ rtl8169_init_one(struct pci_dev *pdev, c
 		iounmap(ioaddr);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
-		kfree(dev);
+		free_netdev(dev);
 		return rc;
 	}
 
@@ -527,12 +867,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);
@@ -545,23 +902,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:
@@ -575,9 +932,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,
@@ -641,65 +996,101 @@ rtl8169_remove_one(struct pci_dev *pdev)
 	iounmap(tp->mmio_addr);
 	pci_release_regions(pdev);
 
-	// poison memory before freeing 
-	memset(dev, 0xBC,
-	       sizeof (struct net_device) + sizeof (struct rtl8169_private));
-
 	pci_disable_device(pdev);
-	kfree(dev);
+	free_netdev(dev);
 	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
@@ -736,11 +1127,21 @@ rtl8169_hw_start(struct net_device *dev)
 	RTL_W32(TxConfig,
 		(TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<
 						TxInterFrameGapShift));
+	tp->cp_cmd |= RTL_R16(CPlusCmd);
+	RTL_W16(CPlusCmd, tp->cp_cmd);
+
+	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");
+		tp->cp_cmd |= (1 << 14) | PCIMulRW;
+		RTL_W16(CPlusCmd, tp->cp_cmd);
+	}
 
 	tp->cur_rx = 0;
 
-	RTL_W32(TxDescStartAddr, virt_to_bus(tp->TxDescArray));
-	RTL_W32(RxDescStartAddr, virt_to_bus(tp->RxDescArray));
+	RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
+	RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
+	RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
+	RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
 	RTL_W8(Cfg9346, Cfg9346_Lock);
 	udelay(10);
 
@@ -758,31 +1159,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->addr = 0x0badbadbadbadbad;
+	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, le64_to_cpu(desc->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->addr = cpu_to_le64(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, le64_to_cpu(desc->addr),
+			 len < ETH_ZLEN ? ETH_ZLEN : len, PCI_DMA_TODEVICE);
+	desc->addr = 0x00;
+	*sk_buff = NULL;
 }
 
 static void
@@ -792,9 +1293,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++;
 		}
 	}
@@ -832,41 +1336,51 @@ 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].addr = cpu_to_le64(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
@@ -884,18 +1398,23 @@ rtl8169_tx_interrupt(struct net_device *
 
 	while (tx_left > 0) {
 		int entry = dirty_tx % NUM_TX_DESC;
+		struct sk_buff *skb = tp->Tx_skbuff[entry];
+		u32 status;
 
-		if ((tp->TxDescArray[entry].status & OWNbit) == 0) {
-			struct sk_buff *skb = tp->Tx_skbuff[entry];
+		rmb();
+		status = le32_to_cpu(tp->TxDescArray[entry].status);
+		if (status & OWNbit)
+			break;
 
-			tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
+		/* FIXME: is it really accurate for TxErr ? */
+		tp->stats.tx_bytes += skb->len >= ETH_ZLEN ?
 					      skb->len : ETH_ZLEN;
-			tp->stats.tx_packets++;
-			dev_kfree_skb_irq(skb);
-			tp->Tx_skbuff[entry] = NULL;
-			dirty_tx++;
-			tx_left--;
-		}
+		tp->stats.tx_packets++;
+		rtl8169_unmap_tx_skb(tp->pci_dev, tp->Tx_skbuff + entry,
+				     tp->TxDescArray + entry);
+		dev_kfree_skb_irq(skb);
+		dirty_tx++;
+		tx_left--;
 	}
 
 	if (tp->dirty_tx != dirty_tx) {
@@ -905,74 +1424,108 @@ 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;
 
-		if (tp->RxDescArray[cur_rx].status & RxRES) {
+		rmb();
+		status = le32_to_cpu(tp->RxDescArray[entry].status);
+
+		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, le64_to_cpu(desc->addr),
+					    RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+			if (rtl8169_try_rx_copy(&skb, pkt_size, desc, dev)) {
+				pci_unmap_single(tp->pci_dev, le64_to_cpu(desc->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. */
-static void
+static irqreturn_t
 rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
@@ -980,14 +1533,16 @@ rtl8169_interrupt(int irq, void *dev_ins
 	int boguscnt = max_interrupt_work;
 	void *ioaddr = tp->mmio_addr;
 	int status = 0;
+	int handled = 0;
 
 	do {
 		status = RTL_R16(IntrStatus);
 
-		/* h/w no longer present (hotplug?) or major error, bail */
-		if (status == 0xFFFF)
+		/* hotplug/major error/no more work/shared irq */
+		if ((status == 0xFFFF) || !status)
 			break;
 
+		handled = 1;
 /*
 		if (status & RxUnderrun)
 			link_changed = RTL_R16 (CSCR) & CSCR_LinkChangeBit;
@@ -995,9 +1550,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 
@@ -1020,17 +1573,20 @@ rtl8169_interrupt(int irq, void *dev_ins
 		/* Clear all interrupt sources. */
 		RTL_W16(IntrStatus, 0xffff);
 	}
+	return IRQ_RETVAL(handled);
 }
 
 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. */
@@ -1049,16 +1605,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;
 }
@@ -1112,11 +1667,25 @@ rtl8169_set_rx_mode(struct net_device *d
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
-struct net_device_stats *
-rtl8169_get_stats(struct net_device *dev)
+/**
+ *  rtl8169_get_stats - Get rtl8169 read/write statistics
+ *  @dev: The Ethernet Device to get statistics for
+ *
+ *  Get TX/RX statistics for rtl8169
+ */
+static 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;
 }
 
@@ -1125,8 +1694,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 -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/sis900.c linux-2.4.27-rc4/drivers/net/sis900.c
--- linux-2.4.26/drivers/net/sis900.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/sis900.c	2004-07-30 16:27:54.000000000 +0000
@@ -18,10 +18,11 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
-   Rev 1.08.05 Jun. 6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary 
+   Rev 1.08.05 Jun.  6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
-   Rev 1.08.03 Feb. 1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
+   Rev 1.08.03 Feb.  1 2002 Matt Domsch <Matt_Domsch@dell.com> update to use library crc32 function
    Rev 1.08.02 Nov. 30 2001 Hui-Fen Hsu workaround for EDB & bug fix for dhcp problem
    Rev 1.08.01 Aug. 25 2001 Hui-Fen Hsu update for 630ET & workaround for ICS1893 PHY
    Rev 1.08.00 Jun. 11 2001 Hui-Fen Hsu workaround for RTL8201 PHY and some bug fix
@@ -47,9 +48,7 @@
 */
 
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
@@ -74,7 +73,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.06 9/24/2002"
+#define SIS900_DRV_VERSION "v1.08.07 11/02/2003"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -171,6 +170,7 @@ struct sis900_private {
 
 	unsigned int tx_full;			/* The Tx queue is full.    */
 	u8 host_bridge_rev;
+	u32 pci_state[16];
 };
 
 MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
@@ -260,9 +260,13 @@ static int __devinit sis630e_get_mac_add
 	u8 reg;
 	int i;
 
-	if ((isa_bridge = pci_find_device(0x1039, 0x0008, isa_bridge)) == NULL) {
-		printk("%s: Can not find ISA bridge\n", net_dev->name);
-		return 0;
+	isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
+	if (!isa_bridge) {
+		isa_bridge = pci_find_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
+		if (!isa_bridge) {
+			printk("%s: Can not find ISA bridge\n", net_dev->name);
+			return 0;
+		}
 	}
 	pci_read_config_byte(isa_bridge, 0x48, &reg);
 	pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
@@ -307,7 +311,7 @@ static int __devinit sis635_get_mac_addr
 		*( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
 	}
 
-	/* enable packet filitering */
+	/* enable packet filtering */
 	outl(rfcrSave | RFEN, rfcr + ioaddr);
 
 	return 1;
@@ -402,6 +406,7 @@ static int __devinit sis900_probe (struc
 	if (!net_dev)
 		return -ENOMEM;
 	SET_MODULE_OWNER(net_dev);
+	SET_NETDEV_DEV(net_dev, &pci_dev->dev);
 
 	/* We do a request_region() to register /proc/ioports info. */
 	ioaddr = pci_resource_start(pci_dev, 0);	
@@ -503,7 +508,7 @@ static int __devinit sis900_probe (struc
  	pci_set_drvdata(pci_dev, NULL);
 	pci_release_regions(pci_dev);
  err_out:
-	kfree(net_dev);
+	free_netdev(net_dev);
 	return ret;
 }
 
@@ -995,7 +1000,7 @@ sis900_init_rxfilter (struct net_device 
 		}
 	}
 
-	/* enable packet filitering */
+	/* enable packet filtering */
 	outl(rfcrSave | RFEN, rfcr + ioaddr);
 }
 
@@ -1467,7 +1472,7 @@ static void sis900_tx_timeout(struct net
  *	@net_dev: the net device to transmit with
  *
  *	Set the transmit buffer descriptor, 
- *	and write TxENA to enable transimt state machine.
+ *	and write TxENA to enable transmit state machine.
  *	tell upper layer if the buffer is full
  */
 
@@ -2183,16 +2188,78 @@ static void __devexit sis900_remove(stru
 	pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
 		sis_priv->tx_ring_dma);
 	unregister_netdev(net_dev);
-	kfree(net_dev);
+	free_netdev(net_dev);
 	pci_release_regions(pci_dev);
 	pci_set_drvdata(pci_dev, NULL);
 }
 
+#ifdef CONFIG_PM
+
+static int sis900_suspend(struct pci_dev *pci_dev, u32 state)
+{
+	struct net_device *net_dev = pci_get_drvdata(pci_dev);
+	struct sis900_private *sis_priv = net_dev->priv;
+	long ioaddr = net_dev->base_addr;
+
+	if(!netif_running(net_dev))
+		return 0;
+
+	netif_stop_queue(net_dev);
+	netif_device_detach(net_dev);
+
+	/* Stop the chip's Tx and Rx Status Machine */
+	outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
+
+	pci_set_power_state(pci_dev, 3);
+	pci_save_state(pci_dev, sis_priv->pci_state);
+
+	return 0;
+}
+
+static int sis900_resume(struct pci_dev *pci_dev)
+{
+	struct net_device *net_dev = pci_get_drvdata(pci_dev);
+	struct sis900_private *sis_priv = net_dev->priv;
+	long ioaddr = net_dev->base_addr;
+
+	if(!netif_running(net_dev))
+		return 0;
+	pci_restore_state(pci_dev, sis_priv->pci_state);
+	pci_set_power_state(pci_dev, 0);
+
+	sis900_init_rxfilter(net_dev);
+
+	sis900_init_tx_ring(net_dev);
+	sis900_init_rx_ring(net_dev);
+
+	set_rx_mode(net_dev);
+
+	netif_device_attach(net_dev);
+	netif_start_queue(net_dev);
+
+	/* Workaround for EDB */
+	sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+
+	/* Enable all known interrupts by setting the interrupt mask. */
+	outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
+	outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
+	outl(IE, ioaddr + ier);
+
+	sis900_check_mode(net_dev, sis_priv->mii);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
 static struct pci_driver sis900_pci_driver = {
 	.name		= SIS900_MODULE_NAME,
 	.id_table	= sis900_pci_tbl,
 	.probe		= sis900_probe,
 	.remove		= __devexit_p(sis900_remove),
+#ifdef CONFIG_PM
+	.suspend	= sis900_suspend,
+	.resume		= sis900_resume,
+#endif /* CONFIG_PM */
 };
 
 static int __init sis900_init_module(void)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/sis900.h linux-2.4.27-rc4/drivers/net/sis900.h
--- linux-2.4.26/drivers/net/sis900.h	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/sis900.h	2004-07-30 16:26:03.000000000 +0000
@@ -77,7 +77,7 @@ enum sis900_interrupt_enable_reigster_bi
 	IE = 0x00000001
 };
 
-/* maximum dma burst fro transmission and receive*/
+/* maximum dma burst for transmission and receive */
 #define MAX_DMA_RANGE	7	/* actually 0 means MAXIMUM !! */
 #define TxMXDMA_shift   	20
 #define RxMXDMA_shift    20
@@ -86,7 +86,7 @@ enum sis900_tx_rx_dma{
 	DMA_BURST_512 = 0,	DMA_BURST_64 = 5
 };
 
-/* transmit FIFO threshholds */
+/* transmit FIFO thresholds */
 #define TX_FILL_THRESH   16	/* 1/4 FIFO size */
 #define TxFILLT_shift   	8
 #define TxDRNT_shift    	0
@@ -140,7 +140,7 @@ enum sis96x_eeprom_command {
 	EEREQ = 0x00000400, EEDONE = 0x00000200, EEGNT = 0x00000100
 };
 
-/* Manamgement Data I/O (mdio) frame */
+/* Management Data I/O (mdio) frame */
 #define MIIread         0x6000
 #define MIIwrite        0x5002
 #define MIIpmdShift     7
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/tg3.c linux-2.4.27-rc4/drivers/net/tg3.c
--- linux-2.4.26/drivers/net/tg3.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/tg3.c	2004-07-30 16:27:49.000000000 +0000
@@ -1,8 +1,9 @@
 /*
  * tg3.c: Broadcom Tigon3 ethernet driver.
  *
- * Copyright (C) 2001, 2002, 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
  */
 
 #include <linux/config.h>
@@ -55,8 +56,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"2.9"
-#define DRV_MODULE_RELDATE	"March 8, 2004"
+#define DRV_MODULE_VERSION	"3.8"
+#define DRV_MODULE_RELDATE	"July 14, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -79,7 +80,8 @@
 /* hardware minimum and maximum for a single frame's data payload */
 #define TG3_MIN_MTU			60
 #define TG3_MAX_MTU(tp)	\
-	(GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 ? 9000 : 1500)
+	((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 && \
+	  GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) ? 9000 : 1500)
 
 /* These numbers seem to be hard coded in the NIC firmware somehow.
  * You can't change the ring sizes, but you can change where you place
@@ -97,7 +99,8 @@
  * replace things like '% foo' with '& (foo - 1)'.
  */
 #define TG3_RX_RCB_RING_SIZE(tp)	\
-	(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ? \
+	((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 || \
+	  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ? \
 	 512 : 1024)
 
 #define TG3_TX_RING_SIZE		512
@@ -125,6 +128,9 @@
 /* minimum number of free TX descriptors required to wake up TX process */
 #define TG3_TX_WAKEUP_THRESH		(TG3_TX_RING_SIZE / 4)
 
+/* number of ETHTOOL_GSTATS u64's */
+#define TG3_NUM_STATS		(sizeof(struct tg3_ethtool_stats)/sizeof(u64))
+
 static char version[] __devinitdata =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -171,6 +177,8 @@ static struct pci_device_id tg3_pci_tbl[
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2,
@@ -179,6 +187,20 @@ static struct pci_device_id tg3_pci_tbl[
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX,
@@ -198,6 +220,87 @@ static struct pci_device_id tg3_pci_tbl[
 
 MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);
 
+struct {
+	char string[ETH_GSTRING_LEN];
+} ethtool_stats_keys[TG3_NUM_STATS] = {
+	{ "rx_octets" },
+	{ "rx_fragments" },
+	{ "rx_ucast_packets" },
+	{ "rx_mcast_packets" },
+	{ "rx_bcast_packets" },
+	{ "rx_fcs_errors" },
+	{ "rx_align_errors" },
+	{ "rx_xon_pause_rcvd" },
+	{ "rx_xoff_pause_rcvd" },
+	{ "rx_mac_ctrl_rcvd" },
+	{ "rx_xoff_entered" },
+	{ "rx_frame_too_long_errors" },
+	{ "rx_jabbers" },
+	{ "rx_undersize_packets" },
+	{ "rx_in_length_errors" },
+	{ "rx_out_length_errors" },
+	{ "rx_64_or_less_octet_packets" },
+	{ "rx_65_to_127_octet_packets" },
+	{ "rx_128_to_255_octet_packets" },
+	{ "rx_256_to_511_octet_packets" },
+	{ "rx_512_to_1023_octet_packets" },
+	{ "rx_1024_to_1522_octet_packets" },
+	{ "rx_1523_to_2047_octet_packets" },
+	{ "rx_2048_to_4095_octet_packets" },
+	{ "rx_4096_to_8191_octet_packets" },
+	{ "rx_8192_to_9022_octet_packets" },
+
+	{ "tx_octets" },
+	{ "tx_collisions" },
+
+	{ "tx_xon_sent" },
+	{ "tx_xoff_sent" },
+	{ "tx_flow_control" },
+	{ "tx_mac_errors" },
+	{ "tx_single_collisions" },
+	{ "tx_mult_collisions" },
+	{ "tx_deferred" },
+	{ "tx_excessive_collisions" },
+	{ "tx_late_collisions" },
+	{ "tx_collide_2times" },
+	{ "tx_collide_3times" },
+	{ "tx_collide_4times" },
+	{ "tx_collide_5times" },
+	{ "tx_collide_6times" },
+	{ "tx_collide_7times" },
+	{ "tx_collide_8times" },
+	{ "tx_collide_9times" },
+	{ "tx_collide_10times" },
+	{ "tx_collide_11times" },
+	{ "tx_collide_12times" },
+	{ "tx_collide_13times" },
+	{ "tx_collide_14times" },
+	{ "tx_collide_15times" },
+	{ "tx_ucast_packets" },
+	{ "tx_mcast_packets" },
+	{ "tx_bcast_packets" },
+	{ "tx_carrier_sense_errors" },
+	{ "tx_discards" },
+	{ "tx_errors" },
+
+	{ "dma_writeq_full" },
+	{ "dma_write_prioq_full" },
+	{ "rxbds_empty" },
+	{ "rx_discards" },
+	{ "rx_errors" },
+	{ "rx_threshold_hit" },
+
+	{ "dma_readq_full" },
+	{ "dma_read_prioq_full" },
+	{ "tx_comp_queue_full" },
+
+	{ "ring_set_send_prod_index" },
+	{ "ring_status_update" },
+	{ "nic_irqs" },
+	{ "nic_avoided_irqs" },
+	{ "nic_tx_threshold_hit" }
+};
+
 static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
 {
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
@@ -339,6 +442,7 @@ static void tg3_switch_clocks(struct tg3
 	tp->pci_clock_ctrl = clock_ctrl;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750 &&
 	    (orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
 		tw32_f(TG3PCI_CLOCK_CTRL,
 		     clock_ctrl |
@@ -362,7 +466,7 @@ static int tg3_readphy(struct tg3 *tp, i
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		udelay(40);
+		udelay(80);
 	}
 
 	*val = 0xffffffff;
@@ -395,7 +499,7 @@ static int tg3_readphy(struct tg3 *tp, i
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 		tw32_f(MAC_MI_MODE, tp->mi_mode);
-		udelay(40);
+		udelay(80);
 	}
 
 	return ret;
@@ -409,7 +513,7 @@ static int tg3_writephy(struct tg3 *tp, 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 		tw32_f(MAC_MI_MODE,
 		     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
-		udelay(40);
+		udelay(80);
 	}
 
 	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
@@ -438,7 +542,7 @@ static int tg3_writephy(struct tg3 *tp, 
 
 	if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 		tw32_f(MAC_MI_MODE, tp->mi_mode);
-		udelay(40);
+		udelay(80);
 	}
 
 	return ret;
@@ -642,7 +746,14 @@ static int tg3_phy_reset_5703_4_5(struct
 	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
 	tg3_writephy(tp, 0x16, 0x0000);
 
-	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+		/* Set Extended packet length bit for jumbo frames */
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4400);
+	}
+	else {
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+	}
 
 	tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
 
@@ -656,7 +767,7 @@ static int tg3_phy_reset_5703_4_5(struct
 /* This will reset the tigon3 PHY if there is no valid
  * link unless the FORCE argument is non-zero.
  */
-static int tg3_phy_reset(struct tg3 *tp, int force)
+static int tg3_phy_reset(struct tg3 *tp)
 {
 	u32 phy_status;
 	int err;
@@ -666,12 +777,6 @@ static int tg3_phy_reset(struct tg3 *tp,
 	if (err != 0)
 		return -EBUSY;
 
-	/* If we have link, and not forcing a reset, then nothing
-	 * to do.
-	 */
-	if ((phy_status & BMSR_LSTATUS) != 0 && (force == 0))
-		return 0;
-
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
@@ -698,6 +803,30 @@ out:
 		tg3_writephy(tp, 0x1c, 0x8d68);
 		tg3_writephy(tp, 0x1c, 0x8d68);
 	}
+	if (tp->tg3_flags2 & TG3_FLG2_PHY_BER_BUG) {
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x310b);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x201f);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x9506);
+		tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x401f);
+		tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x14e2);
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0400);
+	}
+	/* Set Extended packet length bit (bit 14) on all chips that */
+	/* support jumbo frames */
+	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
+		/* Cannot do read-modify-write on 5401 */
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+		   GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+		u32 phy_reg;
+
+		/* Set bit 14 with read-modify-write to preserve other bits */
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007);
+		tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg);
+		tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000);
+	}
 	tg3_phy_set_wirespeed(tp);
 	return 0;
 }
@@ -783,6 +912,12 @@ static void tg3_frob_aux_power(struct tg
 
 static int tg3_setup_phy(struct tg3 *, int);
 
+#define RESET_KIND_SHUTDOWN	0
+#define RESET_KIND_INIT		1
+#define RESET_KIND_SUSPEND	2
+
+static void tg3_write_sig_post_reset(struct tg3 *, int);
+
 static int tg3_set_power_state(struct tg3 *tp, int state)
 {
 	u32 misc_host_ctrl;
@@ -869,6 +1004,8 @@ static int tg3_set_power_state(struct tg
 			mac_mode = MAC_MODE_PORT_MODE_TBI;
 		}
 
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
+			tw32(MAC_LED_CTRL, tp->led_ctrl);
 
 		if (((power_caps & PCI_PM_CAP_PME_D3cold) &&
 		     (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)))
@@ -894,7 +1031,8 @@ static int tg3_set_power_state(struct tg
 		     CLOCK_CTRL_ALTCLK |
 		     CLOCK_CTRL_PWRDOWN_PLL133);
 		udelay(40);
-	} else {
+	} else if (!((GET_ASIC_REV(tp->pci_chip_rev_id) == 5750) &&
+		     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
 		u32 newbits1, newbits2;
 
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
@@ -903,7 +1041,8 @@ static int tg3_set_power_state(struct tg
 				    CLOCK_CTRL_TXCLK_DISABLE |
 				    CLOCK_CTRL_ALTCLK);
 			newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
-		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+		} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+			   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 			newbits1 = CLOCK_CTRL_625_CORE;
 			newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
 		} else {
@@ -917,7 +1056,8 @@ static int tg3_set_power_state(struct tg
 		tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2);
 		udelay(40);
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
 			u32 newbits3;
 
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
@@ -940,6 +1080,8 @@ static int tg3_set_power_state(struct tg
 	/* Finally, set the new power state. */
 	pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
 
+	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+
 	return 0;
 }
 
@@ -968,6 +1110,8 @@ static void tg3_link_report(struct tg3 *
 static void tg3_setup_flow_control(struct tg3 *tp, u32 local_adv, u32 remote_adv)
 {
 	u32 new_tg3_flags = 0;
+	u32 old_rx_mode = tp->rx_mode;
+	u32 old_tx_mode = tp->tx_mode;
 
 	if (local_adv & ADVERTISE_PAUSE_CAP) {
 		if (local_adv & ADVERTISE_PAUSE_ASYM) {
@@ -998,10 +1142,18 @@ static void tg3_setup_flow_control(struc
 	else
 		tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
 
+	if (old_rx_mode != tp->rx_mode) {
+		tw32_f(MAC_RX_MODE, tp->rx_mode);
+	}
+	
 	if (new_tg3_flags & TG3_FLAG_TX_PAUSE)
 		tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
 	else
 		tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
+
+	if (old_tx_mode != tp->tx_mode) {
+		tw32_f(MAC_TX_MODE, tp->tx_mode);
+	}
 }
 
 static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
@@ -1189,7 +1341,8 @@ static int tg3_init_5401phy_dsp(struct t
 	int err;
 
 	/* Turn off tap power management. */
-	err  = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c20);
+	/* Set Extended packet length bit */
+	err  = tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x4c20);
 
 	err |= tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x0012);
 	err |= tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x1804);
@@ -1211,6 +1364,27 @@ static int tg3_init_5401phy_dsp(struct t
 	return err;
 }
 
+static int tg3_copper_is_advertising_all(struct tg3 *tp)
+{
+	u32 adv_reg, all_mask;
+
+	tg3_readphy(tp, MII_ADVERTISE, &adv_reg);
+	all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL |
+		    ADVERTISE_100HALF | ADVERTISE_100FULL);
+	if ((adv_reg & all_mask) != all_mask)
+		return 0;
+	if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
+		u32 tg3_ctrl;
+
+		tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl);
+		all_mask = (MII_TG3_CTRL_ADV_1000_HALF |
+			    MII_TG3_CTRL_ADV_1000_FULL);
+		if ((tg3_ctrl & all_mask) != all_mask)
+			return 0;
+	}
+	return 1;
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
 	int current_link_up;
@@ -1230,7 +1404,7 @@ static int tg3_setup_copper_phy(struct t
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
 	tw32_f(MAC_MI_MODE, tp->mi_mode);
-	udelay(40);
+	udelay(80);
 
 	tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x02);
 
@@ -1239,7 +1413,7 @@ static int tg3_setup_copper_phy(struct t
 	 */
 	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-	     tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) &&
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
 	    netif_carrier_ok(tp->dev)) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1247,7 +1421,7 @@ static int tg3_setup_copper_phy(struct t
 			force_reset = 1;
 	}
 	if (force_reset)
-		tg3_phy_reset(tp, 1);
+		tg3_phy_reset(tp);
 
 	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
 		tg3_readphy(tp, MII_BMSR, &bmsr);
@@ -1274,7 +1448,7 @@ static int tg3_setup_copper_phy(struct t
 			if ((tp->phy_id & PHY_ID_REV_MASK) == PHY_REV_BCM5401_B0 &&
 			    !(bmsr & BMSR_LSTATUS) &&
 			    tp->link_config.active_speed == SPEED_1000) {
-				err = tg3_phy_reset(tp, 1);
+				err = tg3_phy_reset(tp);
 				if (!err)
 					err = tg3_init_5401phy_dsp(tp);
 				if (err)
@@ -1299,18 +1473,27 @@ static int tg3_setup_copper_phy(struct t
 	else
 		tg3_writephy(tp, MII_TG3_IMASK, ~0);
 
-	if (tp->led_mode == led_mode_three_link)
-		tg3_writephy(tp, MII_TG3_EXT_CTRL,
-			     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
-	else
-		tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
+		if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
+			tg3_writephy(tp, MII_TG3_EXT_CTRL,
+				     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
+		else
+			tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
+	}
 
 	current_link_up = 0;
 	current_speed = SPEED_INVALID;
 	current_duplex = DUPLEX_INVALID;
 
-	tg3_readphy(tp, MII_BMSR, &bmsr);
-	tg3_readphy(tp, MII_BMSR, &bmsr);
+	bmsr = 0;
+	for (i = 0; i < 100; i++) {
+		tg3_readphy(tp, MII_BMSR, &bmsr);
+		tg3_readphy(tp, MII_BMSR, &bmsr);
+		if (bmsr & BMSR_LSTATUS)
+			break;
+		udelay(40);
+	}
 
 	if (bmsr & BMSR_LSTATUS) {
 		u32 aux_stat, bmcr;
@@ -1326,22 +1509,25 @@ static int tg3_setup_copper_phy(struct t
 		tg3_aux_stat_to_speed_duplex(tp, aux_stat,
 					     &current_speed,
 					     &current_duplex);
-		tg3_readphy(tp, MII_BMCR, &bmcr);
-		tg3_readphy(tp, MII_BMCR, &bmcr);
+
+		bmcr = 0;
+		for (i = 0; i < 200; i++) {
+			tg3_readphy(tp, MII_BMCR, &bmcr);
+			tg3_readphy(tp, MII_BMCR, &bmcr);
+			if (bmcr && bmcr != 0x7fff)
+				break;
+			udelay(10);
+		}
+
 		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
 			if (bmcr & BMCR_ANENABLE) {
-				u32 gig_ctrl;
-
 				current_link_up = 1;
 
 				/* Force autoneg restart if we are exiting
 				 * low power mode.
 				 */
-				tg3_readphy(tp, MII_TG3_CTRL, &gig_ctrl);
-				if (!(gig_ctrl & (MII_TG3_CTRL_ADV_1000_HALF |
-						  MII_TG3_CTRL_ADV_1000_FULL))) {
+				if (!tg3_copper_is_advertising_all(tp))
 					current_link_up = 0;
-				}
 			} else {
 				current_link_up = 0;
 			}
@@ -1407,14 +1593,13 @@ static int tg3_setup_copper_phy(struct t
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
-		if ((tp->led_mode == led_mode_link10) ||
+		if ((tp->led_ctrl == LED_CTRL_MODE_PHY_2) ||
 		    (current_link_up == 1 &&
 		     tp->link_config.active_speed == SPEED_10))
 			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
 	} else {
 		if (current_link_up == 1)
 			tp->mac_mode |= MAC_MODE_LINK_POLARITY;
-		tw32(MAC_LED_CTRL, LED_CTRL_PHY_MODE_1);
 	}
 
 	/* ??? Without this setting Netgear GA302T PHY does not
@@ -1424,7 +1609,7 @@ static int tg3_setup_copper_phy(struct t
 	    tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
 		tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
 		tw32_f(MAC_MI_MODE, tp->mi_mode);
-		udelay(40);
+		udelay(80);
 	}
 
 	tw32_f(MAC_MODE, tp->mac_mode);
@@ -1776,6 +1961,67 @@ static int tg3_fiber_aneg_smachine(struc
 	return ret;
 }
 
+static int fiber_autoneg(struct tg3 *tp, u32 *flags)
+{
+	int res = 0;
+
+	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
+		u32 dig_status;
+
+		dig_status = tr32(SG_DIG_STATUS);
+		*flags = 0;
+		if (dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
+			*flags |= MR_LP_ADV_ASYM_PAUSE;
+		if (dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
+			*flags |= MR_LP_ADV_SYM_PAUSE;
+
+		if ((dig_status & SG_DIG_AUTONEG_COMPLETE) &&
+		    !(dig_status & (SG_DIG_AUTONEG_ERROR |
+				    SG_DIG_PARTNER_FAULT_MASK)))
+			res = 1;
+	} else {
+		struct tg3_fiber_aneginfo aninfo;
+		int status = ANEG_FAILED;
+		unsigned int tick;
+		u32 tmp;
+
+		tw32_f(MAC_TX_AUTO_NEG, 0);
+
+		tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+		tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
+		udelay(40);
+
+		tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
+		udelay(40);
+
+		memset(&aninfo, 0, sizeof(aninfo));
+		aninfo.flags |= MR_AN_ENABLE;
+		aninfo.state = ANEG_STATE_UNKNOWN;
+		aninfo.cur_time = 0;
+		tick = 0;
+		while (++tick < 195000) {
+			status = tg3_fiber_aneg_smachine(tp, &aninfo);
+			if (status == ANEG_DONE || status == ANEG_FAILED)
+				break;
+
+			udelay(1);
+		}
+
+		tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
+		tw32_f(MAC_MODE, tp->mac_mode);
+		udelay(40);
+
+		*flags = aninfo.flags;
+
+		if (status == ANEG_DONE &&
+		    (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
+				     MR_LP_ADV_FULL_DUPLEX)))
+			res = 1;
+	}
+
+	return res;
+}
+
 static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
 {
 	u32 orig_pause_cfg;
@@ -1795,6 +2041,20 @@ static int tg3_setup_fiber_phy(struct tg
 	tw32_f(MAC_MODE, tp->mac_mode);
 	udelay(40);
 
+	if (tp->tg3_flags2 & TG3_FLG2_HW_AUTONEG) {
+		/* Allow time for the hardware to auto-negotiate (195ms) */
+		unsigned int tick = 0;
+
+		while (++tick < 195000) { 
+			if (tr32(SG_DIG_STATUS) & SG_DIG_AUTONEG_COMPLETE)
+				break;
+			udelay(1);
+		}
+		if (tick >= 195000)
+			printk(KERN_INFO PFX "%s: HW autoneg failed !\n",
+			    tp->dev->name);
+	}
+
 	/* Reset when initting first time or we have a link. */
 	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
 	    (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED)) {
@@ -1846,53 +2106,18 @@ static int tg3_setup_fiber_phy(struct tg
 	udelay(40);
 
 	current_link_up = 0;
-	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
-		if (tp->link_config.autoneg == AUTONEG_ENABLE &&
-		    !(tp->tg3_flags & TG3_FLAG_GOT_SERDES_FLOWCTL)) {
-			struct tg3_fiber_aneginfo aninfo;
-			int status = ANEG_FAILED;
-			unsigned int tick;
-			u32 tmp;
-
-			memset(&aninfo, 0, sizeof(aninfo));
-			aninfo.flags |= (MR_AN_ENABLE);
-
-			tw32(MAC_TX_AUTO_NEG, 0);
-
-			tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
-			tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
-			udelay(40);
-
-			tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
-			udelay(40);
-
-			aninfo.state = ANEG_STATE_UNKNOWN;
-			aninfo.cur_time = 0;
-			tick = 0;
-			while (++tick < 195000) {
-				status = tg3_fiber_aneg_smachine(tp, &aninfo);
-				if (status == ANEG_DONE ||
-				    status == ANEG_FAILED)
-					break;
-
-				udelay(1);
-			}
-
-			tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
-			tw32_f(MAC_MODE, tp->mac_mode);
-			udelay(40);
-
-			if (status == ANEG_DONE &&
-			    (aninfo.flags &
-			     (MR_AN_COMPLETE | MR_LINK_OK |
-			      MR_LP_ADV_FULL_DUPLEX))) {
+ 	if (tr32(MAC_STATUS) & MAC_STATUS_PCS_SYNCED) {
+		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
+			u32 flags;
+  
+			if (fiber_autoneg(tp, &flags)) {
 				u32 local_adv, remote_adv;
 
 				local_adv = ADVERTISE_PAUSE_CAP;
 				remote_adv = 0;
-				if (aninfo.flags & MR_LP_ADV_SYM_PAUSE)
-					remote_adv |= LPA_PAUSE_CAP;
-				if (aninfo.flags & MR_LP_ADV_ASYM_PAUSE)
+				if (flags & MR_LP_ADV_SYM_PAUSE)
+  					remote_adv |= LPA_PAUSE_CAP;
+				if (flags & MR_LP_ADV_ASYM_PAUSE)
 					remote_adv |= LPA_PAUSE_ASYM;
 
 				tg3_setup_flow_control(tp, local_adv, remote_adv);
@@ -1919,8 +2144,10 @@ static int tg3_setup_fiber_phy(struct tg
 		} else {
 			/* Forcing 1000FD link up. */
 			current_link_up = 1;
+			tp->tg3_flags |= TG3_FLAG_GOT_SERDES_FLOWCTL;
 		}
-	}
+	} else
+		tp->tg3_flags &= ~TG3_FLAG_GOT_SERDES_FLOWCTL;
 
 	tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 	tw32_f(MAC_MODE, tp->mac_mode);
@@ -1948,9 +2175,15 @@ static int tg3_setup_fiber_phy(struct tg
 	if (current_link_up == 1) {
 		tp->link_config.active_speed = SPEED_1000;
 		tp->link_config.active_duplex = DUPLEX_FULL;
+		tw32(MAC_LED_CTRL, (tp->led_ctrl |
+				    LED_CTRL_LNKLED_OVERRIDE |
+				    LED_CTRL_1000MBPS_ON));
 	} else {
 		tp->link_config.active_speed = SPEED_INVALID;
 		tp->link_config.active_duplex = DUPLEX_INVALID;
+		tw32(MAC_LED_CTRL, (tp->led_ctrl |
+				    LED_CTRL_LNKLED_OVERRIDE |
+				    LED_CTRL_TRAFFIC_OVERRIDE));
 	}
 
 	if (current_link_up != netif_carrier_ok(tp->dev)) {
@@ -2003,6 +2236,16 @@ static int tg3_setup_phy(struct tg3 *tp,
 		      (6 << TX_LENGTHS_IPG_SHIFT) |
 		      (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
+		if (netif_carrier_ok(tp->dev)) {
+			tw32(HOSTCC_STAT_COAL_TICKS,
+			     DEFAULT_STAT_COAL_TICKS);
+		} else {
+			tw32(HOSTCC_STAT_COAL_TICKS, 0);
+		}
+	}
+
 	return err;
 }
 
@@ -2211,6 +2454,11 @@ static int tg3_rx(struct tg3 *tp, int bu
 	int received;
 
 	hw_idx = tp->hw_status->idx[0].rx_producer;
+	/*
+	 * We need to order the read of hw_idx and the read of
+	 * the opaque cookie.
+	 */
+	rmb();
 	sw_idx = rx_rcb_ptr % TG3_RX_RCB_RING_SIZE(tp);
 	work_mask = 0;
 	received = 0;
@@ -2337,7 +2585,7 @@ next_pkt_nopost:
 
 static int tg3_poll(struct net_device *netdev, int *budget)
 {
-	struct tg3 *tp = netdev->priv;
+	struct tg3 *tp = netdev_priv(netdev);
 	struct tg3_hw_status *sblk = tp->hw_status;
 	unsigned long flags;
 	int done;
@@ -2419,7 +2667,7 @@ static inline unsigned int tg3_has_work(
 static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	struct tg3_hw_status *sblk = tp->hw_status;
 	unsigned long flags;
 	unsigned int handled = 1;
@@ -2465,6 +2713,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;
@@ -2492,7 +2747,7 @@ static void tg3_reset_task(void *_data)
 
 static void tg3_tx_timeout(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 
 	printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
 	       dev->name);
@@ -2602,13 +2857,12 @@ static inline int tg3_4g_overflow_test(d
 	u32 base = (u32) mapping & 0xffffffff;
 
 	return ((base > 0xffffdcc0) &&
-		((u64) mapping >> 32) == 0 &&
 		(base + len + 8 < base));
 }
 
-static int tg3_start_xmit_4gbug(struct sk_buff *skb, struct net_device *dev)
+static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	dma_addr_t mapping;
 	unsigned int i;
 	u32 len, entry, base_flags, mss;
@@ -2736,8 +2990,12 @@ static int tg3_start_xmit_4gbug(struct s
 				would_hit_hwbug = entry + 1;
 			}
 
-			tg3_set_txd(tp, entry, mapping, len,
-				    base_flags, (i == last));
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+				tg3_set_txd(tp, entry, mapping, len,
+					    base_flags, (i == last)|(mss << 1));
+			else
+				tg3_set_txd(tp, entry, mapping, len,
+					    base_flags, (i == last));
 
 			entry = NEXT_TX(entry);
 		}
@@ -2806,218 +3064,63 @@ out_unlock:
 	return 0;
 }
 
-static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
+			       int new_mtu)
 {
-	struct tg3 *tp = dev->priv;
-	dma_addr_t mapping;
-	u32 len, entry, base_flags, mss;
-	unsigned long flags;
+	dev->mtu = new_mtu;
 
-	len = skb_headlen(skb);
+	if (new_mtu > ETH_DATA_LEN)
+		tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE;
+	else
+		tp->tg3_flags &= ~TG3_FLAG_JUMBO_ENABLE;
+}
 
-	/* No BH disabling for tx_lock here.  We are running in BH disabled
-	 * context and TX reclaim runs via tp->poll inside of a software
-	 * interrupt.  Rejoice!
-	 *
-	 * Actually, things are not so simple.  If we are to take a hw
-	 * IRQ here, we can deadlock, consider:
-	 *
-	 *       CPU1		CPU2
-	 *   tg3_start_xmit
-	 *   take tp->tx_lock
-	 *			tg3_timer
-	 *			take tp->lock
-	 *   tg3_interrupt
-	 *   spin on tp->lock
-	 *			spin on tp->tx_lock
-	 *
-	 * So we really do need to disable interrupts when taking
-	 * tx_lock here.
-	 */
-	spin_lock_irqsave(&tp->tx_lock, flags);
+static int tg3_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct tg3 *tp = netdev_priv(dev);
 
-	/* This is a hard error, log it. */
-	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
-		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&tp->tx_lock, flags);
-		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-		       dev->name);
-		return 1;
-	}
+	if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
+		return -EINVAL;
 
-	entry = tp->tx_prod;
-	base_flags = 0;
-	if (skb->ip_summed == CHECKSUM_HW)
-		base_flags |= TXD_FLAG_TCPUDP_CSUM;
-#if TG3_TSO_SUPPORT != 0
-	mss = 0;
-	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-	    (mss = skb_shinfo(skb)->tso_size) != 0) {
-		int tcp_opt_len, ip_tcp_len;
+	if (!netif_running(dev)) {
+		/* We'll just catch it later when the
+		 * device is up'd.
+		 */
+		tg3_set_mtu(dev, tp, new_mtu);
+		return 0;
+	}
 
-		tcp_opt_len = ((skb->h.th->doff - 5) * 4);
-		ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
+	tg3_netif_stop(tp);
+	spin_lock_irq(&tp->lock);
+	spin_lock(&tp->tx_lock);
 
-		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
-			       TXD_FLAG_CPU_POST_DMA);
+	tg3_halt(tp);
 
-		skb->nh.iph->check = 0;
-		skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
-		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
-						      skb->nh.iph->daddr,
-						      0, IPPROTO_TCP, 0);
+	tg3_set_mtu(dev, tp, new_mtu);
 
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-			if (tcp_opt_len || skb->nh.iph->ihl > 5) {
-				int tsflags;
+	tg3_init_hw(tp);
 
-				tsflags = ((skb->nh.iph->ihl - 5) +
-					   (tcp_opt_len >> 2));
-				mss |= (tsflags << 11);
-			}
-		} else {
-			if (tcp_opt_len || skb->nh.iph->ihl > 5) {
-				int tsflags;
+	spin_unlock(&tp->tx_lock);
+	spin_unlock_irq(&tp->lock);
+	tg3_netif_start(tp);
 
-				tsflags = ((skb->nh.iph->ihl - 5) +
-					   (tcp_opt_len >> 2));
-				base_flags |= tsflags << 12;
-			}
-		}
-	}
-#else
-	mss = 0;
-#endif
-#if TG3_VLAN_TAG_USED
-	if (tp->vlgrp != NULL && vlan_tx_tag_present(skb))
-		base_flags |= (TXD_FLAG_VLAN |
-			       (vlan_tx_tag_get(skb) << 16));
-#endif
+	return 0;
+}
 
-	/* Queue skb data, a.k.a. the main skb fragment. */
-	mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+/* Free up pending packets in all rx/tx rings.
+ *
+ * The chip has been shut down and the driver detached from
+ * the networking, so no interrupts or new tx packets will
+ * end up in the driver.  tp->{tx,}lock is not held and we are not
+ * in an interrupt context and thus may sleep.
+ */
+static void tg3_free_rings(struct tg3 *tp)
+{
+	struct ring_info *rxp;
+	int i;
 
-	tp->tx_buffers[entry].skb = skb;
-	pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
-
-	tg3_set_txd(tp, entry, mapping, len, base_flags,
-		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
-
-	entry = NEXT_TX(entry);
-
-	/* Now loop through additional data fragments, and queue them. */
-	if (skb_shinfo(skb)->nr_frags > 0) {
-		unsigned int i, last;
-
-		last = skb_shinfo(skb)->nr_frags - 1;
-		for (i = 0; i <= last; i++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-
-
-			len = frag->size;
-			mapping = pci_map_page(tp->pdev,
-					       frag->page,
-					       frag->page_offset,
-					       len, PCI_DMA_TODEVICE);
-
-			tp->tx_buffers[entry].skb = NULL;
-			pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
-
-			tg3_set_txd(tp, entry, mapping, len,
-				    base_flags, (i == last));
-
-			entry = NEXT_TX(entry);
-		}
-	}
-
-	/* Packets are ready, update Tx producer idx local and on card.
-	 * We know this is not a 5700 (by virtue of not being a chip
-	 * requiring the 4GB overflow workaround) so we can safely omit
-	 * the double-write bug tests.
-	 */
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	} 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);
-
-		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	}
-
-	tp->tx_prod = entry;
-	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
-		netif_stop_queue(dev);
-
-	spin_unlock_irqrestore(&tp->tx_lock, flags);
-
-	dev->trans_start = jiffies;
-
-	return 0;
-}
-
-static inline void tg3_set_mtu(struct net_device *dev, struct tg3 *tp,
-			       int new_mtu)
-{
-	dev->mtu = new_mtu;
-
-	if (new_mtu > ETH_DATA_LEN)
-		tp->tg3_flags |= TG3_FLAG_JUMBO_ENABLE;
-	else
-		tp->tg3_flags &= ~TG3_FLAG_JUMBO_ENABLE;
-}
-
-static int tg3_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct tg3 *tp = dev->priv;
-
-	if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
-		return -EINVAL;
-
-	if (!netif_running(dev)) {
-		/* We'll just catch it later when the
-		 * device is up'd.
-		 */
-		tg3_set_mtu(dev, tp, new_mtu);
-		return 0;
-	}
-
-	tg3_netif_stop(tp);
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
-
-	tg3_halt(tp);
-
-	tg3_set_mtu(dev, tp, new_mtu);
-
-	tg3_init_hw(tp);
-
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
-	tg3_netif_start(tp);
-
-	return 0;
-}
-
-/* Free up pending packets in all rx/tx rings.
- *
- * The chip has been shut down and the driver detached from
- * the networking, so no interrupts or new tx packets will
- * end up in the driver.  tp->{tx,}lock is not held and we are not
- * in an interrupt context and thus may sleep.
- */
-static void tg3_free_rings(struct tg3 *tp)
-{
-	struct ring_info *rxp;
-	int i;
-
-	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
-		rxp = &tp->rx_std_buffers[i];
+	for (i = 0; i < TG3_RX_RING_SIZE; i++) {
+		rxp = &tp->rx_std_buffers[i];
 
 		if (rxp->skb == NULL)
 			continue;
@@ -3282,7 +3385,8 @@ static int tg3_stop_block(struct tg3 *tp
 	unsigned int i;
 	u32 val;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 		switch (ofs) {
 		case RCVLSC_MODE:
 		case DMAC_MODE:
@@ -3290,7 +3394,7 @@ static int tg3_stop_block(struct tg3 *tp
 		case BUFMGR_MODE:
 		case MEMARB_MODE:
 			/* We can't enable/disable these bits of the
-			 * 5705, just say success.
+			 * 5705/5750, just say success.
 			 */
 			return 0;
 
@@ -3389,27 +3493,115 @@ out:
 }
 
 /* tp->lock is held. */
-static void tg3_chip_reset(struct tg3 *tp)
+static int tg3_nvram_lock(struct tg3 *tp)
 {
-	u32 val;
-	u32 flags_save;
-
-	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
-		/* Force NVRAM to settle.
-		 * This deals with a chip bug which can result in EEPROM
-		 * corruption.
-		 */
-		if (tp->tg3_flags & TG3_FLAG_NVRAM) {
-			int i;
+	if (tp->tg3_flags & TG3_FLAG_NVRAM) {
+		int i;
 
-			tw32(NVRAM_SWARB, SWARB_REQ_SET1);
-			for (i = 0; i < 100000; i++) {
-				if (tr32(NVRAM_SWARB) & SWARB_GNT1)
-					break;
-				udelay(10);
-			}
+		tw32(NVRAM_SWARB, SWARB_REQ_SET1);
+		for (i = 0; i < 8000; i++) {
+			if (tr32(NVRAM_SWARB) & SWARB_GNT1)
+				break;
+			udelay(20);
 		}
+		if (i == 8000)
+			return -ENODEV;
+	}
+	return 0;
+}
+
+/* tp->lock is held. */
+static void tg3_nvram_unlock(struct tg3 *tp)
+{
+	if (tp->tg3_flags & TG3_FLAG_NVRAM)
+		tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
+}
+
+/* tp->lock is held. */
+static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
+{
+	tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
+
+	if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
+		switch (kind) {
+		case RESET_KIND_INIT:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_START);
+			break;
+
+		case RESET_KIND_SHUTDOWN:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_UNLOAD);
+			break;
+
+		case RESET_KIND_SUSPEND:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_SUSPEND);
+			break;
+
+		default:
+			break;
+		};
 	}
+}
+
+/* tp->lock is held. */
+static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
+{
+	if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
+		switch (kind) {
+		case RESET_KIND_INIT:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_START_DONE);
+			break;
+
+		case RESET_KIND_SHUTDOWN:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_UNLOAD_DONE);
+			break;
+
+		default:
+			break;
+		};
+	}
+}
+
+/* tp->lock is held. */
+static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
+{
+	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+		switch (kind) {
+		case RESET_KIND_INIT:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_START);
+			break;
+
+		case RESET_KIND_SHUTDOWN:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_UNLOAD);
+			break;
+
+		case RESET_KIND_SUSPEND:
+			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
+				      DRV_STATE_SUSPEND);
+			break;
+
+		default:
+			break;
+		};
+	}
+}
+
+/* tp->lock is held. */
+static int tg3_chip_reset(struct tg3 *tp)
+{
+	u32 val;
+	u32 flags_save;
+	int i;
+
+	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704))
+		tg3_nvram_lock(tp);
 
 	/*
 	 * We must avoid the readl() that normally takes place.
@@ -3422,23 +3614,66 @@ static void tg3_chip_reset(struct tg3 *t
 
 	/* do the reset */
 	val = GRC_MISC_CFG_CORECLK_RESET;
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+
+	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+		if (tr32(0x7e2c) == 0x60) {
+			tw32(0x7e2c, 0x20);
+		}
+		if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+			tw32(GRC_MISC_CFG, (1 << 29));
+			val |= (1 << 29);
+		}
+	}
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
 		val |= GRC_MISC_CFG_KEEP_GPHY_POWER;
 	tw32(GRC_MISC_CFG, val);
 
 	/* restore 5701 hardware bug workaround flag */
 	tp->tg3_flags = flags_save;
 
+	/* Unfortunately, we have to delay before the PCI read back.
+	 * Some 575X chips even will not respond to a PCI cfg access
+	 * when the reset command is given to the chip.
+	 *
+	 * How do these hardware designers expect things to work
+	 * properly if the PCI write is posted for a long period
+	 * of time?  It is always necessary to have some method by
+	 * which a register read back can occur to push the write
+	 * out which does the reset.
+	 *
+	 * For most tg3 variants the trick below was working.
+	 * Ho hum...
+	 */
+	udelay(120);
+
 	/* Flush PCI posted writes.  The normal MMIO registers
 	 * are inaccessible at this time so this is the only
-	 * way to make this reliably.  I tried to use indirect
+	 * way to make this reliably (actually, this is no longer
+	 * the case, see above).  I tried to use indirect
 	 * register read/write but this upset some 5701 variants.
 	 */
 	pci_read_config_dword(tp->pdev, PCI_COMMAND, &val);
 
-	udelay(40);
-	udelay(40);
-	udelay(40);
+	udelay(120);
+
+	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+		if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
+			int i;
+			u32 cfg_val;
+
+			/* Wait for link training to complete.  */
+			for (i = 0; i < 5000; i++)
+				udelay(100);
+
+			pci_read_config_dword(tp->pdev, 0xc4, &cfg_val);
+			pci_write_config_dword(tp->pdev, 0xc4,
+					       cfg_val | (1 << 15));
+		}
+		/* Set PCIE max payload size and clear error status.  */
+		pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
+	}
 
 	/* Re-enable indirect register accesses. */
 	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
@@ -3460,14 +3695,67 @@ static void tg3_chip_reset(struct tg3 *t
 
 	tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
 
+	tw32(GRC_MODE, tp->grc_mode);
+
+	if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
+		u32 val = tr32(0xc4);
+
+		tw32(0xc4, val | (1 << 15));
+	}
+
 	if ((tp->nic_sram_data_cfg & NIC_SRAM_DATA_CFG_MINI_PCI) != 0 &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-		tp->pci_clock_ctrl |=
-			(CLOCK_CTRL_FORCE_CLKRUN | CLOCK_CTRL_CLKRUN_OENABLE);
+		tp->pci_clock_ctrl |= CLOCK_CTRL_CLKRUN_OENABLE;
+		if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0)
+			tp->pci_clock_ctrl |= CLOCK_CTRL_FORCE_CLKRUN;
 		tw32(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 	}
 
-	tw32(TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
+	if (tp->phy_id == PHY_ID_SERDES) {
+		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
+		tw32_f(MAC_MODE, tp->mac_mode);
+	} else
+		tw32_f(MAC_MODE, 0);
+	udelay(40);
+
+	/* Wait for firmware initialization to complete. */
+	for (i = 0; i < 100000; i++) {
+		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
+		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
+			break;
+		udelay(10);
+	}
+	if (i >= 100000 &&
+	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
+		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
+		       "firmware will not restart magic=%08x\n",
+		       tp->dev->name, val);
+		return -ENODEV;
+	}
+
+	if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+		u32 val = tr32(0x7c00);
+
+		tw32(0x7c00, val | (1 << 25));
+	}
+
+	/* Reprobe ASF enable state.  */
+	tp->tg3_flags &= ~TG3_FLAG_ENABLE_ASF;
+	tp->tg3_flags2 &= ~TG3_FLG2_ASF_NEW_HANDSHAKE;
+	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
+	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
+		u32 nic_cfg;
+
+		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
+		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
+			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
+		}
+	}
+
+	return 0;
 }
 
 /* tp->lock is held. */
@@ -3494,40 +3782,20 @@ static void tg3_stop_fw(struct tg3 *tp)
 /* tp->lock is held. */
 static int tg3_halt(struct tg3 *tp)
 {
-	u32 val;
-	int i;
+	int err;
 
 	tg3_stop_fw(tp);
+
+	tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN);
+
 	tg3_abort_hw(tp);
-	tg3_chip_reset(tp);
-	tg3_write_mem(tp,
-		      NIC_SRAM_FIRMWARE_MBOX,
-		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
-	for (i = 0; i < 100000; i++) {
-		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
-		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-			break;
-		udelay(10);
-	}
+	err = tg3_chip_reset(tp);
 
-	if (i >= 100000 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
-		printk(KERN_ERR PFX "tg3_halt timed out for %s, "
-		       "firmware will not restart magic=%08x\n",
-		       tp->dev->name, val);
-		return -ENODEV;
-	}
+	tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN);
+	tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
-	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
-		if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
-			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
-				      DRV_STATE_WOL);
-		else
-			tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
-				      DRV_STATE_UNLOAD);
-	} else
-		tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
-			      DRV_STATE_SUSPEND);
+	if (err)
+		return err;
 
 	return 0;
 }
@@ -3828,305 +4096,305 @@ static int tg3_load_5701_a0_firmware_fix
 #if TG3_TSO_SUPPORT != 0
 
 #define TG3_TSO_FW_RELEASE_MAJOR	0x1
-#define TG3_TSO_FW_RELASE_MINOR		0x4
+#define TG3_TSO_FW_RELASE_MINOR		0x6
 #define TG3_TSO_FW_RELEASE_FIX		0x0
 #define TG3_TSO_FW_START_ADDR		0x08000000
 #define TG3_TSO_FW_TEXT_ADDR		0x08000000
-#define TG3_TSO_FW_TEXT_LEN		0x1a90
-#define TG3_TSO_FW_RODATA_ADDR		0x08001a900
+#define TG3_TSO_FW_TEXT_LEN		0x1aa0
+#define TG3_TSO_FW_RODATA_ADDR		0x08001aa0
 #define TG3_TSO_FW_RODATA_LEN		0x60
 #define TG3_TSO_FW_DATA_ADDR		0x08001b20
-#define TG3_TSO_FW_DATA_LEN		0x20
-#define TG3_TSO_FW_SBSS_ADDR		0x08001b40
+#define TG3_TSO_FW_DATA_LEN		0x30
+#define TG3_TSO_FW_SBSS_ADDR		0x08001b50
 #define TG3_TSO_FW_SBSS_LEN		0x2c
-#define TG3_TSO_FW_BSS_ADDR		0x08001b70
+#define TG3_TSO_FW_BSS_ADDR		0x08001b80
 #define TG3_TSO_FW_BSS_LEN		0x894
 
-static u32 tg3TsoFwText[] = {
-	0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800,
-	0x37bd4000, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000010, 0x00000000,
-	0x0000000d, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0x3c04fefe,
-	0xafbf0018, 0x0e0005d4, 0x34840002, 0x0e000664, 0x00000000, 0x3c030800,
-	0x90631b58, 0x24020002, 0x3c040800, 0x24841a9c, 0x14620003, 0x24050001,
-	0x3c040800, 0x24841a90, 0x24060003, 0x00003821, 0xafa00010, 0x0e000678,
+static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = {
+	0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000,
+	0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800,
+	0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
+	0xafbf0018, 0x0e0005d8, 0x34840002, 0x0e000668, 0x00000000, 0x3c030800,
+	0x90631b68, 0x24020002, 0x3c040800, 0x24841aac, 0x14620003, 0x24050001,
+	0x3c040800, 0x24841aa0, 0x24060006, 0x00003821, 0xafa00010, 0x0e00067c,
 	0xafa00014, 0x8f625c50, 0x34420001, 0xaf625c50, 0x8f625c90, 0x34420001,
 	0xaf625c90, 0x2402ffff, 0x0e000034, 0xaf625404, 0x8fbf0018, 0x03e00008,
 	0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c,
 	0xafb20018, 0xafb10014, 0x0e00005b, 0xafb00010, 0x24120002, 0x24110001,
 	0x8f706820, 0x32020100, 0x10400003, 0x00000000, 0x0e0000bb, 0x00000000,
-	0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001ef, 0x24040001,
+	0x8f706820, 0x32022000, 0x10400004, 0x32020001, 0x0e0001f0, 0x24040001,
 	0x32020001, 0x10400003, 0x00000000, 0x0e0000a3, 0x00000000, 0x3c020800,
-	0x90421b88, 0x14520003, 0x00000000, 0x0e0004bf, 0x00000000, 0x0a00003c,
+	0x90421b98, 0x14520003, 0x00000000, 0x0e0004c0, 0x00000000, 0x0a00003c,
 	0xaf715028, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
-	0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ab0, 0x00002821, 0x00003021,
-	0x00003821, 0xafbf0018, 0xafa00010, 0x0e000678, 0xafa00014, 0x3c040800,
-	0x248423c8, 0xa4800000, 0x3c010800, 0xa0201b88, 0x3c010800, 0xac201b8c,
-	0x3c010800, 0xac201b90, 0x3c010800, 0xac201b94, 0x3c010800, 0xac201b9c,
-	0x3c010800, 0xac201ba8, 0x3c010800, 0xac201bac, 0x8f624434, 0x3c010800,
-	0xac221b78, 0x8f624438, 0x3c010800, 0xac221b7c, 0x8f624410, 0xac80f7a8,
-	0x3c010800, 0xac201b74, 0x3c010800, 0xac2023d0, 0x3c010800, 0xac2023b8,
-	0x3c010800, 0xac2023bc, 0x3c010800, 0xac2023f0, 0x3c010800, 0xac221b80,
+	0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac0, 0x00002821, 0x00003021,
+	0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x3c040800,
+	0x248423d8, 0xa4800000, 0x3c010800, 0xa0201b98, 0x3c010800, 0xac201b9c,
+	0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
+	0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bbc, 0x8f624434, 0x3c010800,
+	0xac221b88, 0x8f624438, 0x3c010800, 0xac221b8c, 0x8f624410, 0xac80f7a8,
+	0x3c010800, 0xac201b84, 0x3c010800, 0xac2023e0, 0x3c010800, 0xac2023c8,
+	0x3c010800, 0xac2023cc, 0x3c010800, 0xac202400, 0x3c010800, 0xac221b90,
 	0x8f620068, 0x24030007, 0x00021702, 0x10430005, 0x00000000, 0x8f620068,
-	0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac2023fc,
-	0xac820034, 0x3c040800, 0x24841abc, 0x3c050800, 0x8ca523fc, 0x00003021,
-	0x00003821, 0xafa00010, 0x0e000678, 0xafa00014, 0x8fbf0018, 0x03e00008,
-	0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ac8, 0x00002821, 0x00003021,
-	0x00003821, 0xafbf0018, 0xafa00010, 0x0e000678, 0xafa00014, 0x0e00005b,
+	0x00021702, 0x14400004, 0x24020001, 0x3c010800, 0x0a000097, 0xac20240c,
+	0xac820034, 0x3c040800, 0x24841acc, 0x3c050800, 0x8ca5240c, 0x00003021,
+	0x00003821, 0xafa00010, 0x0e00067c, 0xafa00014, 0x8fbf0018, 0x03e00008,
+	0x27bd0020, 0x27bdffe0, 0x3c040800, 0x24841ad8, 0x00002821, 0x00003021,
+	0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014, 0x0e00005b,
 	0x00000000, 0x0e0000b4, 0x00002021, 0x8fbf0018, 0x03e00008, 0x27bd0020,
 	0x24020001, 0x8f636820, 0x00821004, 0x00021027, 0x00621824, 0x03e00008,
 	0xaf636820, 0x27bdffd0, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020,
 	0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f675c5c, 0x3c030800,
-	0x24631bac, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b88,
-	0x14400118, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902,
+	0x24631bbc, 0x8c620000, 0x14470005, 0x3c0200ff, 0x3c020800, 0x90421b98,
+	0x14400119, 0x3c0200ff, 0x3442fff8, 0x00e28824, 0xac670000, 0x00111902,
 	0x306300ff, 0x30e20003, 0x000211c0, 0x00622825, 0x00a04021, 0x00071602,
-	0x3c030800, 0x90631b88, 0x3044000f, 0x14600036, 0x00804821, 0x24020001,
-	0x3c010800, 0xa0221b88, 0x00051100, 0x00821025, 0x3c010800, 0xac201b8c,
-	0x3c010800, 0xac201b90, 0x3c010800, 0xac201b94, 0x3c010800, 0xac201b9c,
-	0x3c010800, 0xac201ba8, 0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4,
-	0x3c010800, 0xa42223c8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222400,
-	0x30428000, 0x3c010800, 0xa4231bb6, 0x10400005, 0x24020001, 0x3c010800,
-	0xac2223e4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023e4,
-	0x9622000a, 0x3c030800, 0x94631bb6, 0x3c010800, 0xac2023e0, 0x3c010800,
-	0xac2023e8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800,
-	0xa42223c0, 0x3c010800, 0x0a000115, 0xa4231b86, 0x9622000c, 0x3c010800,
-	0xa42223dc, 0x3c040800, 0x24841b8c, 0x8c820000, 0x00021100, 0x3c010800,
-	0x00220821, 0xac311bb8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
-	0xac271bbc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800,
-	0x00220821, 0xac261bc0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
-	0xac291bc4, 0x96230008, 0x3c020800, 0x8c421b9c, 0x00432821, 0x3c010800,
-	0xac251b9c, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14,
+	0x3c030800, 0x90631b98, 0x3044000f, 0x14600036, 0x00804821, 0x24020001,
+	0x3c010800, 0xa0221b98, 0x00051100, 0x00821025, 0x3c010800, 0xac201b9c,
+	0x3c010800, 0xac201ba0, 0x3c010800, 0xac201ba4, 0x3c010800, 0xac201bac,
+	0x3c010800, 0xac201bb8, 0x3c010800, 0xac201bb0, 0x3c010800, 0xac201bb4,
+	0x3c010800, 0xa42223d8, 0x9622000c, 0x30437fff, 0x3c010800, 0xa4222410,
+	0x30428000, 0x3c010800, 0xa4231bc6, 0x10400005, 0x24020001, 0x3c010800,
+	0xac2223f4, 0x0a000102, 0x2406003e, 0x24060036, 0x3c010800, 0xac2023f4,
+	0x9622000a, 0x3c030800, 0x94631bc6, 0x3c010800, 0xac2023f0, 0x3c010800,
+	0xac2023f8, 0x00021302, 0x00021080, 0x00c21021, 0x00621821, 0x3c010800,
+	0xa42223d0, 0x3c010800, 0x0a000115, 0xa4231b96, 0x9622000c, 0x3c010800,
+	0xa42223ec, 0x3c040800, 0x24841b9c, 0x8c820000, 0x00021100, 0x3c010800,
+	0x00220821, 0xac311bc8, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
+	0xac271bcc, 0x8c820000, 0x25030001, 0x306601ff, 0x00021100, 0x3c010800,
+	0x00220821, 0xac261bd0, 0x8c820000, 0x00021100, 0x3c010800, 0x00220821,
+	0xac291bd4, 0x96230008, 0x3c020800, 0x8c421bac, 0x00432821, 0x3c010800,
+	0xac251bac, 0x9622000a, 0x30420004, 0x14400018, 0x00061100, 0x8f630c14,
 	0x3063000f, 0x2c620002, 0x1440000b, 0x3c02c000, 0x8f630c14, 0x3c020800,
-	0x8c421b30, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b30, 0x2c620002,
+	0x8c421b40, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002,
 	0x1040fff7, 0x3c02c000, 0x00e21825, 0xaf635c5c, 0x8f625c50, 0x30420002,
-	0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b70,
-	0x3c040800, 0x94841b84, 0x01221025, 0x3c010800, 0xa42223ca, 0x24020001,
-	0x3c010800, 0xac221ba8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003,
-	0xac231b70, 0x3c010800, 0xa4251b84, 0x3c060800, 0x24c61b8c, 0x8cc20000,
-	0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000652,
-	0x24040002, 0x0a0001e5, 0x00000000, 0x3c020800, 0x8c421ba8, 0x10400077,
-	0x24020001, 0x3c050800, 0x90a51b88, 0x14a20071, 0x00000000, 0x3c150800,
-	0x96b51b86, 0x3c040800, 0x8c841b9c, 0x32a3ffff, 0x0083102a, 0x1440006b,
-	0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523e0, 0x1060005b,
+	0x10400014, 0x00000000, 0x0a000147, 0x00000000, 0x3c030800, 0x8c631b80,
+	0x3c040800, 0x94841b94, 0x01221025, 0x3c010800, 0xa42223da, 0x24020001,
+	0x3c010800, 0xac221bb8, 0x24630001, 0x0085202a, 0x3c010800, 0x10800003,
+	0xac231b80, 0x3c010800, 0xa4251b94, 0x3c060800, 0x24c61b9c, 0x8cc20000,
+	0x24420001, 0xacc20000, 0x28420080, 0x14400005, 0x00000000, 0x0e000656,
+	0x24040002, 0x0a0001e6, 0x00000000, 0x3c020800, 0x8c421bb8, 0x10400078,
+	0x24020001, 0x3c050800, 0x90a51b98, 0x14a20072, 0x00000000, 0x3c150800,
+	0x96b51b96, 0x3c040800, 0x8c841bac, 0x32a3ffff, 0x0083102a, 0x1440006c,
+	0x00000000, 0x14830003, 0x00000000, 0x3c010800, 0xac2523f0, 0x1060005c,
 	0x00009021, 0x24d60004, 0x0060a021, 0x24d30014, 0x8ec20000, 0x00028100,
-	0x3c110800, 0x02308821, 0x0e000621, 0x8e311bb8, 0x00402821, 0x10a00053,
-	0x00000000, 0x9628000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e22000c,
-	0x2407188c, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bc0, 0x3c020800,
-	0x00501021, 0x8c421bc4, 0x00031d00, 0x00021400, 0x00621825, 0xaca30014,
-	0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff, 0x00431021,
-	0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000, 0x30c4ffff,
-	0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004, 0x8e63fff4,
-	0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021, 0xae62fff4,
-	0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0, 0xae60fff4,
-	0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008, 0x24020305,
-	0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c, 0x0a0001ca,
-	0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223e0, 0x10400003, 0x3c024b65,
-	0x0a0001d2, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c, 0x30e2ffff,
-	0xaca20010, 0x0e00059f, 0x00a02021, 0x3242ffff, 0x0054102b, 0x1440ffaa,
-	0x00000000, 0x24020002, 0x3c010800, 0x0a0001e5, 0xa0221b88, 0x8ec2083c,
-	0x24420001, 0x0a0001e5, 0xaec2083c, 0x0e0004bf, 0x00000000, 0x8fbf002c,
-	0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028, 0xafb30024,
-	0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff, 0x3442fff8,
-	0x3c060800, 0x24c61ba4, 0x02428824, 0x9623000e, 0x8cc20000, 0x00431021,
-	0xacc20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821, 0x0e000637,
-	0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002,
-	0x10400121, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1040011c,
-	0x00000000, 0x0a00020c, 0x00000000, 0x8e240008, 0x8e230014, 0x00041402,
-	0x000241c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f, 0x00031942,
-	0x30637800, 0x00021100, 0x24424000, 0x00625021, 0x9542000a, 0x3084ffff,
-	0x30420008, 0x104000b3, 0x000429c0, 0x3c020800, 0x8c4223f0, 0x1440002d,
-	0x25050008, 0x95020014, 0x3c010800, 0xa42223c0, 0x8d070010, 0x00071402,
-	0x3c010800, 0xa42223c2, 0x3c010800, 0xa42723c4, 0x9502000e, 0x30e3ffff,
-	0x00431023, 0x3c010800, 0xac2223f8, 0x8f626800, 0x3c030010, 0x00431024,
-	0x10400005, 0x00000000, 0x9503001a, 0x9502001c, 0x0a000241, 0x00431021,
-	0x9502001a, 0x3c010800, 0xac2223ec, 0x3c02c000, 0x02421825, 0x3c010800,
-	0xac2823f0, 0x3c010800, 0xac3223f4, 0xaf635c9c, 0x8f625c90, 0x30420002,
-	0x104000df, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000da,
-	0x00000000, 0x0a00024e, 0x00000000, 0x9502000e, 0x3c030800, 0x946323c4,
-	0x00434823, 0x3123ffff, 0x2c620008, 0x1040001c, 0x00000000, 0x95020014,
-	0x24420028, 0x00a22821, 0x00031042, 0x1840000b, 0x00002021, 0x24c60848,
-	0x00403821, 0x94a30000, 0x8cc20000, 0x24840001, 0x00431021, 0xacc20000,
-	0x0087102a, 0x1440fff9, 0x24a50002, 0x31220001, 0x1040001f, 0x3c024000,
-	0x3c040800, 0x248423ec, 0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021,
-	0x0a00028d, 0xac820000, 0x8f626800, 0x3c030010, 0x00431024, 0x10400009,
-	0x00000000, 0x9502001a, 0x3c030800, 0x8c6323ec, 0x00431021, 0x3c010800,
-	0xac2223ec, 0x0a00028e, 0x3c024000, 0x9502001a, 0x9504001c, 0x3c030800,
-	0x8c6323ec, 0x00441023, 0x00621821, 0x3c010800, 0xac2323ec, 0x3c024000,
-	0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000,
-	0x9542000a, 0x30420010, 0x10400095, 0x00000000, 0x3c060800, 0x24c623f0,
-	0x3c020800, 0x944223c4, 0x8cc50000, 0x3c040800, 0x8c8423f8, 0x24420030,
-	0x00a22821, 0x94a20004, 0x3c030800, 0x8c6323ec, 0x00441023, 0x00621821,
-	0x00603821, 0x00032402, 0x30e2ffff, 0x00823821, 0x00071402, 0x00e23821,
-	0x00071027, 0x3c010800, 0xac2323ec, 0xa4a20006, 0x3c030800, 0x8c6323f4,
-	0x3c0200ff, 0x3442fff8, 0x00628824, 0x96220008, 0x24040001, 0x24034000,
-	0x000241c0, 0x00e01021, 0xa502001a, 0xa500001c, 0xacc00000, 0x3c010800,
-	0xac241b50, 0xaf635cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000,
-	0x3c010800, 0xac201b50, 0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002,
-	0x10400003, 0x00000000, 0x3c010800, 0xac201b50, 0x3c020800, 0x8c421b50,
-	0x1040ffec, 0x00000000, 0x3c040800, 0x0e000637, 0x8c8423f4, 0x0a00032c,
-	0x00000000, 0x3c030800, 0x90631b88, 0x24020002, 0x14620003, 0x3c034b65,
-	0x0a0002e3, 0x00008021, 0x8e22001c, 0x34637654, 0x10430002, 0x24100002,
-	0x24100001, 0x01002021, 0x0e000352, 0x02003021, 0x24020003, 0x3c010800,
-	0xa0221b88, 0x24020002, 0x1202000a, 0x24020001, 0x3c030800, 0x8c6323e0,
-	0x10620006, 0x00000000, 0x3c020800, 0x944223c8, 0x00021400, 0x0a000321,
-	0xae220014, 0x3c040800, 0x248423ca, 0x94820000, 0x00021400, 0xae220014,
-	0x3c020800, 0x8c421bac, 0x3c03c000, 0x3c010800, 0xa0201b88, 0x00431025,
-	0xaf625c5c, 0x8f625c50, 0x30420002, 0x10400009, 0x00000000, 0x2484f7e2,
-	0x8c820000, 0x00431025, 0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa,
-	0x00000000, 0x3c020800, 0x24421b74, 0x8c430000, 0x24630001, 0xac430000,
-	0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14,
-	0x3c020800, 0x8c421b30, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b30,
-	0x2c620002, 0x1040fff7, 0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c,
-	0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x12600003, 0x00000000,
-	0x0e0004bf, 0x00000000, 0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c,
-	0x8fb00018, 0x03e00008, 0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b78,
-	0x8c820000, 0x00031c02, 0x0043102b, 0x14400007, 0x3c038000, 0x8c840004,
-	0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444,
-	0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008,
-	0x3042ffff, 0x3c024000, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002,
-	0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821,
-	0x14c00011, 0x256e0008, 0x3c020800, 0x8c4223e4, 0x10400007, 0x24020016,
-	0x3c010800, 0xa42223c2, 0x2402002a, 0x3c010800, 0x0a000366, 0xa42223c4,
-	0x8d670010, 0x00071402, 0x3c010800, 0xa42223c2, 0x3c010800, 0xa42723c4,
-	0x3c040800, 0x948423c4, 0x3c030800, 0x946323c2, 0x95cf0006, 0x3c020800,
-	0x944223c0, 0x00832023, 0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821,
-	0x3082ffff, 0x14c0001a, 0x01226021, 0x9582000c, 0x3042003f, 0x3c010800,
-	0xa42223c6, 0x95820004, 0x95830006, 0x3c010800, 0xac2023d4, 0x3c010800,
-	0xac2023d8, 0x00021400, 0x00431025, 0x3c010800, 0xac221bb0, 0x95220004,
-	0x3c010800, 0xa4221bb4, 0x95230002, 0x01e51023, 0x0043102a, 0x10400010,
-	0x24020001, 0x3c010800, 0x0a00039a, 0xac2223e8, 0x3c030800, 0x8c6323d8,
-	0x3c020800, 0x94421bb4, 0x00431021, 0xa5220004, 0x3c020800, 0x94421bb0,
-	0xa5820004, 0x3c020800, 0x8c421bb0, 0xa5820006, 0x3c020800, 0x8c4223e0,
-	0x3c0d0800, 0x8dad23d4, 0x3c0a0800, 0x144000e5, 0x8d4a23d8, 0x3c020800,
-	0x94421bb4, 0x004a1821, 0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d,
-	0x01435023, 0x3c020800, 0x944223c6, 0x30420009, 0x10400008, 0x00000000,
-	0x9582000c, 0x3042fff6, 0xa582000c, 0x3c020800, 0x944223c6, 0x30420009,
-	0x01a26823, 0x3c020800, 0x8c4223e8, 0x1040004a, 0x01203821, 0x3c020800,
-	0x944223c2, 0x00004021, 0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff,
-	0x00021042, 0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001,
-	0x00c23021, 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff,
-	0x00623021, 0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a,
-	0x00003021, 0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021,
-	0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009,
-	0x00442023, 0x01803821, 0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042,
-	0x18400010, 0x00c33021, 0x00404821, 0x94e20000, 0x24e70002, 0x00c23021,
+	0x3c110800, 0x02308821, 0x0e000625, 0x8e311bc8, 0x00402821, 0x10a00054,
+	0x00000000, 0x9628000a, 0x31020040, 0x10400005, 0x2407180c, 0x8e22000c,
+	0x2407188c, 0x00021400, 0xaca20018, 0x3c030800, 0x00701821, 0x8c631bd0,
+	0x3c020800, 0x00501021, 0x8c421bd4, 0x00031d00, 0x00021400, 0x00621825,
+	0xaca30014, 0x8ec30004, 0x96220008, 0x00432023, 0x3242ffff, 0x3083ffff,
+	0x00431021, 0x0282102a, 0x14400002, 0x02b23023, 0x00803021, 0x8e620000,
+	0x30c4ffff, 0x00441021, 0xae620000, 0x8e220000, 0xaca20000, 0x8e220004,
+	0x8e63fff4, 0x00431021, 0xaca20004, 0xa4a6000e, 0x8e62fff4, 0x00441021,
+	0xae62fff4, 0x96230008, 0x0043102a, 0x14400005, 0x02469021, 0x8e62fff0,
+	0xae60fff4, 0x24420001, 0xae62fff0, 0xaca00008, 0x3242ffff, 0x14540008,
+	0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x24020905, 0xa4a2000c,
+	0x0a0001cb, 0x34e70020, 0xa4a2000c, 0x3c020800, 0x8c4223f0, 0x10400003,
+	0x3c024b65, 0x0a0001d3, 0x34427654, 0x3c02b49a, 0x344289ab, 0xaca2001c,
+	0x30e2ffff, 0xaca20010, 0x0e0005a2, 0x00a02021, 0x3242ffff, 0x0054102b,
+	0x1440ffa9, 0x00000000, 0x24020002, 0x3c010800, 0x0a0001e6, 0xa0221b98,
+	0x8ec2083c, 0x24420001, 0x0a0001e6, 0xaec2083c, 0x0e0004c0, 0x00000000,
+	0x8fbf002c, 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
+	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf0028,
+	0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f725c9c, 0x3c0200ff,
+	0x3442fff8, 0x3c070800, 0x24e71bb4, 0x02428824, 0x9623000e, 0x8ce20000,
+	0x00431021, 0xace20000, 0x8e220010, 0x30420020, 0x14400011, 0x00809821,
+	0x0e00063b, 0x02202021, 0x3c02c000, 0x02421825, 0xaf635c9c, 0x8f625c90,
+	0x30420002, 0x1040011e, 0x00000000, 0xaf635c9c, 0x8f625c90, 0x30420002,
+	0x10400119, 0x00000000, 0x0a00020d, 0x00000000, 0x8e240008, 0x8e230014,
+	0x00041402, 0x000231c0, 0x00031502, 0x304201ff, 0x2442ffff, 0x3042007f,
+	0x00031942, 0x30637800, 0x00021100, 0x24424000, 0x00624821, 0x9522000a,
+	0x3084ffff, 0x30420008, 0x104000b0, 0x000429c0, 0x3c020800, 0x8c422400,
+	0x14400024, 0x24c50008, 0x94c20014, 0x3c010800, 0xa42223d0, 0x8cc40010,
+	0x00041402, 0x3c010800, 0xa42223d2, 0x3c010800, 0xa42423d4, 0x94c2000e,
+	0x3083ffff, 0x00431023, 0x3c010800, 0xac222408, 0x94c2001a, 0x3c010800,
+	0xac262400, 0x3c010800, 0xac322404, 0x3c010800, 0xac2223fc, 0x3c02c000,
+	0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e5, 0x00000000,
+	0xaf635c9c, 0x8f625c90, 0x30420002, 0x104000e0, 0x00000000, 0x0a000246,
+	0x00000000, 0x94c2000e, 0x3c030800, 0x946323d4, 0x00434023, 0x3103ffff,
+	0x2c620008, 0x1040001c, 0x00000000, 0x94c20014, 0x24420028, 0x00a22821,
+	0x00031042, 0x1840000b, 0x00002021, 0x24e60848, 0x00403821, 0x94a30000,
+	0x8cc20000, 0x24840001, 0x00431021, 0xacc20000, 0x0087102a, 0x1440fff9,
+	0x24a50002, 0x31020001, 0x1040001f, 0x3c024000, 0x3c040800, 0x248423fc,
+	0xa0a00001, 0x94a30000, 0x8c820000, 0x00431021, 0x0a000285, 0xac820000,
+	0x8f626800, 0x3c030010, 0x00431024, 0x10400009, 0x00000000, 0x94c2001a,
+	0x3c030800, 0x8c6323fc, 0x00431021, 0x3c010800, 0xac2223fc, 0x0a000286,
+	0x3c024000, 0x94c2001a, 0x94c4001c, 0x3c030800, 0x8c6323fc, 0x00441023,
+	0x00621821, 0x3c010800, 0xac2323fc, 0x3c024000, 0x02421825, 0xaf635c9c,
+	0x8f625c90, 0x30420002, 0x1440fffc, 0x00000000, 0x9522000a, 0x30420010,
+	0x1040009b, 0x00000000, 0x3c030800, 0x946323d4, 0x3c070800, 0x24e72400,
+	0x8ce40000, 0x8f626800, 0x24630030, 0x00832821, 0x3c030010, 0x00431024,
+	0x1440000a, 0x00000000, 0x94a20004, 0x3c040800, 0x8c842408, 0x3c030800,
+	0x8c6323fc, 0x00441023, 0x00621821, 0x3c010800, 0xac2323fc, 0x3c040800,
+	0x8c8423fc, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402, 0x00822021,
+	0x00041027, 0xa4a20006, 0x3c030800, 0x8c632404, 0x3c0200ff, 0x3442fff8,
+	0x00628824, 0x96220008, 0x24050001, 0x24034000, 0x000231c0, 0x00801021,
+	0xa4c2001a, 0xa4c0001c, 0xace00000, 0x3c010800, 0xac251b60, 0xaf635cb8,
+	0x8f625cb0, 0x30420002, 0x10400003, 0x00000000, 0x3c010800, 0xac201b60,
+	0x8e220008, 0xaf625cb8, 0x8f625cb0, 0x30420002, 0x10400003, 0x00000000,
+	0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x1040ffec, 0x00000000,
+	0x3c040800, 0x0e00063b, 0x8c842404, 0x0a00032a, 0x00000000, 0x3c030800,
+	0x90631b98, 0x24020002, 0x14620003, 0x3c034b65, 0x0a0002e1, 0x00008021,
+	0x8e22001c, 0x34637654, 0x10430002, 0x24100002, 0x24100001, 0x00c02021,
+	0x0e000350, 0x02003021, 0x24020003, 0x3c010800, 0xa0221b98, 0x24020002,
+	0x1202000a, 0x24020001, 0x3c030800, 0x8c6323f0, 0x10620006, 0x00000000,
+	0x3c020800, 0x944223d8, 0x00021400, 0x0a00031f, 0xae220014, 0x3c040800,
+	0x248423da, 0x94820000, 0x00021400, 0xae220014, 0x3c020800, 0x8c421bbc,
+	0x3c03c000, 0x3c010800, 0xa0201b98, 0x00431025, 0xaf625c5c, 0x8f625c50,
+	0x30420002, 0x10400009, 0x00000000, 0x2484f7e2, 0x8c820000, 0x00431025,
+	0xaf625c5c, 0x8f625c50, 0x30420002, 0x1440fffa, 0x00000000, 0x3c020800,
+	0x24421b84, 0x8c430000, 0x24630001, 0xac430000, 0x8f630c14, 0x3063000f,
+	0x2c620002, 0x1440000c, 0x3c024000, 0x8f630c14, 0x3c020800, 0x8c421b40,
+	0x3063000f, 0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7,
+	0x00000000, 0x3c024000, 0x02421825, 0xaf635c9c, 0x8f625c90, 0x30420002,
+	0x1440fffc, 0x00000000, 0x12600003, 0x00000000, 0x0e0004c0, 0x00000000,
+	0x8fbf0028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x03e00008,
+	0x27bd0030, 0x8f634450, 0x3c040800, 0x24841b88, 0x8c820000, 0x00031c02,
+	0x0043102b, 0x14400007, 0x3c038000, 0x8c840004, 0x8f624450, 0x00021c02,
+	0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
+	0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3c024000,
+	0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00000000,
+	0x03e00008, 0x00000000, 0x27bdffe0, 0x00805821, 0x14c00011, 0x256e0008,
+	0x3c020800, 0x8c4223f4, 0x10400007, 0x24020016, 0x3c010800, 0xa42223d2,
+	0x2402002a, 0x3c010800, 0x0a000364, 0xa42223d4, 0x8d670010, 0x00071402,
+	0x3c010800, 0xa42223d2, 0x3c010800, 0xa42723d4, 0x3c040800, 0x948423d4,
+	0x3c030800, 0x946323d2, 0x95cf0006, 0x3c020800, 0x944223d0, 0x00832023,
+	0x01e2c023, 0x3065ffff, 0x24a20028, 0x01c24821, 0x3082ffff, 0x14c0001a,
+	0x01226021, 0x9582000c, 0x3042003f, 0x3c010800, 0xa42223d6, 0x95820004,
+	0x95830006, 0x3c010800, 0xac2023e4, 0x3c010800, 0xac2023e8, 0x00021400,
+	0x00431025, 0x3c010800, 0xac221bc0, 0x95220004, 0x3c010800, 0xa4221bc4,
+	0x95230002, 0x01e51023, 0x0043102a, 0x10400010, 0x24020001, 0x3c010800,
+	0x0a000398, 0xac2223f8, 0x3c030800, 0x8c6323e8, 0x3c020800, 0x94421bc4,
+	0x00431021, 0xa5220004, 0x3c020800, 0x94421bc0, 0xa5820004, 0x3c020800,
+	0x8c421bc0, 0xa5820006, 0x3c020800, 0x8c4223f0, 0x3c0d0800, 0x8dad23e4,
+	0x3c0a0800, 0x144000e5, 0x8d4a23e8, 0x3c020800, 0x94421bc4, 0x004a1821,
+	0x3063ffff, 0x0062182b, 0x24020002, 0x10c2000d, 0x01435023, 0x3c020800,
+	0x944223d6, 0x30420009, 0x10400008, 0x00000000, 0x9582000c, 0x3042fff6,
+	0xa582000c, 0x3c020800, 0x944223d6, 0x30420009, 0x01a26823, 0x3c020800,
+	0x8c4223f8, 0x1040004a, 0x01203821, 0x3c020800, 0x944223d2, 0x00004021,
+	0xa520000a, 0x01e21023, 0xa5220002, 0x3082ffff, 0x00021042, 0x18400008,
+	0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021, 0x0103102a,
+	0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402,
+	0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021, 0x2527000c,
+	0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004, 0x1440fffb,
+	0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023, 0x01803821,
+	0x3082ffff, 0xa4e00010, 0x00621821, 0x00021042, 0x18400010, 0x00c33021,
+	0x00404821, 0x94e20000, 0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006,
+	0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008,
+	0x0109102a, 0x1440fff3, 0x00000000, 0x30820001, 0x10400005, 0x00061c02,
+	0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02, 0x30c2ffff, 0x00623021,
+	0x00061402, 0x00c23021, 0x0a00047d, 0x30c6ffff, 0x24020002, 0x14c20081,
+	0x00000000, 0x3c020800, 0x8c42240c, 0x14400007, 0x00000000, 0x3c020800,
+	0x944223d2, 0x95230002, 0x01e21023, 0x10620077, 0x00000000, 0x3c020800,
+	0x944223d2, 0x01e21023, 0xa5220002, 0x3c020800, 0x8c42240c, 0x1040001a,
+	0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b96, 0x00e04021, 0x00072c02,
+	0x00aa2021, 0x00431023, 0x00823823, 0x00072402, 0x30e2ffff, 0x00823821,
+	0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800, 0x948423d4, 0x00453023,
+	0x00e02821, 0x00641823, 0x006d1821, 0x00c33021, 0x00061c02, 0x30c2ffff,
+	0x0a00047d, 0x00623021, 0x01203821, 0x00004021, 0x3082ffff, 0x00021042,
+	0x18400008, 0x00003021, 0x00401821, 0x94e20000, 0x25080001, 0x00c23021,
+	0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02, 0x30c2ffff, 0x00623021,
+	0x00061402, 0x00c23021, 0x00c02821, 0x00061027, 0xa522000a, 0x00003021,
+	0x2527000c, 0x00004021, 0x94e20000, 0x25080001, 0x00c23021, 0x2d020004,
+	0x1440fffb, 0x24e70002, 0x95220002, 0x00004021, 0x91230009, 0x00442023,
+	0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800, 0x948423d4, 0x00621821,
+	0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021, 0x00061c02, 0x3c020800,
+	0x944223d0, 0x00c34821, 0x00441023, 0x00021fc2, 0x00431021, 0x00021043,
+	0x18400010, 0x00003021, 0x00402021, 0x94e20000, 0x24e70002, 0x00c23021,
 	0x30e2007f, 0x14400006, 0x25080001, 0x8d630000, 0x3c02007f, 0x3442ff80,
-	0x00625824, 0x25670008, 0x0109102a, 0x1440fff3, 0x00000000, 0x30820001,
-	0x10400005, 0x00061c02, 0xa0e00001, 0x94e20000, 0x00c23021, 0x00061c02,
-	0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x0a00047f, 0x30c6ffff,
-	0x24020002, 0x14c20081, 0x00000000, 0x3c020800, 0x8c4223fc, 0x14400007,
-	0x00000000, 0x3c020800, 0x944223c2, 0x95230002, 0x01e21023, 0x10620077,
-	0x00000000, 0x3c020800, 0x944223c2, 0x01e21023, 0xa5220002, 0x3c020800,
-	0x8c4223fc, 0x1040001a, 0x31e3ffff, 0x8dc70010, 0x3c020800, 0x94421b86,
-	0x00e04021, 0x00072c02, 0x00aa2021, 0x00431023, 0x00823823, 0x00072402,
-	0x30e2ffff, 0x00823821, 0x00071027, 0xa522000a, 0x3102ffff, 0x3c040800,
-	0x948423c4, 0x00453023, 0x00e02821, 0x00641823, 0x006d1821, 0x00c33021,
-	0x00061c02, 0x30c2ffff, 0x0a00047f, 0x00623021, 0x01203821, 0x00004021,
-	0x3082ffff, 0x00021042, 0x18400008, 0x00003021, 0x00401821, 0x94e20000,
-	0x25080001, 0x00c23021, 0x0103102a, 0x1440fffb, 0x24e70002, 0x00061c02,
-	0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c02821, 0x00061027,
-	0xa522000a, 0x00003021, 0x2527000c, 0x00004021, 0x94e20000, 0x25080001,
-	0x00c23021, 0x2d020004, 0x1440fffb, 0x24e70002, 0x95220002, 0x00004021,
-	0x91230009, 0x00442023, 0x01803821, 0x3082ffff, 0xa4e00010, 0x3c040800,
-	0x948423c4, 0x00621821, 0x00c33021, 0x00061c02, 0x30c2ffff, 0x00623021,
-	0x00061c02, 0x3c020800, 0x944223c0, 0x00c34821, 0x00441023, 0x00021fc2,
-	0x00431021, 0x00021043, 0x18400010, 0x00003021, 0x00402021, 0x94e20000,
-	0x24e70002, 0x00c23021, 0x30e2007f, 0x14400006, 0x25080001, 0x8d630000,
-	0x3c02007f, 0x3442ff80, 0x00625824, 0x25670008, 0x0104102a, 0x1440fff3,
-	0x00000000, 0x3c020800, 0x944223dc, 0x00c23021, 0x3122ffff, 0x00c23021,
-	0x00061c02, 0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c04021,
-	0x00061027, 0xa5820010, 0xadc00014, 0x0a00049f, 0xadc00000, 0x8dc70010,
-	0x00e04021, 0x11400007, 0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff,
-	0x00433021, 0x00061402, 0x00c22821, 0x00051027, 0xa522000a, 0x3c030800,
-	0x946323c4, 0x3102ffff, 0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02,
-	0x30c2ffff, 0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027,
-	0xa5820010, 0x3102ffff, 0x00051c00, 0x00431025, 0xadc20010, 0x3c020800,
-	0x8c4223e4, 0x10400002, 0x25e2fff2, 0xa5c20034, 0x3c020800, 0x8c4223d8,
-	0x3c040800, 0x8c8423d4, 0x24420001, 0x3c010800, 0xac2223d8, 0x3c020800,
-	0x8c421bb0, 0x3303ffff, 0x00832021, 0x3c010800, 0xac2423d4, 0x00431821,
-	0x0062102b, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223d4, 0x3c010800,
-	0xac231bb0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800, 0x24a51b86,
-	0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034, 0xafb40030,
-	0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000, 0x3c020800,
-	0x944223c0, 0x3c030800, 0x8c631ba0, 0x3c040800, 0x8c841b9c, 0x01221023,
-	0x0064182a, 0xa7a9001e, 0x106000bc, 0xa7a20016, 0x24be0022, 0x97b6001e,
-	0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000, 0x8fc2fff8,
-	0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000ae, 0x00000000,
-	0x97d50818, 0x32a2ffff, 0x104000a1, 0x00009021, 0x0040a021, 0x00008821,
-	0x0e000621, 0x00000000, 0x00403021, 0x14c00007, 0x00000000, 0x3c020800,
-	0x8c4223cc, 0x24420001, 0x3c010800, 0x0a000593, 0xac2223cc, 0x3c100800,
-	0x02118021, 0x8e101bb8, 0x9608000a, 0x31020040, 0x10400004, 0x2407180c,
-	0x8e02000c, 0x2407188c, 0xacc20018, 0x31020080, 0x54400001, 0x34e70010,
-	0x3c020800, 0x00511021, 0x8c421bc0, 0x3c030800, 0x00711821, 0x8c631bc4,
-	0x00021500, 0x00031c00, 0x00431025, 0xacc20014, 0x96040008, 0x3242ffff,
-	0x00821021, 0x0282102a, 0x14400002, 0x02b22823, 0x00802821, 0x8e020000,
-	0x02459021, 0xacc20000, 0x8e020004, 0x00c02021, 0x26310010, 0xac820004,
-	0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010, 0x24020305, 0x0e00059f,
-	0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc6, 0x3242ffff, 0x0a00058b,
-	0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a, 0x10400066, 0x00000000,
-	0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021, 0x0e000621, 0x8e101bb8,
-	0x00403021, 0x14c00005, 0x00000000, 0x8e62082c, 0x24420001, 0x0a000593,
-	0xae62082c, 0x9608000a, 0x31020040, 0x10400004, 0x2407180c, 0x8e02000c,
-	0x2407188c, 0xacc20018, 0x3c020800, 0x00511021, 0x8c421bc0, 0x3c030800,
-	0x00711821, 0x8c631bc4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014,
-	0x8e63fff4, 0x96020008, 0x00432023, 0x3242ffff, 0x3083ffff, 0x00431021,
-	0x02c2102a, 0x10400003, 0x00802821, 0x97a9001e, 0x01322823, 0x8e620000,
-	0x30a4ffff, 0x00441021, 0xae620000, 0xa4c5000e, 0x8e020000, 0xacc20000,
-	0x8e020004, 0x8e63fff4, 0x00431021, 0xacc20004, 0x8e63fff4, 0x96020008,
-	0x00641821, 0x0062102a, 0x14400006, 0x02459021, 0x8e62fff0, 0xae60fff4,
-	0x24420001, 0x0a00056e, 0xae62fff0, 0xae63fff4, 0xacc00008, 0x3242ffff,
-	0x10560003, 0x31020004, 0x10400006, 0x24020305, 0x31020080, 0x54400001,
-	0x34e70010, 0x34e70020, 0x24020905, 0xa4c2000c, 0x8ee30000, 0x8ee20004,
-	0x14620007, 0x3c02b49a, 0x8ee20860, 0x54400001, 0x34e70400, 0x3c024b65,
-	0x0a000585, 0x34427654, 0x344289ab, 0xacc2001c, 0x30e2ffff, 0xacc20010,
-	0x0e00059f, 0x00c02021, 0x3242ffff, 0x0056102b, 0x1440ff9c, 0x00000000,
-	0x8e620000, 0x8e63fffc, 0x0043102a, 0x1440ff4a, 0x00000000, 0x8fbf0044,
-	0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034, 0x8fb40030, 0x8fb3002c,
-	0x8fb20028, 0x8fb10024, 0x8fb00020, 0x03e00008, 0x27bd0048, 0x27bdffe8,
-	0xafbf0014, 0xafb00010, 0x8f624450, 0x8f634410, 0x0a0005ae, 0x00808021,
-	0x8f626820, 0x30422000, 0x10400003, 0x00000000, 0x0e0001ef, 0x00002021,
-	0x8f624450, 0x8f634410, 0x3042ffff, 0x0043102b, 0x1440fff5, 0x00000000,
-	0x8f630c14, 0x3063000f, 0x2c620002, 0x1440000b, 0x00000000, 0x8f630c14,
-	0x3c020800, 0x8c421b30, 0x3063000f, 0x24420001, 0x3c010800, 0xac221b30,
-	0x2c620002, 0x1040fff7, 0x00000000, 0xaf705c18, 0x8f625c10, 0x30420002,
-	0x10400009, 0x00000000, 0x8f626820, 0x30422000, 0x1040fff8, 0x00000000,
-	0x0e0001ef, 0x00002021, 0x0a0005c1, 0x00000000, 0x8fbf0014, 0x8fb00010,
-	0x03e00008, 0x27bd0018, 0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000,
-	0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804,
-	0x8f634000, 0x24020b50, 0x3c010800, 0xac221b44, 0x24020b78, 0x3c010800,
-	0xac221b54, 0x34630002, 0xaf634000, 0x0e000601, 0x00808021, 0x3c010800,
-	0xa0221b58, 0x304200ff, 0x24030002, 0x14430005, 0x00000000, 0x3c020800,
-	0x8c421b44, 0x0a0005f4, 0xac5000c0, 0x3c020800, 0x8c421b44, 0xac5000bc,
-	0x8f624434, 0x8f634438, 0x8f644410, 0x3c010800, 0xac221b4c, 0x3c010800,
-	0xac231b5c, 0x3c010800, 0xac241b48, 0x8fbf0014, 0x8fb00010, 0x03e00008,
-	0x27bd0018, 0x3c040800, 0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003,
-	0xac830000, 0x8cc20000, 0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa,
-	0xac830000, 0x8cc20000, 0x50430001, 0x24050001, 0x3c020800, 0xac470000,
-	0x03e00008, 0x00a01021, 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c,
-	0x8f62680c, 0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9,
-	0x00000000, 0x03e00008, 0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b4c,
-	0x00031c02, 0x0043102b, 0x14400008, 0x3c038000, 0x3c040800, 0x8c841b5c,
-	0x8f624450, 0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444,
-	0x8f624444, 0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008,
-	0x3042ffff, 0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000,
-	0x0a000644, 0x2402ffff, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002,
-	0x1440fffc, 0x00001021, 0x03e00008, 0x00000000, 0x8f624450, 0x3c030800,
-	0x8c631b48, 0x0a00064d, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b,
-	0x1440fffc, 0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821,
-	0x3c040800, 0x24841ae0, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010,
-	0x0e000678, 0xafa00014, 0x0a00065c, 0x00000000, 0x8fbf0018, 0x03e00008,
-	0x27bd0020, 0x00000000, 0x00000000, 0x00000000, 0x3c020800, 0x34423000,
-	0x3c030800, 0x34633000, 0x3c040800, 0x348437ff, 0x3c010800, 0xac221b64,
-	0x24020040, 0x3c010800, 0xac221b68, 0x3c010800, 0xac201b60, 0xac600000,
-	0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
-	0x00804821, 0x8faa0010, 0x3c020800, 0x8c421b60, 0x3c040800, 0x8c841b68,
-	0x8fab0014, 0x24430001, 0x0044102b, 0x3c010800, 0xac231b60, 0x14400003,
-	0x00004021, 0x3c010800, 0xac201b60, 0x3c020800, 0x8c421b60, 0x3c030800,
-	0x8c631b64, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
-	0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b60,
-	0x3c030800, 0x8c631b64, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008,
-	0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
-	0x00000000, 0x00000000,
+	0x00625824, 0x25670008, 0x0104102a, 0x1440fff3, 0x00000000, 0x3c020800,
+	0x944223ec, 0x00c23021, 0x3122ffff, 0x00c23021, 0x00061c02, 0x30c2ffff,
+	0x00623021, 0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010,
+	0xadc00014, 0x0a00049d, 0xadc00000, 0x8dc70010, 0x00e04021, 0x11400007,
+	0x00072c02, 0x00aa3021, 0x00061402, 0x30c3ffff, 0x00433021, 0x00061402,
+	0x00c22821, 0x00051027, 0xa522000a, 0x3c030800, 0x946323d4, 0x3102ffff,
+	0x01e21021, 0x00433023, 0x00cd3021, 0x00061c02, 0x30c2ffff, 0x00623021,
+	0x00061402, 0x00c23021, 0x00c04021, 0x00061027, 0xa5820010, 0x3102ffff,
+	0x00051c00, 0x00431025, 0xadc20010, 0x3c020800, 0x8c4223f4, 0x10400005,
+	0x2de205eb, 0x14400002, 0x25e2fff2, 0x34028870, 0xa5c20034, 0x3c030800,
+	0x246323e8, 0x8c620000, 0x24420001, 0xac620000, 0x3c040800, 0x8c8423e4,
+	0x3c020800, 0x8c421bc0, 0x3303ffff, 0x00832021, 0x00431821, 0x0062102b,
+	0x3c010800, 0xac2423e4, 0x10400003, 0x2482ffff, 0x3c010800, 0xac2223e4,
+	0x3c010800, 0xac231bc0, 0x03e00008, 0x27bd0020, 0x27bdffb8, 0x3c050800,
+	0x24a51b96, 0xafbf0044, 0xafbe0040, 0xafb7003c, 0xafb60038, 0xafb50034,
+	0xafb40030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x94a90000,
+	0x3c020800, 0x944223d0, 0x3c030800, 0x8c631bb0, 0x3c040800, 0x8c841bac,
+	0x01221023, 0x0064182a, 0xa7a9001e, 0x106000be, 0xa7a20016, 0x24be0022,
+	0x97b6001e, 0x24b3001a, 0x24b70016, 0x8fc20000, 0x14400008, 0x00000000,
+	0x8fc2fff8, 0x97a30016, 0x8fc4fff4, 0x00431021, 0x0082202a, 0x148000b0,
+	0x00000000, 0x97d50818, 0x32a2ffff, 0x104000a3, 0x00009021, 0x0040a021,
+	0x00008821, 0x0e000625, 0x00000000, 0x00403021, 0x14c00007, 0x00000000,
+	0x3c020800, 0x8c4223dc, 0x24420001, 0x3c010800, 0x0a000596, 0xac2223dc,
+	0x3c100800, 0x02118021, 0x8e101bc8, 0x9608000a, 0x31020040, 0x10400005,
+	0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x31020080,
+	0x54400001, 0x34e70010, 0x3c020800, 0x00511021, 0x8c421bd0, 0x3c030800,
+	0x00711821, 0x8c631bd4, 0x00021500, 0x00031c00, 0x00431025, 0xacc20014,
+	0x96040008, 0x3242ffff, 0x00821021, 0x0282102a, 0x14400002, 0x02b22823,
+	0x00802821, 0x8e020000, 0x02459021, 0xacc20000, 0x8e020004, 0x00c02021,
+	0x26310010, 0xac820004, 0x30e2ffff, 0xac800008, 0xa485000e, 0xac820010,
+	0x24020305, 0x0e0005a2, 0xa482000c, 0x3242ffff, 0x0054102b, 0x1440ffc5,
+	0x3242ffff, 0x0a00058e, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
+	0x10400067, 0x00000000, 0x8e62fff0, 0x00028900, 0x3c100800, 0x02118021,
+	0x0e000625, 0x8e101bc8, 0x00403021, 0x14c00005, 0x00000000, 0x8e62082c,
+	0x24420001, 0x0a000596, 0xae62082c, 0x9608000a, 0x31020040, 0x10400005,
+	0x2407180c, 0x8e02000c, 0x2407188c, 0x00021400, 0xacc20018, 0x3c020800,
+	0x00511021, 0x8c421bd0, 0x3c030800, 0x00711821, 0x8c631bd4, 0x00021500,
+	0x00031c00, 0x00431025, 0xacc20014, 0x8e63fff4, 0x96020008, 0x00432023,
+	0x3242ffff, 0x3083ffff, 0x00431021, 0x02c2102a, 0x10400003, 0x00802821,
+	0x97a9001e, 0x01322823, 0x8e620000, 0x30a4ffff, 0x00441021, 0xae620000,
+	0xa4c5000e, 0x8e020000, 0xacc20000, 0x8e020004, 0x8e63fff4, 0x00431021,
+	0xacc20004, 0x8e63fff4, 0x96020008, 0x00641821, 0x0062102a, 0x14400006,
+	0x02459021, 0x8e62fff0, 0xae60fff4, 0x24420001, 0x0a000571, 0xae62fff0,
+	0xae63fff4, 0xacc00008, 0x3242ffff, 0x10560003, 0x31020004, 0x10400006,
+	0x24020305, 0x31020080, 0x54400001, 0x34e70010, 0x34e70020, 0x24020905,
+	0xa4c2000c, 0x8ee30000, 0x8ee20004, 0x14620007, 0x3c02b49a, 0x8ee20860,
+	0x54400001, 0x34e70400, 0x3c024b65, 0x0a000588, 0x34427654, 0x344289ab,
+	0xacc2001c, 0x30e2ffff, 0xacc20010, 0x0e0005a2, 0x00c02021, 0x3242ffff,
+	0x0056102b, 0x1440ff9b, 0x00000000, 0x8e620000, 0x8e63fffc, 0x0043102a,
+	0x1440ff48, 0x00000000, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038,
+	0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+	0x03e00008, 0x27bd0048, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f624450,
+	0x8f634410, 0x0a0005b1, 0x00808021, 0x8f626820, 0x30422000, 0x10400003,
+	0x00000000, 0x0e0001f0, 0x00002021, 0x8f624450, 0x8f634410, 0x3042ffff,
+	0x0043102b, 0x1440fff5, 0x00000000, 0x8f630c14, 0x3063000f, 0x2c620002,
+	0x1440000b, 0x00000000, 0x8f630c14, 0x3c020800, 0x8c421b40, 0x3063000f,
+	0x24420001, 0x3c010800, 0xac221b40, 0x2c620002, 0x1040fff7, 0x00000000,
+	0xaf705c18, 0x8f625c10, 0x30420002, 0x10400009, 0x00000000, 0x8f626820,
+	0x30422000, 0x1040fff8, 0x00000000, 0x0e0001f0, 0x00002021, 0x0a0005c4,
+	0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000,
+	0x00000000, 0x00000000, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010,
+	0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50,
+	0x3c010800, 0xac221b54, 0x24020b78, 0x3c010800, 0xac221b64, 0x34630002,
+	0xaf634000, 0x0e000605, 0x00808021, 0x3c010800, 0xa0221b68, 0x304200ff,
+	0x24030002, 0x14430005, 0x00000000, 0x3c020800, 0x8c421b54, 0x0a0005f8,
+	0xac5000c0, 0x3c020800, 0x8c421b54, 0xac5000bc, 0x8f624434, 0x8f634438,
+	0x8f644410, 0x3c010800, 0xac221b5c, 0x3c010800, 0xac231b6c, 0x3c010800,
+	0xac241b58, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c040800,
+	0x8c870000, 0x3c03aa55, 0x3463aa55, 0x3c06c003, 0xac830000, 0x8cc20000,
+	0x14430007, 0x24050002, 0x3c0355aa, 0x346355aa, 0xac830000, 0x8cc20000,
+	0x50430001, 0x24050001, 0x3c020800, 0xac470000, 0x03e00008, 0x00a01021,
+	0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe,
+	0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008,
+	0x27bd0008, 0x8f634450, 0x3c020800, 0x8c421b5c, 0x00031c02, 0x0043102b,
+	0x14400008, 0x3c038000, 0x3c040800, 0x8c841b6c, 0x8f624450, 0x00021c02,
+	0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024,
+	0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff,
+	0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0a000648, 0x2402ffff,
+	0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021,
+	0x03e00008, 0x00000000, 0x8f624450, 0x3c030800, 0x8c631b58, 0x0a000651,
+	0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000,
+	0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040800, 0x24841af0,
+	0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0e00067c, 0xafa00014,
+	0x0a000660, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x00000000,
+	0x00000000, 0x00000000, 0x3c020800, 0x34423000, 0x3c030800, 0x34633000,
+	0x3c040800, 0x348437ff, 0x3c010800, 0xac221b74, 0x24020040, 0x3c010800,
+	0xac221b78, 0x3c010800, 0xac201b70, 0xac600000, 0x24630004, 0x0083102b,
+	0x5040fffd, 0xac600000, 0x03e00008, 0x00000000, 0x00804821, 0x8faa0010,
+	0x3c020800, 0x8c421b70, 0x3c040800, 0x8c841b78, 0x8fab0014, 0x24430001,
+	0x0044102b, 0x3c010800, 0xac231b70, 0x14400003, 0x00004021, 0x3c010800,
+	0xac201b70, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74, 0x91240000,
+	0x00021140, 0x00431021, 0x00481021, 0x25080001, 0xa0440000, 0x29020008,
+	0x1440fff4, 0x25290001, 0x3c020800, 0x8c421b70, 0x3c030800, 0x8c631b74,
+	0x8f64680c, 0x00021140, 0x00431021, 0xac440008, 0xac45000c, 0xac460010,
+	0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
 };
 
 u32 tg3TsoFwRodata[] = {
@@ -4134,201 +4402,200 @@ u32 tg3TsoFwRodata[] = {
 	0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f,
 	0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000,
 	0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000,
+	0x00000000,
 };
 
-#if 0 /* All zeros, don't eat up space with it. */
 u32 tg3TsoFwData[] = {
+	0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000,
 	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000
+	0x00000000,
 };
-#endif
 
 /* 5705 needs a special version of the TSO firmware.  */
 #define TG3_TSO5_FW_RELEASE_MAJOR	0x1
-#define TG3_TSO5_FW_RELASE_MINOR	0x1
+#define TG3_TSO5_FW_RELASE_MINOR	0x2
 #define TG3_TSO5_FW_RELEASE_FIX		0x0
 #define TG3_TSO5_FW_START_ADDR		0x00010000
 #define TG3_TSO5_FW_TEXT_ADDR		0x00010000
-#define TG3_TSO5_FW_TEXT_LEN		0xeb0
-#define TG3_TSO5_FW_RODATA_ADDR		0x00010eb0
+#define TG3_TSO5_FW_TEXT_LEN		0xe90
+#define TG3_TSO5_FW_RODATA_ADDR		0x00010e90
 #define TG3_TSO5_FW_RODATA_LEN		0x50
-#define TG3_TSO5_FW_DATA_ADDR		0x00010f20
+#define TG3_TSO5_FW_DATA_ADDR		0x00010f00
 #define TG3_TSO5_FW_DATA_LEN		0x20
-#define TG3_TSO5_FW_SBSS_ADDR		0x00010f40
+#define TG3_TSO5_FW_SBSS_ADDR		0x00010f20
 #define TG3_TSO5_FW_SBSS_LEN		0x28
-#define TG3_TSO5_FW_BSS_ADDR		0x00010f70
+#define TG3_TSO5_FW_BSS_ADDR		0x00010f50
 #define TG3_TSO5_FW_BSS_LEN		0x88
 
-static u32 tg3Tso5FwText[] = {
-	0x0c004003, 0x00000000, 0x00010f30, 0x00000000, 0x10000003, 0x00000000,
+static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = {
+	0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000,
 	0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001,
 	0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe,
-	0xafbf0018, 0x0c0042f0, 0x34840002, 0x0c00436c, 0x00000000, 0x3c030001,
-	0x90630f54, 0x24020002, 0x3c040001, 0x24840ebc, 0x14620003, 0x24050001,
-	0x3c040001, 0x24840eb0, 0x24060001, 0x00003821, 0xafa00010, 0x0c004380,
+	0xafbf0018, 0x0c0042e8, 0x34840002, 0x0c004364, 0x00000000, 0x3c030001,
+	0x90630f34, 0x24020002, 0x3c040001, 0x24840e9c, 0x14620003, 0x24050001,
+	0x3c040001, 0x24840e90, 0x24060002, 0x00003821, 0xafa00010, 0x0c004378,
 	0xafa00014, 0x0c00402c, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020,
 	0x00000000, 0x00000000, 0x27bdffe0, 0xafbf001c, 0xafb20018, 0xafb10014,
-	0x0c0042d3, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400,
+	0x0c0042d4, 0xafb00010, 0x3c128000, 0x24110001, 0x8f706810, 0x32020400,
 	0x10400007, 0x00000000, 0x8f641008, 0x00921024, 0x14400003, 0x00000000,
-	0x0c004064, 0x00000000, 0x3c020001, 0x90420f76, 0x10510003, 0x32020200,
+	0x0c004064, 0x00000000, 0x3c020001, 0x90420f56, 0x10510003, 0x32020200,
 	0x1040fff1, 0x00000000, 0x0c0041b4, 0x00000000, 0x08004034, 0x00000000,
 	0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-	0x27bdffe0, 0x3c040001, 0x24840ed0, 0x00002821, 0x00003021, 0x00003821,
-	0xafbf0018, 0xafa00010, 0x0c004380, 0xafa00014, 0x0000d021, 0x24020130,
-	0xaf625000, 0x3c010001, 0xa4200f70, 0x3c010001, 0xa0200f77, 0x8fbf0018,
-	0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f80,
+	0x27bdffe0, 0x3c040001, 0x24840eb0, 0x00002821, 0x00003021, 0x00003821,
+	0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0000d021, 0x24020130,
+	0xaf625000, 0x3c010001, 0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018,
+	0x03e00008, 0x27bd0020, 0x00000000, 0x00000000, 0x3c030001, 0x24630f60,
 	0x90620000, 0x27bdfff0, 0x14400003, 0x0080c021, 0x08004073, 0x00004821,
 	0x3c022000, 0x03021024, 0x10400003, 0x24090002, 0x08004073, 0xa0600000,
 	0x24090001, 0x00181040, 0x30431f80, 0x346f8008, 0x1520004b, 0x25eb0028,
-	0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f9a, 0x00041402,
-	0xa0a20000, 0x3c010001, 0xa0240f9b, 0x3c020001, 0x00431021, 0x94428014,
-	0x3c010001, 0xa0220f9c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff,
-	0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f80, 0x0124102b,
+	0x3c040001, 0x00832021, 0x8c848010, 0x3c050001, 0x24a50f7a, 0x00041402,
+	0xa0a20000, 0x3c010001, 0xa0240f7b, 0x3c020001, 0x00431021, 0x94428014,
+	0x3c010001, 0xa0220f7c, 0x3c0c0001, 0x01836021, 0x8d8c8018, 0x304200ff,
+	0x24420008, 0x000220c3, 0x24020001, 0x3c010001, 0xa0220f60, 0x0124102b,
 	0x1040000c, 0x00003821, 0x24a6000e, 0x01602821, 0x8ca20000, 0x8ca30004,
 	0x24a50008, 0x24e70001, 0xacc20000, 0xacc30004, 0x00e4102b, 0x1440fff8,
-	0x24c60008, 0x00003821, 0x3c080001, 0x25080f9b, 0x91060000, 0x3c020001,
-	0x90420f9c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021,
+	0x24c60008, 0x00003821, 0x3c080001, 0x25080f7b, 0x91060000, 0x3c020001,
+	0x90420f7c, 0x2503000d, 0x00c32821, 0x00461023, 0x00021fc2, 0x00431021,
 	0x00021043, 0x1840000c, 0x00002021, 0x91020001, 0x00461023, 0x00021fc2,
 	0x00431021, 0x00021843, 0x94a20000, 0x24e70001, 0x00822021, 0x00e3102a,
 	0x1440fffb, 0x24a50002, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
 	0x00822021, 0x3c02ffff, 0x01821024, 0x3083ffff, 0x00431025, 0x3c010001,
-	0x080040fa, 0xac220fa0, 0x3c050001, 0x24a50f9c, 0x90a20000, 0x3c0c0001,
+	0x080040fa, 0xac220f80, 0x3c050001, 0x24a50f7c, 0x90a20000, 0x3c0c0001,
 	0x01836021, 0x8d8c8018, 0x000220c2, 0x1080000e, 0x00003821, 0x01603021,
 	0x24a5000c, 0x8ca20000, 0x8ca30004, 0x24a50008, 0x24e70001, 0xacc20000,
-	0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f9c,
+	0xacc30004, 0x00e4102b, 0x1440fff8, 0x24c60008, 0x3c050001, 0x24a50f7c,
 	0x90a20000, 0x30430007, 0x24020004, 0x10620011, 0x28620005, 0x10400005,
 	0x24020002, 0x10620008, 0x000710c0, 0x080040fa, 0x00000000, 0x24020006,
 	0x1062000e, 0x000710c0, 0x080040fa, 0x00000000, 0x00a21821, 0x9463000c,
 	0x004b1021, 0x080040fa, 0xa4430000, 0x000710c0, 0x00a21821, 0x8c63000c,
 	0x004b1021, 0x080040fa, 0xac430000, 0x00a21821, 0x8c63000c, 0x004b2021,
 	0x00a21021, 0xac830000, 0x94420010, 0xa4820004, 0x95e70006, 0x3c020001,
-	0x90420f9c, 0x3c030001, 0x90630f9a, 0x00e2c823, 0x3c020001, 0x90420f9b,
+	0x90420f7c, 0x3c030001, 0x90630f7a, 0x00e2c823, 0x3c020001, 0x90420f7b,
 	0x24630028, 0x01e34021, 0x24420028, 0x15200012, 0x01e23021, 0x94c2000c,
-	0x3c010001, 0xa4220f98, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f96,
-	0x3c010001, 0xa4200f92, 0x00021400, 0x00431025, 0x3c010001, 0xac220f8c,
-	0x95020004, 0x3c010001, 0x08004124, 0xa4220f90, 0x3c020001, 0x94420f90,
-	0x3c030001, 0x94630f92, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f8c,
-	0xa4c20004, 0x3c020001, 0x8c420f8c, 0xa4c20006, 0x3c040001, 0x94840f92,
-	0x3c020001, 0x94420f90, 0x3c0a0001, 0x954a0f96, 0x00441821, 0x3063ffff,
-	0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f98,
-	0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f98,
+	0x3c010001, 0xa4220f78, 0x94c20004, 0x94c30006, 0x3c010001, 0xa4200f76,
+	0x3c010001, 0xa4200f72, 0x00021400, 0x00431025, 0x3c010001, 0xac220f6c,
+	0x95020004, 0x3c010001, 0x08004124, 0xa4220f70, 0x3c020001, 0x94420f70,
+	0x3c030001, 0x94630f72, 0x00431021, 0xa5020004, 0x3c020001, 0x94420f6c,
+	0xa4c20004, 0x3c020001, 0x8c420f6c, 0xa4c20006, 0x3c040001, 0x94840f72,
+	0x3c020001, 0x94420f70, 0x3c0a0001, 0x954a0f76, 0x00441821, 0x3063ffff,
+	0x0062182a, 0x24020002, 0x1122000b, 0x00832023, 0x3c030001, 0x94630f78,
+	0x30620009, 0x10400006, 0x3062fff6, 0xa4c2000c, 0x3c020001, 0x94420f78,
 	0x30420009, 0x01425023, 0x24020001, 0x1122001b, 0x29220002, 0x50400005,
 	0x24020002, 0x11200007, 0x31a2ffff, 0x08004197, 0x00000000, 0x1122001d,
-	0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0fa0, 0x10800005,
+	0x24020016, 0x08004197, 0x31a2ffff, 0x3c0e0001, 0x95ce0f80, 0x10800005,
 	0x01806821, 0x01c42021, 0x00041c02, 0x3082ffff, 0x00627021, 0x000e1027,
-	0xa502000a, 0x3c030001, 0x90630f9b, 0x31a2ffff, 0x00e21021, 0x0800418d,
-	0x00432023, 0x3c020001, 0x94420fa0, 0x00442021, 0x00041c02, 0x3082ffff,
+	0xa502000a, 0x3c030001, 0x90630f7b, 0x31a2ffff, 0x00e21021, 0x0800418d,
+	0x00432023, 0x3c020001, 0x94420f80, 0x00442021, 0x00041c02, 0x3082ffff,
 	0x00622021, 0x00807021, 0x00041027, 0x08004185, 0xa502000a, 0x3c050001,
-	0x24a50f9a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000,
-	0x00e21023, 0xa5020002, 0x3c030001, 0x94630fa0, 0x3c020001, 0x94420f7a,
+	0x24a50f7a, 0x90a30000, 0x14620002, 0x24e2fff2, 0xa5e20034, 0x90a20000,
+	0x00e21023, 0xa5020002, 0x3c030001, 0x94630f80, 0x3c020001, 0x94420f5a,
 	0x30e5ffff, 0x00641821, 0x00451023, 0x00622023, 0x00041c02, 0x3082ffff,
-	0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f9c, 0x24620001,
+	0x00622021, 0x00041027, 0xa502000a, 0x3c030001, 0x90630f7c, 0x24620001,
 	0x14a20005, 0x00807021, 0x01631021, 0x90420000, 0x08004185, 0x00026200,
 	0x24620002, 0x14a20003, 0x306200fe, 0x004b1021, 0x944c0000, 0x3c020001,
-	0x94420fa2, 0x3183ffff, 0x3c040001, 0x90840f9b, 0x00431021, 0x00e21021,
+	0x94420f82, 0x3183ffff, 0x3c040001, 0x90840f7b, 0x00431021, 0x00e21021,
 	0x00442023, 0x008a2021, 0x00041c02, 0x3082ffff, 0x00622021, 0x00041402,
 	0x00822021, 0x00806821, 0x00041027, 0xa4c20010, 0x31a2ffff, 0x000e1c00,
-	0x00431025, 0x3c040001, 0x24840f92, 0xade20010, 0x94820000, 0x3c050001,
-	0x94a50f96, 0x3c030001, 0x8c630f8c, 0x24420001, 0x00b92821, 0xa4820000,
-	0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f96, 0x10600003,
-	0x24a2ffff, 0x3c010001, 0xa4220f96, 0x3c024000, 0x03021025, 0x3c010001,
-	0xac240f8c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f76,
+	0x00431025, 0x3c040001, 0x24840f72, 0xade20010, 0x94820000, 0x3c050001,
+	0x94a50f76, 0x3c030001, 0x8c630f6c, 0x24420001, 0x00b92821, 0xa4820000,
+	0x3322ffff, 0x00622021, 0x0083182b, 0x3c010001, 0xa4250f76, 0x10600003,
+	0x24a2ffff, 0x3c010001, 0xa4220f76, 0x3c024000, 0x03021025, 0x3c010001,
+	0xac240f6c, 0xaf621008, 0x03e00008, 0x27bd0010, 0x3c030001, 0x90630f56,
 	0x27bdffe8, 0x24020001, 0xafbf0014, 0x10620026, 0xafb00010, 0x8f620cf4,
-	0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f84,
+	0x2442ffff, 0x3042007f, 0x00021100, 0x8c434000, 0x3c010001, 0xac230f64,
 	0x8c434008, 0x24444000, 0x8c5c4004, 0x30620040, 0x14400002, 0x24020088,
-	0x24020008, 0x3c010001, 0xa4220f88, 0x30620004, 0x10400005, 0x24020001,
-	0x3c010001, 0xa0220f77, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f77,
-	0x00031402, 0x3c010001, 0xa4220f74, 0x9483000c, 0x24020001, 0x3c010001,
-	0xa4200f70, 0x3c010001, 0xa0220f76, 0x3c010001, 0xa4230f82, 0x24020001,
+	0x24020008, 0x3c010001, 0xa4220f68, 0x30620004, 0x10400005, 0x24020001,
+	0x3c010001, 0xa0220f57, 0x080041d5, 0x00031402, 0x3c010001, 0xa0200f57,
+	0x00031402, 0x3c010001, 0xa4220f54, 0x9483000c, 0x24020001, 0x3c010001,
+	0xa4200f50, 0x3c010001, 0xa0220f56, 0x3c010001, 0xa4230f62, 0x24020001,
 	0x1342001e, 0x00000000, 0x13400005, 0x24020003, 0x13420067, 0x00000000,
-	0x080042cf, 0x00000000, 0x3c020001, 0x94420f82, 0x241a0001, 0x3c010001,
-	0xa4200f7e, 0x3c010001, 0xa4200f72, 0x304407ff, 0x00021bc2, 0x00031823,
+	0x080042cf, 0x00000000, 0x3c020001, 0x94420f62, 0x241a0001, 0x3c010001,
+	0xa4200f5e, 0x3c010001, 0xa4200f52, 0x304407ff, 0x00021bc2, 0x00031823,
 	0x3063003e, 0x34630036, 0x00021242, 0x3042003c, 0x00621821, 0x3c010001,
-	0xa4240f78, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f7a, 0x3c010001,
-	0xa4230f7c, 0x3c060001, 0x24c60f72, 0x94c50000, 0x94c30002, 0x3c040001,
-	0x94840f7a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021,
-	0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f76, 0x8f641008,
+	0xa4240f58, 0x00832021, 0x24630030, 0x3c010001, 0xa4240f5a, 0x3c010001,
+	0xa4230f5c, 0x3c060001, 0x24c60f52, 0x94c50000, 0x94c30002, 0x3c040001,
+	0x94840f5a, 0x00651021, 0x0044102a, 0x10400013, 0x3c108000, 0x00a31021,
+	0xa4c20000, 0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008,
 	0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4,
 	0x00501024, 0x104000b7, 0x00000000, 0x0800420f, 0x00000000, 0x3c030001,
-	0x94630f70, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001,
-	0xa4230f70, 0xaf620ce8, 0x3c020001, 0x94420f88, 0x34420024, 0xaf620cec,
-	0x94c30002, 0x3c020001, 0x94420f70, 0x14620012, 0x3c028000, 0x3c108000,
-	0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f76, 0x8f641008, 0x00901024,
+	0x94630f50, 0x00851023, 0xa4c40000, 0x00621821, 0x3042ffff, 0x3c010001,
+	0xa4230f50, 0xaf620ce8, 0x3c020001, 0x94420f68, 0x34420024, 0xaf620cec,
+	0x94c30002, 0x3c020001, 0x94420f50, 0x14620012, 0x3c028000, 0x3c108000,
+	0x3c02a000, 0xaf620cf4, 0x3c010001, 0xa0200f56, 0x8f641008, 0x00901024,
 	0x14400003, 0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024,
 	0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003, 0xaf620cf4, 0x3c108000,
 	0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064, 0x00000000,
 	0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x080042cf, 0x241a0003,
-	0x3c070001, 0x24e70f70, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001,
-	0x8c420f84, 0xaf620ce4, 0x3c050001, 0x94a50f74, 0x94e30000, 0x3c040001,
-	0x94840f78, 0x3c020001, 0x94420f7e, 0x00a32823, 0x00822023, 0x30a6ffff,
-	0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f7c,
-	0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f74,
+	0x3c070001, 0x24e70f50, 0x94e20000, 0x03821021, 0xaf620ce0, 0x3c020001,
+	0x8c420f64, 0xaf620ce4, 0x3c050001, 0x94a50f54, 0x94e30000, 0x3c040001,
+	0x94840f58, 0x3c020001, 0x94420f5e, 0x00a32823, 0x00822023, 0x30a6ffff,
+	0x3083ffff, 0x00c3102b, 0x14400043, 0x00000000, 0x3c020001, 0x94420f5c,
+	0x00021400, 0x00621025, 0xaf620ce8, 0x94e20000, 0x3c030001, 0x94630f54,
 	0x00441021, 0xa4e20000, 0x3042ffff, 0x14430021, 0x3c020008, 0x3c020001,
-	0x90420f77, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f88, 0x34630624,
-	0x0800427c, 0x0000d021, 0x3c020001, 0x94420f88, 0x3c030008, 0x34630624,
+	0x90420f57, 0x10400006, 0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624,
+	0x0800427c, 0x0000d021, 0x3c020001, 0x94420f68, 0x3c030008, 0x34630624,
 	0x00431025, 0xaf620cec, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
-	0xa0200f76, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
+	0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
 	0x00000000, 0x8f620cf4, 0x00501024, 0x10400015, 0x00000000, 0x08004283,
-	0x00000000, 0x3c030001, 0x94630f88, 0x34420624, 0x3c108000, 0x00621825,
+	0x00000000, 0x3c030001, 0x94630f68, 0x34420624, 0x3c108000, 0x00621825,
 	0x3c028000, 0xaf630cec, 0xaf620cf4, 0x8f641008, 0x00901024, 0x14400003,
 	0x00000000, 0x0c004064, 0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7,
-	0x00000000, 0x3c010001, 0x080042cf, 0xa4200f7e, 0x3c020001, 0x94420f7c,
-	0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f77, 0x10400009,
-	0x3c03000c, 0x3c020001, 0x94420f88, 0x34630624, 0x0000d021, 0x00431025,
-	0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f88, 0x3c030008,
-	0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f7e, 0x00451021,
-	0x3c010001, 0xa4220f7e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
-	0xa0200f76, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
+	0x00000000, 0x3c010001, 0x080042cf, 0xa4200f5e, 0x3c020001, 0x94420f5c,
+	0x00021400, 0x00c21025, 0xaf620ce8, 0x3c020001, 0x90420f57, 0x10400009,
+	0x3c03000c, 0x3c020001, 0x94420f68, 0x34630624, 0x0000d021, 0x00431025,
+	0xaf620cec, 0x080042c1, 0x3c108000, 0x3c020001, 0x94420f68, 0x3c030008,
+	0x34630604, 0x00431025, 0xaf620cec, 0x3c020001, 0x94420f5e, 0x00451021,
+	0x3c010001, 0xa4220f5e, 0x3c108000, 0x3c02a000, 0xaf620cf4, 0x3c010001,
+	0xa0200f56, 0x8f641008, 0x00901024, 0x14400003, 0x00000000, 0x0c004064,
 	0x00000000, 0x8f620cf4, 0x00501024, 0x1440fff7, 0x00000000, 0x8fbf0014,
-	0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0x3c040001, 0x24840ee0,
-	0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004380,
-	0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001, 0xa4200f70,
-	0x3c010001, 0xa0200f77, 0x8f636804, 0x3c020001, 0x3442e000, 0x00621824,
-	0x3c020001, 0x14620003, 0x00000000, 0x080042eb, 0x00000000, 0x8fbf0018,
-	0x03e00008, 0x27bd0020, 0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010,
-	0xaf60680c, 0x8f626804, 0x34420082, 0xaf626804, 0x8f634000, 0x24020b50,
-	0x3c010001, 0xac220f40, 0x24020b78, 0x3c010001, 0xac220f50, 0x34630002,
-	0xaf634000, 0x0c00431d, 0x00808021, 0x3c010001, 0xa0220f54, 0x304200ff,
-	0x24030002, 0x14430005, 0x00000000, 0x3c020001, 0x8c420f40, 0x08004310,
-	0xac5000c0, 0x3c020001, 0x8c420f40, 0xac5000bc, 0x8f624434, 0x8f634438,
-	0x8f644410, 0x3c010001, 0xac220f48, 0x3c010001, 0xac230f58, 0x3c010001,
-	0xac240f44, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008,
-	0x24020001, 0x27bdfff8, 0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c,
-	0x1043fffe, 0x00000000, 0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000,
-	0x03e00008, 0x27bd0008, 0x8f634450, 0x3c020001, 0x8c420f48, 0x00031c02,
-	0x0043102b, 0x14400008, 0x3c038000, 0x3c040001, 0x8c840f58, 0x8f624450,
-	0x00021c02, 0x0083102b, 0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444,
-	0x00431024, 0x1440fffd, 0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff,
-	0x3082ffff, 0x2442e000, 0x2c422001, 0x14400003, 0x3c024000, 0x0800434f,
-	0x2402ffff, 0x00822025, 0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc,
-	0x00001021, 0x03e00008, 0x00000000, 0x8f624450, 0x3c030001, 0x8c630f44,
-	0x08004358, 0x3042ffff, 0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc,
-	0x00000000, 0x03e00008, 0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001,
-	0x24840ef0, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010, 0x0c004380,
-	0xafa00014, 0x08004367, 0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020,
-	0x3c020001, 0x3442d600, 0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff,
-	0x3c010001, 0xac220f60, 0x24020040, 0x3c010001, 0xac220f64, 0x3c010001,
-	0xac200f5c, 0xac600000, 0x24630004, 0x0083102b, 0x5040fffd, 0xac600000,
-	0x03e00008, 0x00000000, 0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f5c,
-	0x3c040001, 0x8c840f64, 0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001,
-	0xac230f5c, 0x14400003, 0x00004021, 0x3c010001, 0xac200f5c, 0x3c020001,
-	0x8c420f5c, 0x3c030001, 0x8c630f60, 0x91240000, 0x00021140, 0x00431021,
-	0x00481021, 0x25080001, 0xa0440000, 0x29020008, 0x1440fff4, 0x25290001,
-	0x3c020001, 0x8c420f5c, 0x3c030001, 0x8c630f60, 0x8f64680c, 0x00021140,
-	0x00431021, 0xac440008, 0xac45000c, 0xac460010, 0xac470014, 0xac4a0018,
-	0x03e00008, 0xac4b001c, 0x00000000, 0x00000000,
+	0x8fb00010, 0x03e00008, 0x27bd0018, 0x00000000, 0x27bdffe0, 0x3c040001,
+	0x24840ec0, 0x00002821, 0x00003021, 0x00003821, 0xafbf0018, 0xafa00010,
+	0x0c004378, 0xafa00014, 0x0000d021, 0x24020130, 0xaf625000, 0x3c010001,
+	0xa4200f50, 0x3c010001, 0xa0200f57, 0x8fbf0018, 0x03e00008, 0x27bd0020,
+	0x27bdffe8, 0x3c1bc000, 0xafbf0014, 0xafb00010, 0xaf60680c, 0x8f626804,
+	0x34420082, 0xaf626804, 0x8f634000, 0x24020b50, 0x3c010001, 0xac220f20,
+	0x24020b78, 0x3c010001, 0xac220f30, 0x34630002, 0xaf634000, 0x0c004315,
+	0x00808021, 0x3c010001, 0xa0220f34, 0x304200ff, 0x24030002, 0x14430005,
+	0x00000000, 0x3c020001, 0x8c420f20, 0x08004308, 0xac5000c0, 0x3c020001,
+	0x8c420f20, 0xac5000bc, 0x8f624434, 0x8f634438, 0x8f644410, 0x3c010001,
+	0xac220f28, 0x3c010001, 0xac230f38, 0x3c010001, 0xac240f24, 0x8fbf0014,
+	0x8fb00010, 0x03e00008, 0x27bd0018, 0x03e00008, 0x24020001, 0x27bdfff8,
+	0x18800009, 0x00002821, 0x8f63680c, 0x8f62680c, 0x1043fffe, 0x00000000,
+	0x24a50001, 0x00a4102a, 0x1440fff9, 0x00000000, 0x03e00008, 0x27bd0008,
+	0x8f634450, 0x3c020001, 0x8c420f28, 0x00031c02, 0x0043102b, 0x14400008,
+	0x3c038000, 0x3c040001, 0x8c840f38, 0x8f624450, 0x00021c02, 0x0083102b,
+	0x1040fffc, 0x3c038000, 0xaf634444, 0x8f624444, 0x00431024, 0x1440fffd,
+	0x00000000, 0x8f624448, 0x03e00008, 0x3042ffff, 0x3082ffff, 0x2442e000,
+	0x2c422001, 0x14400003, 0x3c024000, 0x08004347, 0x2402ffff, 0x00822025,
+	0xaf645c38, 0x8f625c30, 0x30420002, 0x1440fffc, 0x00001021, 0x03e00008,
+	0x00000000, 0x8f624450, 0x3c030001, 0x8c630f24, 0x08004350, 0x3042ffff,
+	0x8f624450, 0x3042ffff, 0x0043102b, 0x1440fffc, 0x00000000, 0x03e00008,
+	0x00000000, 0x27bdffe0, 0x00802821, 0x3c040001, 0x24840ed0, 0x00003021,
+	0x00003821, 0xafbf0018, 0xafa00010, 0x0c004378, 0xafa00014, 0x0800435f,
+	0x00000000, 0x8fbf0018, 0x03e00008, 0x27bd0020, 0x3c020001, 0x3442d600,
+	0x3c030001, 0x3463d600, 0x3c040001, 0x3484ddff, 0x3c010001, 0xac220f40,
+	0x24020040, 0x3c010001, 0xac220f44, 0x3c010001, 0xac200f3c, 0xac600000,
+	0x24630004, 0x0083102b, 0x5040fffd, 0xac600000, 0x03e00008, 0x00000000,
+	0x00804821, 0x8faa0010, 0x3c020001, 0x8c420f3c, 0x3c040001, 0x8c840f44,
+	0x8fab0014, 0x24430001, 0x0044102b, 0x3c010001, 0xac230f3c, 0x14400003,
+	0x00004021, 0x3c010001, 0xac200f3c, 0x3c020001, 0x8c420f3c, 0x3c030001,
+	0x8c630f40, 0x91240000, 0x00021140, 0x00431021, 0x00481021, 0x25080001,
+	0xa0440000, 0x29020008, 0x1440fff4, 0x25290001, 0x3c020001, 0x8c420f3c,
+	0x3c030001, 0x8c630f40, 0x8f64680c, 0x00021140, 0x00431021, 0xac440008,
+	0xac45000c, 0xac460010, 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c,
+	0x00000000, 0x00000000, 0x00000000,
 };
 
-u32 tg3Tso5FwRodata[] = {
+u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = {
 	0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000,
 	0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000,
 	0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272,
-	0x00000000, 0x00000000, 0x00000000
+	0x00000000, 0x00000000, 0x00000000,
 };
 
-u32 tg3Tso5FwData[] = {
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 
-	0x66666c64, 0x5f76312e, 0x312e3000, 0x00000000
+u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = {
+	0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000,
 };
 
 /* tp->lock is held. */
@@ -4338,6 +4605,9 @@ static int tg3_load_tso_firmware(struct 
 	unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
 	int err, i;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+		return 0;
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 		info.text_base = TG3_TSO5_FW_TEXT_ADDR;
 		info.text_len = TG3_TSO5_FW_TEXT_LEN;
@@ -4364,7 +4634,7 @@ static int tg3_load_tso_firmware(struct 
 		info.rodata_data = &tg3TsoFwRodata[0];
 		info.data_base = TG3_TSO_FW_DATA_ADDR;
 		info.data_len = TG3_TSO_FW_DATA_LEN;
-		info.data_data = NULL;
+		info.data_data = &tg3TsoFwData[0];
 		cpu_base = TX_CPU_BASE;
 		cpu_scratch_base = TX_CPU_SCRATCH_BASE;
 		cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
@@ -4440,7 +4710,7 @@ static void __tg3_set_mac_addr(struct tg
 
 static int tg3_set_mac_addr(struct net_device *dev, void *p)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	struct sockaddr *addr = p;
 
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -4485,55 +4755,27 @@ static int tg3_reset_hw(struct tg3 *tp)
 
 	tg3_stop_fw(tp);
 
+	tg3_write_sig_pre_reset(tp, RESET_KIND_INIT);
+
 	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) {
 		err = tg3_abort_hw(tp);
 		if (err)
 			return err;
 	}
 
-	tg3_chip_reset(tp);
-
-	val = tr32(GRC_MODE);
-	val &= GRC_MODE_HOST_STACKUP;
-	tw32(GRC_MODE, val | tp->grc_mode);
-
-	tg3_write_mem(tp,
-		      NIC_SRAM_FIRMWARE_MBOX,
-		      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
-	if (tp->phy_id == PHY_ID_SERDES) {
-		tp->mac_mode = MAC_MODE_PORT_MODE_TBI;
-		tw32_f(MAC_MODE, tp->mac_mode);
-	} else
-		tw32_f(MAC_MODE, 0);
-	udelay(40);
-
-	/* Wait for firmware initialization to complete. */
-	for (i = 0; i < 100000; i++) {
-		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
-		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
-			break;
-		udelay(10);
-	}
-	if (i >= 100000 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
-		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
-		       "firmware will not restart magic=%08x\n",
-		       tp->dev->name, val);
-		return -ENODEV;
-	}
+	err = tg3_chip_reset(tp);
+	if (err)
+		return err;
 
-	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF)
-		tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
-			      DRV_STATE_START);
-	else
-		tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
-			      DRV_STATE_SUSPEND);
+	tg3_write_sig_legacy(tp, RESET_KIND_INIT);
 
 	/* This works around an issue with Athlon chipsets on
 	 * B3 tigon3 silicon.  This bit has no effect on any
-	 * other revision.
+	 * other revision.  But do not set this on PCI Express
+	 * chips.
 	 */
-	tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
+	if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+		tp->pci_clock_ctrl |= CLOCK_CTRL_DELAY_PCI_GRANT;
 	tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
@@ -4543,6 +4785,13 @@ static int tg3_reset_hw(struct tg3 *tp)
 		tw32(TG3PCI_PCISTATE, val);
 	}
 
+	if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
+		/* Enable some hw fixes.  */
+		val = tr32(TG3PCI_MSI_DATA);
+		val |= (1 << 26) | (1 << 28) | (1 << 29);
+		tw32(TG3PCI_MSI_DATA, val);
+	}
+
 	/* Descriptor ring init may make accesses to the
 	 * NIC SRAM area to setup the TX descriptors, so we
 	 * can only do this after the hardware has been
@@ -4573,11 +4822,15 @@ static int tg3_reset_hw(struct tg3 *tp)
 	     (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
 
 	/* Setup the timer prescalar register.  Clock is always 66Mhz. */
-	tw32(GRC_MISC_CFG,
-	     (65 << GRC_MISC_CFG_PRESCALAR_SHIFT));
+	val = tr32(GRC_MISC_CFG);
+	val &= ~0xff;
+	val |= (65 << GRC_MISC_CFG_PRESCALAR_SHIFT);
+	tw32(GRC_MISC_CFG, val);
 
 	/* Initialize MBUF/DESC pool. */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		/* Do nothing.  */
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
 		tw32(BUFMGR_MB_POOL_ADDR, NIC_SRAM_MBUF_POOL_BASE);
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
 			tw32(BUFMGR_MB_POOL_SIZE, NIC_SRAM_MBUF_POOL_SIZE64);
@@ -4635,30 +4888,6 @@ static int tg3_reset_hw(struct tg3 *tp)
 		return -ENODEV;
 	}
 
-	tw32(FTQ_RESET, 0xffffffff);
-	tw32(FTQ_RESET, 0x00000000);
-	for (i = 0; i < 2000; i++) {
-		if (tr32(FTQ_RESET) == 0x00000000)
-			break;
-		udelay(10);
-	}
-	if (i >= 2000) {
-		printk(KERN_ERR PFX "tg3_reset_hw cannot reset FTQ for %s.\n",
-		       tp->dev->name);
-		return -ENODEV;
-	}
-
-	/* Clear statistics/status block in chip, and status block in ram. */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
-		for (i = NIC_SRAM_STATS_BLK;
-	     	     i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
-	     	     i += sizeof(u32)) {
-			tg3_write_mem(tp, i, 0);
-			udelay(40);
-		}
-	}
-	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
-
 	/* Setup replenish threshold. */
 	tw32(RCVBDI_STD_THRESH, tp->rx_pending / 8);
 
@@ -4689,7 +4918,8 @@ static int tg3_reset_hw(struct tg3 *tp)
 	/* Don't even try to program the JUMBO/MINI buffer descriptor
 	 * configs on 5705.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 		tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS,
 		     RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT);
 	} else {
@@ -4718,10 +4948,11 @@ static int tg3_reset_hw(struct tg3 *tp)
 
 	}
 
-	/* There is only one send ring on 5705, no need to explicitly
+	/* There is only one send ring on 5705/5750, no need to explicitly
 	 * disable the others.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
 		/* Clear out send RCB ring in SRAM. */
 		for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
 			tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
@@ -4746,10 +4977,11 @@ static int tg3_reset_hw(struct tg3 *tp)
 			       NIC_SRAM_TX_BUFFER_DESC);
 	}
 
-	/* There is only one receive return ring on 5705, no need to explicitly
-	 * disable the others.
+	/* There is only one receive return ring on 5705/5750, no need
+	 * to explicitly disable the others.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
 		for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK;
 		     i += TG3_BDINFO_SIZE) {
 			tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
@@ -4803,17 +5035,24 @@ static int tg3_reset_hw(struct tg3 *tp)
 		      RDMAC_MODE_LNGREAD_ENAB);
 	if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
 		rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
-		if (tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
-			if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) {
-				rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
-			} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
-				   !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
-				rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
-			}
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
+	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
+		if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
+		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
+		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
+			rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
+		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
+			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
+			rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
 		}
 	}
 
+#if TG3_TSO_SUPPORT != 0
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+		rdmac_mode |= (1 << 27);
+#endif
+
 	/* Receive/send statistics. */
 	if ((rdmac_mode & RDMAC_MODE_FIFO_SIZE_128) &&
 	    (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
@@ -4841,10 +5080,11 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
 	tw32(HOSTCC_RXMAX_FRAMES, 1);
 	tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
 		tw32(HOSTCC_RXCOAL_TICK_INT, 0);
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)
 		tw32(HOSTCC_TXCOAL_TICK_INT, 0);
+	}
 	tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
 	tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
 
@@ -4854,10 +5094,11 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
 	     ((u64) tp->status_mapping & 0xffffffff));
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
 		/* Status/statistics block address.  See tg3_timer,
 		 * the tg3_periodic_fetch_stats call there, and
-		 * tg3_get_stats to see how this works for 5705 chips.
+		 * tg3_get_stats to see how this works for 5705/5750 chips.
 		 */
 		tw32(HOSTCC_STAT_COAL_TICKS,
 		     DEFAULT_STAT_COAL_TICKS);
@@ -4873,9 +5114,19 @@ static int tg3_reset_hw(struct tg3 *tp)
 
 	tw32(RCVCC_MODE, RCVCC_MODE_ENABLE | RCVCC_MODE_ATTN_ENABLE);
 	tw32(RCVLPC_MODE, RCVLPC_MODE_ENABLE);
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
 		tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
 
+	/* Clear statistics/status block in chip, and status block in ram. */
+	for (i = NIC_SRAM_STATS_BLK;
+	     i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
+	     i += sizeof(u32)) {
+		tg3_write_mem(tp, i, 0);
+		udelay(40);
+	}
+	memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE);
+
 	tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE |
 		MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE;
 	tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
@@ -4891,7 +5142,8 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
 	tr32(MAILBOX_INTERRUPT_0);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750) {
 		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
 		udelay(40);
 	}
@@ -4901,10 +5153,21 @@ static int tg3_reset_hw(struct tg3 *tp)
 	       WDMAC_MODE_ADDROFLOW_ENAB | WDMAC_MODE_FIFOOFLOW_ENAB |
 	       WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
 	       WDMAC_MODE_LNGREAD_ENAB);
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-	    (tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) != 0 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_IS_5788))
-		val |= WDMAC_MODE_RX_ACCEL;
+
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		if ((tp->tg3_flags & TG3_FLG2_TSO_CAPABLE) &&
+		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
+		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
+			/* nothing */
+		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
+			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
+			   !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+			val |= WDMAC_MODE_RX_ACCEL;
+		}
+	}
+
 	tw32_f(WDMAC_MODE, val);
 	udelay(40);
 
@@ -4927,13 +5190,18 @@ static int tg3_reset_hw(struct tg3 *tp)
 	udelay(40);
 
 	tw32(RCVDCC_MODE, RCVDCC_MODE_ENABLE | RCVDCC_MODE_ATTN_ENABLE);
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5705 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)
 		tw32(MBFREE_MODE, MBFREE_MODE_ENABLE);
 	tw32(SNDDATAC_MODE, SNDDATAC_MODE_ENABLE);
 	tw32(SNDBDC_MODE, SNDBDC_MODE_ENABLE | SNDBDC_MODE_ATTN_ENABLE);
 	tw32(RCVBDI_MODE, RCVBDI_MODE_ENABLE | RCVBDI_MODE_RCB_ATTN_ENAB);
 	tw32(RCVDBDI_MODE, RCVDBDI_MODE_ENABLE | RCVDBDI_MODE_INV_RING_SZ);
 	tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
+#if TG3_TSO_SUPPORT != 0
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+		tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
+#endif
 	tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE);
 	tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
 
@@ -4968,9 +5236,10 @@ static int tg3_reset_hw(struct tg3 *tp)
 
 	tp->mi_mode = MAC_MI_MODE_BASE;
 	tw32_f(MAC_MI_MODE, tp->mi_mode);
-	udelay(40);
+	udelay(80);
+
+	tw32(MAC_LED_CTRL, tp->led_ctrl);
 
-	tw32(MAC_LED_CTRL, 0);
 	tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
 	if (tp->phy_id == PHY_ID_SERDES) {
 		tw32_f(MAC_RX_MODE, RX_MODE_RESET);
@@ -4979,14 +5248,43 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
-	if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
-		tw32(MAC_SERDES_CFG, 0x616000);
+	if (tp->phy_id == PHY_ID_SERDES) {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+			/* Set drive transmission level to 1.2V  */
+			val = tr32(MAC_SERDES_CFG);
+			val &= 0xfffff000;
+			val |= 0x880;
+			tw32(MAC_SERDES_CFG, val);
+		}
+		if (tp->pci_chip_rev_id == CHIPREV_ID_5703_A1)
+			tw32(MAC_SERDES_CFG, 0x616000);
+	}
 
 	/* Prevent chip from dropping frames when flow control
 	 * is enabled.
 	 */
 	tw32_f(MAC_LOW_WMARK_MAX_RX_FRAME, 2);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+	    tp->phy_id == PHY_ID_SERDES) {
+		/* Enable hardware link auto-negotiation */
+		u32 digctrl, txctrl;
+
+		digctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_CRC16_CLEAR_N |
+		    SG_DIG_LOCAL_DUPLEX_STATUS | SG_DIG_LOCAL_LINK_STATUS |
+		    (2 << SG_DIG_SPEED_STATUS_SHIFT) | SG_DIG_FIBER_MODE |
+		    SG_DIG_GBIC_ENABLE;
+
+		txctrl = tr32(MAC_SERDES_CFG);
+		tw32_f(MAC_SERDES_CFG, txctrl | MAC_SERDES_CFG_EDGE_SELECT);
+		tw32_f(SG_DIG_CTRL, digctrl | SG_DIG_SOFT_RESET);
+		tr32(SG_DIG_CTRL);
+		udelay(5);
+		tw32_f(SG_DIG_CTRL, digctrl);
+
+		tp->tg3_flags2 |= TG3_FLG2_HW_AUTONEG;
+	}
+
 	err = tg3_setup_phy(tp, 1);
 	if (err)
 		return err;
@@ -5008,7 +5306,8 @@ static int tg3_reset_hw(struct tg3 *tp)
 	tw32(MAC_RCV_RULE_1,  0x86000004 & RCV_RULE_DISABLE_MASK);
 	tw32(MAC_RCV_VALUE_1, 0xffffffff & RCV_RULE_DISABLE_MASK);
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
 		limit = 8;
 	else
 		limit = 16;
@@ -5050,6 +5349,8 @@ static int tg3_reset_hw(struct tg3 *tp)
 		break;
 	};
 
+	tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
+
 	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)
 		tg3_enable_ints(tp);
 
@@ -5150,7 +5451,8 @@ static void tg3_timer(unsigned long __op
 		return;
 	}
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
 		tg3_periodic_fetch_stats(tp);
 
 	/* This part only runs once per second. */
@@ -5220,7 +5522,7 @@ static void tg3_timer(unsigned long __op
 
 static int tg3_open(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
 	spin_lock_irq(&tp->lock);
@@ -5519,10 +5821,11 @@ static int tg3_open(struct net_device *d
 #endif
 
 static struct net_device_stats *tg3_get_stats(struct net_device *);
+static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
 
 static int tg3_close(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 
 	netif_stop_queue(dev);
 
@@ -5550,6 +5853,8 @@ static int tg3_close(struct net_device *
 
 	memcpy(&tp->net_stats_prev, tg3_get_stats(tp->dev),
 	       sizeof(tp->net_stats_prev));
+	memcpy(&tp->estats_prev, tg3_get_estats(tp),
+	       sizeof(tp->estats_prev));
 
 	tg3_free_consistent(tp);
 
@@ -5592,9 +5897,101 @@ static unsigned long calc_crc_errors(str
 	return get_stat64(&hw_stats->rx_fcs_errors);
 }
 
+#define ESTAT_ADD(member) \
+	estats->member =	old_estats->member + \
+				get_stat64(&hw_stats->member)
+
+static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp)
+{
+	struct tg3_ethtool_stats *estats = &tp->estats;
+	struct tg3_ethtool_stats *old_estats = &tp->estats_prev;
+	struct tg3_hw_stats *hw_stats = tp->hw_stats;
+
+	if (!hw_stats)
+		return old_estats;
+
+	ESTAT_ADD(rx_octets);
+	ESTAT_ADD(rx_fragments);
+	ESTAT_ADD(rx_ucast_packets);
+	ESTAT_ADD(rx_mcast_packets);
+	ESTAT_ADD(rx_bcast_packets);
+	ESTAT_ADD(rx_fcs_errors);
+	ESTAT_ADD(rx_align_errors);
+	ESTAT_ADD(rx_xon_pause_rcvd);
+	ESTAT_ADD(rx_xoff_pause_rcvd);
+	ESTAT_ADD(rx_mac_ctrl_rcvd);
+	ESTAT_ADD(rx_xoff_entered);
+	ESTAT_ADD(rx_frame_too_long_errors);
+	ESTAT_ADD(rx_jabbers);
+	ESTAT_ADD(rx_undersize_packets);
+	ESTAT_ADD(rx_in_length_errors);
+	ESTAT_ADD(rx_out_length_errors);
+	ESTAT_ADD(rx_64_or_less_octet_packets);
+	ESTAT_ADD(rx_65_to_127_octet_packets);
+	ESTAT_ADD(rx_128_to_255_octet_packets);
+	ESTAT_ADD(rx_256_to_511_octet_packets);
+	ESTAT_ADD(rx_512_to_1023_octet_packets);
+	ESTAT_ADD(rx_1024_to_1522_octet_packets);
+	ESTAT_ADD(rx_1523_to_2047_octet_packets);
+	ESTAT_ADD(rx_2048_to_4095_octet_packets);
+	ESTAT_ADD(rx_4096_to_8191_octet_packets);
+	ESTAT_ADD(rx_8192_to_9022_octet_packets);
+
+	ESTAT_ADD(tx_octets);
+	ESTAT_ADD(tx_collisions);
+	ESTAT_ADD(tx_xon_sent);
+	ESTAT_ADD(tx_xoff_sent);
+	ESTAT_ADD(tx_flow_control);
+	ESTAT_ADD(tx_mac_errors);
+	ESTAT_ADD(tx_single_collisions);
+	ESTAT_ADD(tx_mult_collisions);
+	ESTAT_ADD(tx_deferred);
+	ESTAT_ADD(tx_excessive_collisions);
+	ESTAT_ADD(tx_late_collisions);
+	ESTAT_ADD(tx_collide_2times);
+	ESTAT_ADD(tx_collide_3times);
+	ESTAT_ADD(tx_collide_4times);
+	ESTAT_ADD(tx_collide_5times);
+	ESTAT_ADD(tx_collide_6times);
+	ESTAT_ADD(tx_collide_7times);
+	ESTAT_ADD(tx_collide_8times);
+	ESTAT_ADD(tx_collide_9times);
+	ESTAT_ADD(tx_collide_10times);
+	ESTAT_ADD(tx_collide_11times);
+	ESTAT_ADD(tx_collide_12times);
+	ESTAT_ADD(tx_collide_13times);
+	ESTAT_ADD(tx_collide_14times);
+	ESTAT_ADD(tx_collide_15times);
+	ESTAT_ADD(tx_ucast_packets);
+	ESTAT_ADD(tx_mcast_packets);
+	ESTAT_ADD(tx_bcast_packets);
+	ESTAT_ADD(tx_carrier_sense_errors);
+	ESTAT_ADD(tx_discards);
+	ESTAT_ADD(tx_errors);
+
+	ESTAT_ADD(dma_writeq_full);
+	ESTAT_ADD(dma_write_prioq_full);
+	ESTAT_ADD(rxbds_empty);
+	ESTAT_ADD(rx_discards);
+	ESTAT_ADD(rx_errors);
+	ESTAT_ADD(rx_threshold_hit);
+
+	ESTAT_ADD(dma_readq_full);
+	ESTAT_ADD(dma_read_prioq_full);
+	ESTAT_ADD(tx_comp_queue_full);
+
+	ESTAT_ADD(ring_set_send_prod_index);
+	ESTAT_ADD(ring_status_update);
+	ESTAT_ADD(nic_irqs);
+	ESTAT_ADD(nic_avoided_irqs);
+	ESTAT_ADD(nic_tx_threshold_hit);
+
+	return estats;
+}
+
 static struct net_device_stats *tg3_get_stats(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	struct net_device_stats *stats = &tp->net_stats;
 	struct net_device_stats *old_stats = &tp->net_stats_prev;
 	struct tg3_hw_stats *hw_stats = tp->hw_stats;
@@ -5618,7 +6015,8 @@ static struct net_device_stats *tg3_get_
 		get_stat64(&hw_stats->tx_octets);
 
 	stats->rx_errors = old_stats->rx_errors +
-		get_stat64(&hw_stats->rx_errors);
+		get_stat64(&hw_stats->rx_errors) +
+		get_stat64(&hw_stats->rx_discards);
 	stats->tx_errors = old_stats->tx_errors +
 		get_stat64(&hw_stats->tx_errors) +
 		get_stat64(&hw_stats->tx_mac_errors) +
@@ -5685,7 +6083,7 @@ static void tg3_set_multi(struct tg3 *tp
 
 static void __tg3_set_rx_mode(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	u32 rx_mode;
 
 	rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC |
@@ -5749,7 +6147,7 @@ static void __tg3_set_rx_mode(struct net
 
 static void tg3_set_rx_mode(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 
 	spin_lock_irq(&tp->lock);
 	__tg3_set_rx_mode(dev);
@@ -5763,10 +6161,12 @@ static int tg3_get_regs_len(struct net_d
 	return TG3_REGDUMP_LEN;
 }
 
-static void tg3_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
+static void tg3_get_regs(struct net_device *dev,
+		struct ethtool_regs *regs, void *_p)
 {
-	struct tg3 *tp = dev->priv;
-	u8 *orig_p = p;
+	u32 *p = _p;
+	struct tg3 *tp = netdev_priv(dev);
+	u8 *orig_p = _p;
 	int i;
 
 	regs->version = 0;
@@ -5776,15 +6176,15 @@ static void tg3_get_regs(struct net_devi
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
-#define __GET_REG32(reg)	(*((u32 *)(p))++ = tr32(reg))
+#define __GET_REG32(reg)	(*(p)++ = tr32(reg))
 #define GET_REG32_LOOP(base,len)		\
-do {	p = orig_p + (base);			\
+do {	p = (u32 *)(orig_p + (base));		\
 	for (i = 0; i < len; i += 4)		\
 		__GET_REG32((base) + i);	\
 } while (0)
-#define GET_REG32_1(reg)	\
-do {	p = orig_p + (reg);	\
-	__GET_REG32((reg));	\
+#define GET_REG32_1(reg)			\
+do {	p = (u32 *)(orig_p + (reg));		\
+	__GET_REG32((reg));			\
 } while (0)
 
 	GET_REG32_LOOP(TG3PCI_VENDOR, 0xb0);
@@ -5828,9 +6228,75 @@ do {	p = orig_p + (reg);	\
 	spin_unlock_irq(&tp->lock);
 }
 
+static int tg3_get_eeprom_len(struct net_device *dev)
+{
+	return EEPROM_CHIP_SIZE;
+}
+
+static int __devinit tg3_nvram_read_using_eeprom(struct tg3 *tp,
+						 u32 offset, u32 *val);
+static int tg3_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct tg3 *tp = dev->priv;
+	int ret;
+	u8  *pd;
+	u32 i, offset, len, val, b_offset, b_count;
+
+	offset = eeprom->offset;
+	len = eeprom->len;
+	eeprom->len = 0;
+
+	ret = tg3_nvram_read_using_eeprom(tp, 0, &eeprom->magic);
+	if (ret)
+		return ret;
+	eeprom->magic = swab32(eeprom->magic);
+
+	if (offset & 3) {
+		/* adjustments to start on required 4 byte boundary */
+		b_offset = offset & 3;
+		b_count = 4 - b_offset;
+		if (b_count > len) {
+			/* i.e. offset=1 len=2 */
+			b_count = len;
+		}
+		ret = tg3_nvram_read_using_eeprom(tp, offset-b_offset, &val);
+		if (ret)
+			return ret;
+		memcpy(data, ((char*)&val) + b_offset, b_count);
+		len -= b_count;
+		offset += b_count;
+	        eeprom->len += b_count;
+	}
+
+	/* read bytes upto the last 4 byte boundary */
+	pd = &data[eeprom->len];
+	for (i = 0; i < (len - (len & 3)); i += 4) {
+		ret = tg3_nvram_read_using_eeprom(tp, offset + i, 
+				(u32*)(pd + i));
+		if (ret) {
+			eeprom->len += i;
+			return ret;
+		}
+	}
+	eeprom->len += i;
+
+	if (len & 3) {
+		/* read last bytes not ending on 4 byte boundary */
+		pd = &data[eeprom->len];
+		b_count = len & 3;
+		b_offset = offset + len - b_count;
+		ret = tg3_nvram_read_using_eeprom(tp, b_offset, &val);
+		if (ret)
+			return ret;
+		memcpy(pd, ((char*)&val), b_count);
+		eeprom->len += b_count;
+	}
+	return 0;
+}
+
 static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-  	struct tg3 *tp = dev->priv;
+  	struct tg3 *tp = netdev_priv(dev);
   
 	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
 					tp->link_config.phy_is_low_power)
@@ -5865,12 +6331,22 @@ static int tg3_get_settings(struct net_d
   
 static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE) ||
 	    tp->link_config.phy_is_low_power)
 		return -EAGAIN;
 
+	if (tp->phy_id == PHY_ID_SERDES) {
+		/* These are the only valid advertisement bits allowed.  */
+		if (cmd->autoneg == AUTONEG_ENABLE &&
+		    (cmd->advertising & ~(ADVERTISED_1000baseT_Half |
+					  ADVERTISED_1000baseT_Full |
+					  ADVERTISED_Autoneg |
+					  ADVERTISED_FIBRE)))
+			return -EINVAL;
+	}
+
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
 
@@ -5880,6 +6356,7 @@ static int tg3_set_settings(struct net_d
 		tp->link_config.speed = SPEED_INVALID;
 		tp->link_config.duplex = DUPLEX_INVALID;
 	} else {
+		tp->link_config.advertising = 0;
 		tp->link_config.speed = cmd->speed;
 		tp->link_config.duplex = cmd->duplex;
   	}
@@ -5893,7 +6370,7 @@ static int tg3_set_settings(struct net_d
   
 static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	strcpy(info->driver, DRV_MODULE_NAME);
 	strcpy(info->version, DRV_MODULE_VERSION);
@@ -5902,7 +6379,7 @@ static void tg3_get_drvinfo(struct net_d
   
 static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	wol->supported = WAKE_MAGIC;
 	wol->wolopts = 0;
@@ -5913,7 +6390,7 @@ static void tg3_get_wol(struct net_devic
   
 static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
@@ -5934,20 +6411,20 @@ static int tg3_set_wol(struct net_device
   
 static u32 tg3_get_msglevel(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	return tp->msg_enable;
 }
   
 static void tg3_set_msglevel(struct net_device *dev, u32 value)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	tp->msg_enable = value;
 }
   
 #if TG3_TSO_SUPPORT != 0
 static int tg3_set_tso(struct net_device *dev, u32 value)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 
 	if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) {
 		if (value)
@@ -5960,7 +6437,7 @@ static int tg3_set_tso(struct net_device
   
 static int tg3_nway_reset(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	u32 bmcr;
 	int r;
   
@@ -5979,7 +6456,7 @@ static int tg3_nway_reset(struct net_dev
   
 static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	ering->rx_max_pending = TG3_RX_RING_SIZE - 1;
 	ering->rx_mini_max_pending = 0;
@@ -5993,7 +6470,7 @@ static void tg3_get_ringparam(struct net
   
 static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
 	    (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
@@ -6024,7 +6501,7 @@ static int tg3_set_ringparam(struct net_
   
 static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
 	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0;
@@ -6033,7 +6510,7 @@ static void tg3_get_pauseparam(struct ne
   
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	tg3_netif_stop(tp);
 	spin_lock_irq(&tp->lock);
@@ -6061,13 +6538,13 @@ static int tg3_set_pauseparam(struct net
   
 static u32 tg3_get_rx_csum(struct net_device *dev)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	return (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0;
 }
   
 static int tg3_set_rx_csum(struct net_device *dev, u32 data)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) {
 		if (data != 0)
@@ -6087,7 +6564,7 @@ static int tg3_set_rx_csum(struct net_de
   
 static int tg3_set_tx_csum(struct net_device *dev, u32 data)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
   
 	if (tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) {
 		if (data != 0)
@@ -6102,11 +6579,35 @@ static int tg3_set_tx_csum(struct net_de
 
 	return 0;
 }
-  
+
+static int tg3_get_stats_count (struct net_device *dev)
+{
+	return TG3_NUM_STATS;
+}
+
+static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
+		break;
+	default:
+		WARN_ON(1);	/* we need a WARN() */
+		break;
+	}
+}
+
+static void tg3_get_ethtool_stats (struct net_device *dev,
+				   struct ethtool_stats *estats, u64 *tmp_stats)
+{
+	struct tg3 *tp = dev->priv;
+	memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
+}
+
 static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
 	switch(cmd) {
@@ -6117,6 +6618,9 @@ static int tg3_ioctl(struct net_device *
 	case SIOCGMIIREG: {
 		u32 mii_regval;
 
+		if (tp->phy_id == PHY_ID_SERDES)
+			break;			/* We have no PHY */
+
 		spin_lock_irq(&tp->lock);
 		err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
 		spin_unlock_irq(&tp->lock);
@@ -6127,6 +6631,9 @@ static int tg3_ioctl(struct net_device *
 	}
 
 	case SIOCSMIIREG:
+		if (tp->phy_id == PHY_ID_SERDES)
+			break;			/* We have no PHY */
+
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
@@ -6146,7 +6653,7 @@ static int tg3_ioctl(struct net_device *
 #if TG3_VLAN_TAG_USED
 static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
@@ -6162,7 +6669,7 @@ static void tg3_vlan_rx_register(struct 
 
 static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 
 	spin_lock_irq(&tp->lock);
 	spin_lock(&tp->tx_lock);
@@ -6185,6 +6692,8 @@ static struct ethtool_ops tg3_ethtool_op
 	.set_msglevel		= tg3_set_msglevel,
 	.nway_reset		= tg3_nway_reset,
 	.get_link		= ethtool_op_get_link,
+	.get_eeprom_len		= tg3_get_eeprom_len,
+	.get_eeprom		= tg3_get_eeprom,
 	.get_ringparam		= tg3_get_ringparam,
 	.set_ringparam		= tg3_set_ringparam,
 	.get_pauseparam		= tg3_get_pauseparam,
@@ -6199,6 +6708,9 @@ static struct ethtool_ops tg3_ethtool_op
 	.get_tso		= ethtool_op_get_tso,
 	.set_tso		= tg3_set_tso,
 #endif
+	.get_strings		= tg3_get_strings,
+	.get_stats_count	= tg3_get_stats_count,
+	.get_ethtool_stats	= tg3_get_ethtool_stats,
 };
 
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
@@ -6225,7 +6737,15 @@ static void __devinit tg3_nvram_init(str
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-		u32 nvcfg1 = tr32(NVRAM_CFG1);
+		u32 nvcfg1;
+
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+			u32 nvaccess = tr32(NVRAM_ACCESS);
+
+			tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
+		}
+
+		nvcfg1 = tr32(NVRAM_CFG1);
 
 		tp->tg3_flags |= TG3_FLAG_NVRAM;
 		if (nvcfg1 & NVRAM_CFG1_FLASHIF_ENAB) {
@@ -6236,6 +6756,11 @@ static void __devinit tg3_nvram_init(str
 			tw32(NVRAM_CFG1, nvcfg1);
 		}
 
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+			u32 nvaccess = tr32(NVRAM_ACCESS);
+
+			tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
+		}
 	} else {
 		tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
 	}
@@ -6278,7 +6803,7 @@ static int __devinit tg3_nvram_read_usin
 static int __devinit tg3_nvram_read(struct tg3 *tp,
 				    u32 offset, u32 *val)
 {
-	int i, saw_done_clear;
+	int i;
 
 	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
 		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n");
@@ -6296,11 +6821,12 @@ static int __devinit tg3_nvram_read(stru
 	if (offset > NVRAM_ADDR_MSK)
 		return -EINVAL;
 
-	tw32(NVRAM_SWARB, SWARB_REQ_SET1);
-	for (i = 0; i < 1000; i++) {
-		if (tr32(NVRAM_SWARB) & SWARB_GNT1)
-			break;
-		udelay(20);
+	tg3_nvram_lock(tp);
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		u32 nvaccess = tr32(NVRAM_ACCESS);
+
+		tw32_f(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
 	}
 
 	tw32(NVRAM_ADDR, offset);
@@ -6308,24 +6834,26 @@ static int __devinit tg3_nvram_read(stru
 	     NVRAM_CMD_RD | NVRAM_CMD_GO |
 	     NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
 
-	/* Wait for done bit to clear then set again. */
-	saw_done_clear = 0;
+	/* Wait for done bit to clear. */
 	for (i = 0; i < 1000; i++) {
 		udelay(10);
-		if (!saw_done_clear &&
-		    !(tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
-			saw_done_clear = 1;
-		else if (saw_done_clear &&
-			 (tr32(NVRAM_CMD) & NVRAM_CMD_DONE))
+		if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
+			udelay(10);
+			*val = swab32(tr32(NVRAM_RDDATA));
 			break;
+		}
 	}
-	if (i >= 1000) {
-		tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
-		return -EBUSY;
+
+	tg3_nvram_unlock(tp);
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+		u32 nvaccess = tr32(NVRAM_ACCESS);
+
+		tw32_f(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
 	}
 
-	*val = swab32(tr32(NVRAM_RDDATA));
-	tw32(NVRAM_SWARB, 0x20);
+	if (i >= 1000)
+		return -EBUSY;
 
 	return 0;
 }
@@ -6346,8 +6874,8 @@ static struct subsys_tbl_ent subsys_id_t
 	{ PCI_VENDOR_ID_BROADCOM, 0x0007, PHY_ID_SERDES  }, /* BCM95701A7 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x0008, PHY_ID_BCM5701 }, /* BCM95701A10 */
 	{ PCI_VENDOR_ID_BROADCOM, 0x8008, PHY_ID_BCM5701 }, /* BCM95701A12 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5701 }, /* BCM95703Ax1 */
-	{ PCI_VENDOR_ID_BROADCOM, 0x8009, PHY_ID_BCM5701 }, /* BCM95703Ax2 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x0009, PHY_ID_BCM5703 }, /* BCM95703Ax1 */
+	{ PCI_VENDOR_ID_BROADCOM, 0x8009, PHY_ID_BCM5703 }, /* BCM95703Ax2 */
 
 	/* 3com boards. */
 	{ PCI_VENDOR_ID_3COM, 0x1000, PHY_ID_BCM5401 }, /* 3C996T */
@@ -6377,7 +6905,6 @@ static int __devinit tg3_phy_probe(struc
 {
 	u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
 	u32 hw_phy_id, hw_phy_id_masked;
-	enum phy_led_mode eeprom_led_mode;
 	u32 val;
 	int i, eeprom_signature_found, err;
 
@@ -6393,11 +6920,10 @@ static int __devinit tg3_phy_probe(struc
 	}
 
 	eeprom_phy_id = PHY_ID_INVALID;
-	eeprom_led_mode = led_mode_auto;
 	eeprom_signature_found = 0;
 	tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
 	if (val == NIC_SRAM_DATA_SIG_MAGIC) {
-		u32 nic_cfg;
+		u32 nic_cfg, led_cfg;
 
 		tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
 		tp->nic_sram_data_cfg = nic_cfg;
@@ -6421,45 +6947,89 @@ static int __devinit tg3_phy_probe(struc
 			}
 		}
 
-		switch (nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK) {
-		case NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD:
-			eeprom_led_mode = led_mode_three_link;
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+			tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &led_cfg);
+			led_cfg &= (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
+				    SHASTA_EXT_LED_MODE_MASK);
+		} else
+			led_cfg = nic_cfg & NIC_SRAM_DATA_CFG_LED_MODE_MASK;
+
+		switch (led_cfg) {
+		default:
+		case NIC_SRAM_DATA_CFG_LED_MODE_PHY_1:
+			tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 			break;
 
-		case NIC_SRAM_DATA_CFG_LED_LINK_SPD:
-			eeprom_led_mode = led_mode_link10;
+		case NIC_SRAM_DATA_CFG_LED_MODE_PHY_2:
+			tp->led_ctrl = LED_CTRL_MODE_PHY_2;
 			break;
 
-		default:
-			eeprom_led_mode = led_mode_auto;
+		case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
+			tp->led_ctrl = LED_CTRL_MODE_MAC;
+			break;
+
+		case SHASTA_EXT_LED_SHARED:
+			tp->led_ctrl = LED_CTRL_MODE_SHARED;
+			if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+			    tp->pci_chip_rev_id != CHIPREV_ID_5750_A1)
+				tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+						 LED_CTRL_MODE_PHY_2);
+			break;
+
+		case SHASTA_EXT_LED_MAC:
+			tp->led_ctrl = LED_CTRL_MODE_SHASTA_MAC;
 			break;
+
+		case SHASTA_EXT_LED_COMBO:
+			tp->led_ctrl = LED_CTRL_MODE_COMBO;
+			if (tp->pci_chip_rev_id != CHIPREV_ID_5750_A0)
+				tp->led_ctrl |= (LED_CTRL_MODE_PHY_1 |
+						 LED_CTRL_MODE_PHY_2);
+			break;
+
 		};
 
+		if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
+		     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) &&
+		    tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
+			tp->led_ctrl = LED_CTRL_MODE_PHY_2;
+
 		if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) ||
 		     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
 		     (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)) &&
 		    (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP))
 			tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT;
 
-		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE)
+		if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) {
 			tp->tg3_flags |= TG3_FLAG_ENABLE_ASF;
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+				tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
+		}
 		if (nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL)
 			tp->tg3_flags |= TG3_FLAG_SERDES_WOL_CAP;
 	}
 
-	/* Now read the physical PHY_ID from the chip and verify
-	 * that it is sane.  If it doesn't look good, we fall back
-	 * to either the hard-coded table based PHY_ID and failing
-	 * that the value found in the eeprom area.
-	 */
-	err  = tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
-	err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
-
-	hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
-	hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
-	hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;
+	/* Reading the PHY ID register can conflict with ASF
+	 * firwmare access to the PHY hardware.
+	 */
+	err = 0;
+	if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
+		hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID;
+	} else {
+		/* Now read the physical PHY_ID from the chip and verify
+		 * that it is sane.  If it doesn't look good, we fall back
+		 * to either the hard-coded table based PHY_ID and failing
+		 * that the value found in the eeprom area.
+		 */
+		err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
+		err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);
+
+		hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
+		hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
+		hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;
 
-	hw_phy_id_masked = hw_phy_id & PHY_ID_MASK;
+		hw_phy_id_masked = hw_phy_id & PHY_ID_MASK;
+	}
 
 	if (!err && KNOWN_PHY_ID(hw_phy_id_masked)) {
 		tp->phy_id = hw_phy_id;
@@ -6476,64 +7046,62 @@ static int __devinit tg3_phy_probe(struc
 		}
 	}
 
-	err = tg3_phy_reset(tp, 1);
-	if (err)
-		return err;
+	if (tp->phy_id != PHY_ID_SERDES &&
+	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
+		u32 bmsr, adv_reg, tg3_ctrl;
 
-	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
-	    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
-		u32 mii_tg3_ctrl;
-		
-		/* These chips, when reset, only advertise 10Mb
-		 * capabilities.  Fix that.
-		 */
-		err  = tg3_writephy(tp, MII_ADVERTISE,
-				    (ADVERTISE_CSMA |
-				     ADVERTISE_PAUSE_CAP |
-				     ADVERTISE_10HALF |
-				     ADVERTISE_10FULL |
-				     ADVERTISE_100HALF |
-				     ADVERTISE_100FULL));
-		mii_tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
-				MII_TG3_CTRL_ADV_1000_FULL |
-				MII_TG3_CTRL_AS_MASTER |
-				MII_TG3_CTRL_ENABLE_AS_MASTER);
-		if (tp->tg3_flags & TG3_FLAG_10_100_ONLY)
-			mii_tg3_ctrl = 0;
+		tg3_readphy(tp, MII_BMSR, &bmsr);
+		tg3_readphy(tp, MII_BMSR, &bmsr);
 
-		err |= tg3_writephy(tp, MII_TG3_CTRL, mii_tg3_ctrl);
-		err |= tg3_writephy(tp, MII_BMCR,
-				    (BMCR_ANRESTART | BMCR_ANENABLE));
-	}
+		if (bmsr & BMSR_LSTATUS)
+			goto skip_phy_reset;
+		    
+		err = tg3_phy_reset(tp);
+		if (err)
+			return err;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703) {
-		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);
-	}
+		adv_reg = (ADVERTISE_10HALF | ADVERTISE_10FULL |
+			   ADVERTISE_100HALF | ADVERTISE_100FULL |
+			   ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+		tg3_ctrl = 0;
+		if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
+			tg3_ctrl = (MII_TG3_CTRL_ADV_1000_HALF |
+				    MII_TG3_CTRL_ADV_1000_FULL);
+			if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
+			    tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
+				tg3_ctrl |= (MII_TG3_CTRL_AS_MASTER |
+					     MII_TG3_CTRL_ENABLE_AS_MASTER);
+		}
 
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) &&
-	    (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)) {
-		tg3_writephy(tp, 0x1c, 0x8d68);
-		tg3_writephy(tp, 0x1c, 0x8d68);
+		if (!tg3_copper_is_advertising_all(tp)) {
+			tg3_writephy(tp, MII_ADVERTISE, adv_reg);
+
+			if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
+				tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl);
+
+			tg3_writephy(tp, MII_BMCR,
+				     BMCR_ANENABLE | BMCR_ANRESTART);
+		}
+		tg3_phy_set_wirespeed(tp);
+
+		tg3_writephy(tp, MII_ADVERTISE, adv_reg);
+		if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY))
+			tg3_writephy(tp, MII_TG3_CTRL, tg3_ctrl);
 	}
 
-	/* Enable Ethernet@WireSpeed */
-	tg3_phy_set_wirespeed(tp);
+skip_phy_reset:
+	if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
+		err = tg3_init_5401phy_dsp(tp);
+		if (err)
+			return err;
+	}
 
 	if (!err && ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401)) {
 		err = tg3_init_5401phy_dsp(tp);
 	}
 
-	/* Determine the PHY led mode. */
-	if (tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) {
-		tp->led_mode = led_mode_link10;
-	} else {
-		tp->led_mode = led_mode_three_link;
-		if (eeprom_signature_found &&
-		    eeprom_led_mode != led_mode_auto)
-			tp->led_mode = eeprom_led_mode;
-	}
+	if (!eeprom_signature_found)
+		tp->led_ctrl = LED_CTRL_MODE_PHY_1;
 
 	if (tp->phy_id == PHY_ID_SERDES)
 		tp->link_config.advertising =
@@ -6715,6 +7283,9 @@ static int __devinit tg3_get_invariants(
 	tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
 	tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
+	if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0)
+		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
 	    tp->pci_lat_timer < 64) {
 		tp->pci_lat_timer = 64;
@@ -6767,8 +7338,12 @@ static int __devinit tg3_get_invariants(
 	/* Back to back register writes can cause problems on this chip,
 	 * the workaround is to read back all reg writes except those to
 	 * mailbox regs.  See tg3_write_indirect_reg32().
+	 *
+	 * PCI Express 5750_A0 rev chips need this workaround too.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
+	    ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
+	     tp->pci_chip_rev_id == CHIPREV_ID_5750_A0))
 		tp->tg3_flags |= TG3_FLAG_5701_REG_WRITE_BUG;
 
 	if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
@@ -6787,7 +7362,7 @@ static int __devinit tg3_get_invariants(
 	err = tg3_set_power_state(tp, 0);
 	if (err) {
 		printk(KERN_ERR PFX "(%s) transition to D0 failed\n",
-		       tp->pdev->slot_name);
+		       pci_name(tp->pdev));
 		return err;
 	}
 
@@ -6835,6 +7410,10 @@ static int __devinit tg3_get_invariants(
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
 		tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+		tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
+
 	/* Only 5701 and later support tagged irq status mode.
 	 * Also, 5788 chips cannot use tagged irq status.
 	 *
@@ -6850,7 +7429,7 @@ static int __devinit tg3_get_invariants(
 
 	/* Initialize MAC MI mode, polling disabled. */
 	tw32_f(MAC_MI_MODE, tp->mi_mode);
-	udelay(40);
+	udelay(80);
 
 	/* Initialize data/descriptor byte/word swapping. */
 	val = tr32(GRC_MODE);
@@ -6891,12 +7470,22 @@ static int __devinit tg3_get_invariants(
 	udelay(50);
 	tg3_nvram_init(tp);
 
+	/* Always use host TXDs, it performs better in particular
+	 * with multi-frag packets.  The tests below are kept here
+	 * as documentation should we change this decision again
+	 * in the future.
+	 */
+	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
+
+#if 0
 	/* Determine if TX descriptors will reside in
 	 * main memory or in the chip SRAM.
 	 */
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
 		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
+#endif
 
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
@@ -6919,13 +7508,15 @@ static int __devinit tg3_get_invariants(
 	     tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
 	     (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
 	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
-	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)))
+	      tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
+	    (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
+	     tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F))
 		tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
 
 	err = tg3_phy_probe(tp);
 	if (err) {
 		printk(KERN_ERR PFX "(%s) phy probe failed, err %d\n",
-		       tp->pdev->slot_name, err);
+		       pci_name(tp->pdev), err);
 		/* ... but do not return immediately ... */
 	}
 
@@ -6933,11 +7524,6 @@ static int __devinit tg3_get_invariants(
 
 	if (tp->phy_id == PHY_ID_SERDES) {
 		tp->tg3_flags &= ~TG3_FLAG_USE_MI_INTERRUPT;
-
-		/* And override led_mode in case Dell ever makes
-		 * a fibre board.
-		 */
-		tp->led_mode = led_mode_three_link;
 	} else {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
 			tp->tg3_flags |= TG3_FLAG_USE_MI_INTERRUPT;
@@ -6954,7 +7540,7 @@ static int __devinit tg3_get_invariants(
 	else
 		tp->tg3_flags &= ~TG3_FLAG_USE_LINKCHG_REG;
 
-	/* The led_mode is set during tg3_phy_probe, here we might
+	/* The led_ctrl is set during tg3_phy_probe, here we might
 	 * have to force the link status polling mechanism based
 	 * upon subsystem IDs.
 	 */
@@ -6978,13 +7564,10 @@ static int __devinit tg3_get_invariants(
 	else
 		tp->tg3_flags &= ~TG3_FLAG_TXD_MBOX_HWBUG;
 
-	/* 5700 chips can get confused if TX buffers straddle the
-	 * 4GB address boundary in some cases.
+	/* It seems all chips can get confused if TX buffers
+	 * straddle the 4GB address boundary in some cases.
 	 */
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
-		tp->dev->hard_start_xmit = tg3_start_xmit_4gbug;
-	else
-		tp->dev->hard_start_xmit = tg3_start_xmit;
+	tp->dev->hard_start_xmit = tg3_start_xmit;
 
 	tp->rx_offset = 2;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
@@ -7037,10 +7620,16 @@ static int __devinit tg3_get_device_addr
 		return 0;
 #endif
 
-	if (PCI_FUNC(tp->pdev->devfn) == 0)
-		mac_offset = 0x7c;
-	else
-		mac_offset = 0xcc;
+	mac_offset = 0x7c;
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
+	    !(tp->tg3_flags & TG3_FLG2_SUN_5704)) {
+		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
+			mac_offset = 0xcc;
+		if (tg3_nvram_lock(tp))
+			tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
+		else
+			tg3_nvram_unlock(tp);
+	}
 
 	/* First try to get it from MAC address mailbox. */
 	tg3_read_mem(tp, NIC_SRAM_MAC_ADDR_HIGH_MBOX, &hi);
@@ -7184,50 +7773,9 @@ static int __devinit tg3_test_dma(struct
 		goto out_nofree;
 	}
 
-	if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) == 0) {
-		tp->dma_rwctrl =
-			(0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
-			(0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
-			(0x7 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
-			(0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
-			(0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705)
-			tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA
-					    << DMA_RWCTRL_MIN_DMA_SHIFT);
-	} else {
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
-			tp->dma_rwctrl =
-				(0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
-				(0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
-				(0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
-				(0x7 << DMA_RWCTRL_READ_WATER_SHIFT) |
-				(0x00 << DMA_RWCTRL_MIN_DMA_SHIFT);
-		else
-			tp->dma_rwctrl =
-				(0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
-				(0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT) |
-				(0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
-				(0x3 << DMA_RWCTRL_READ_WATER_SHIFT) |
-				(0x0f << DMA_RWCTRL_MIN_DMA_SHIFT);
-
-		/* Wheee, some more chip bugs... */
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
-			u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
-
-			if (ccval == 0x6 || ccval == 0x7)
-				tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
-		}
-	}
-
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
-		tp->dma_rwctrl &= ~(DMA_RWCTRL_MIN_DMA
-				    << DMA_RWCTRL_MIN_DMA_SHIFT);
+	tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
+			  (0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
 
-	/* We don't do this on x86 because it seems to hurt performace.
-	 * It does help things on other platforms though.
-	 */
 #ifndef CONFIG_X86
 	{
 		u8 byte;
@@ -7239,55 +7787,63 @@ static int __devinit tg3_test_dma(struct
 		else
 			cacheline_size = (int) byte * 4;
 
-		tp->dma_rwctrl &= ~(DMA_RWCTRL_READ_BNDRY_MASK |
-				    DMA_RWCTRL_WRITE_BNDRY_MASK);
-
 		switch (cacheline_size) {
 		case 16:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_16 |
-				 DMA_RWCTRL_WRITE_BNDRY_16);
-			break;
-
 		case 32:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_32 |
-				 DMA_RWCTRL_WRITE_BNDRY_32);
-			break;
-
 		case 64:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_64 |
-				 DMA_RWCTRL_WRITE_BNDRY_64);
-			break;
-
 		case 128:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_128 |
-				 DMA_RWCTRL_WRITE_BNDRY_128);
-			break;
-
+			if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+			    !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+				tp->dma_rwctrl |=
+					DMA_RWCTRL_WRITE_BNDRY_384_PCIX;
+				break;
+			} else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+				tp->dma_rwctrl &=
+					~(DMA_RWCTRL_PCI_WRITE_CMD);
+				tp->dma_rwctrl |=
+					DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
+				break;
+			}
+			/* fallthrough */
 		case 256:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_256 |
-				 DMA_RWCTRL_WRITE_BNDRY_256);
-			break;
-
-		case 512:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_512 |
-				 DMA_RWCTRL_WRITE_BNDRY_512);
-			break;
-
-		case 1024:
-			tp->dma_rwctrl |=
-				(DMA_RWCTRL_READ_BNDRY_1024 |
-				 DMA_RWCTRL_WRITE_BNDRY_1024);
-			break;
+			if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+			    !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+				tp->dma_rwctrl |=
+					DMA_RWCTRL_WRITE_BNDRY_256;
+			else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+				tp->dma_rwctrl |=
+					DMA_RWCTRL_WRITE_BNDRY_256_PCIX;
 		};
 	}
 #endif
 
+	if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+		tp->dma_rwctrl |= 0x001f0000;
+	} else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
+			tp->dma_rwctrl |= 0x003f0000;
+		else
+			tp->dma_rwctrl |= 0x003f000f;
+	} else {
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+			u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
+
+			if (ccval == 0x6 || ccval == 0x7)
+				tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
+
+			/* Set bit 23 to renable PCIX hw bug fix */
+			tp->dma_rwctrl |= 0x009f0000;
+		} else {
+			tp->dma_rwctrl |= 0x001b000f;
+		}
+	}
+
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704)
+		tp->dma_rwctrl &= 0xfffffff0;
+
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 		/* Remove this if it causes problems for some boards. */
@@ -7430,6 +7986,7 @@ static char * __devinit tg3_phy_string(s
 	case PHY_ID_BCM5703:	return "5703";
 	case PHY_ID_BCM5704:	return "5704";
 	case PHY_ID_BCM5705:	return "5705";
+	case PHY_ID_BCM5750:	return "5750";
 	case PHY_ID_BCM8002:	return "8002";
 	case PHY_ID_SERDES:	return "serdes";
 	default:		return "unknown";
@@ -7527,6 +8084,7 @@ static int __devinit tg3_init_one(struct
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -7536,7 +8094,7 @@ static int __devinit tg3_init_one(struct
 	dev->vlan_rx_kill_vid = tg3_vlan_rx_kill_vid;
 #endif
 
-	tp = dev->priv;
+	tp = netdev_priv(dev);
 	tp->pdev = pdev;
 	tp->dev = dev;
 	tp->pm_cap = pm_cap;
@@ -7604,6 +8162,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) {
@@ -7612,7 +8173,8 @@ static int __devinit tg3_init_one(struct
 		goto err_out_iounmap;
 	}
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
 		tp->bufmgr_config.mbuf_read_dma_low_water =
 			DEFAULT_MB_RDMA_LOW_WATER_5705;
 		tp->bufmgr_config.mbuf_mac_rx_low_water =
@@ -7625,8 +8187,8 @@ static int __devinit tg3_init_one(struct
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 ||
 	    tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 ||
-	    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 ||
-	    (tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
+	    ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 &&
+	     GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5750)) {
 		tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE;
 	} else {
 		tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE;
@@ -7718,13 +8280,26 @@ static int __devinit tg3_init_one(struct
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? '\n' : ':');
 
+	printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] "
+	       "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
+	       "TSOcap[%d] \n",
+	       dev->name,
+	       (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0,
+	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
+	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
+	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
+	       (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
+	       (tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
+	       (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
+	       (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
+
 	return 0;
 
 err_out_iounmap:
 	iounmap((void *) tp->regs);
 
 err_out_free_dev:
-	kfree(dev);
+	free_netdev(dev);
 
 err_out_free_res:
 	pci_release_regions(pdev);
@@ -7740,9 +8315,11 @@ static void __devexit tg3_remove_one(str
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	if (dev) {
+		struct tg3 *tp = netdev_priv(dev);
+
 		unregister_netdev(dev);
-		iounmap((void *) ((struct tg3 *)(dev->priv))->regs);
-		kfree(dev);
+		iounmap((void *)tp->regs);
+		free_netdev(dev);
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
 		pci_set_drvdata(pdev, NULL);
@@ -7752,7 +8329,7 @@ static void __devexit tg3_remove_one(str
 static int tg3_suspend(struct pci_dev *pdev, u32 state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
 	if (!netif_running(dev))
@@ -7799,12 +8376,14 @@ static int tg3_suspend(struct pci_dev *p
 static int tg3_resume(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	struct tg3 *tp = dev->priv;
+	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
 	if (!netif_running(dev))
 		return 0;
 
+	pci_restore_state(tp->pdev, tp->pci_cfg_state);
+
 	err = tg3_set_power_state(tp, 0);
 	if (err)
 		return err;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/tg3.h linux-2.4.27-rc4/drivers/net/tg3.h
--- linux-2.4.26/drivers/net/tg3.h	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/tg3.h	2004-07-30 16:29:23.000000000 +0000
@@ -1,8 +1,9 @@
 /* $Id: tg3.h,v 1.37.2.32 2002/03/11 12:18:18 davem Exp $
  * tg3.h: Definitions for Broadcom Tigon3 ethernet driver.
  *
- * Copyright (C) 2001, 2002 David S. Miller (davem@redhat.com)
+ * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
+ * Copyright (C) 2004 Sun Microsystems Inc.
  */
 
 #ifndef _T3_H
@@ -116,14 +117,20 @@
 #define  CHIPREV_ID_5704_A0		 0x2000
 #define  CHIPREV_ID_5704_A1		 0x2001
 #define  CHIPREV_ID_5704_A2		 0x2002
+#define  CHIPREV_ID_5704_A3		 0x2003
 #define  CHIPREV_ID_5705_A0		 0x3000
 #define  CHIPREV_ID_5705_A1		 0x3001
+#define  CHIPREV_ID_5705_A2		 0x3002
+#define  CHIPREV_ID_5705_A3		 0x3003
+#define  CHIPREV_ID_5750_A0		 0x4000
+#define  CHIPREV_ID_5750_A1		 0x4001
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
 #define   ASIC_REV_5703			 0x01
 #define   ASIC_REV_5704			 0x02
 #define   ASIC_REV_5705			 0x03
+#define   ASIC_REV_5750			 0x04
 #define  GET_CHIP_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX		 0x70
 #define   CHIPREV_5700_BX		 0x71
@@ -144,8 +151,11 @@
 #define  DMA_RWCTRL_READ_BNDRY_MASK	 0x00000700
 #define  DMA_RWCTRL_READ_BNDRY_DISAB	 0x00000000
 #define  DMA_RWCTRL_READ_BNDRY_16	 0x00000100
+#define  DMA_RWCTRL_READ_BNDRY_128_PCIX	 0x00000100
 #define  DMA_RWCTRL_READ_BNDRY_32	 0x00000200
+#define  DMA_RWCTRL_READ_BNDRY_256_PCIX	 0x00000200
 #define  DMA_RWCTRL_READ_BNDRY_64	 0x00000300
+#define  DMA_RWCTRL_READ_BNDRY_384_PCIX	 0x00000300
 #define  DMA_RWCTRL_READ_BNDRY_128	 0x00000400
 #define  DMA_RWCTRL_READ_BNDRY_256	 0x00000500
 #define  DMA_RWCTRL_READ_BNDRY_512	 0x00000600
@@ -153,8 +163,11 @@
 #define  DMA_RWCTRL_WRITE_BNDRY_MASK	 0x00003800
 #define  DMA_RWCTRL_WRITE_BNDRY_DISAB	 0x00000000
 #define  DMA_RWCTRL_WRITE_BNDRY_16	 0x00000800
+#define  DMA_RWCTRL_WRITE_BNDRY_128_PCIX 0x00000800
 #define  DMA_RWCTRL_WRITE_BNDRY_32	 0x00001000
+#define  DMA_RWCTRL_WRITE_BNDRY_256_PCIX 0x00001000
 #define  DMA_RWCTRL_WRITE_BNDRY_64	 0x00001800
+#define  DMA_RWCTRL_WRITE_BNDRY_384_PCIX 0x00001800
 #define  DMA_RWCTRL_WRITE_BNDRY_128	 0x00002000
 #define  DMA_RWCTRL_WRITE_BNDRY_256	 0x00002800
 #define  DMA_RWCTRL_WRITE_BNDRY_512	 0x00003000
@@ -170,6 +183,9 @@
 #define  DMA_RWCTRL_PCI_READ_CMD_SHIFT	 24
 #define  DMA_RWCTRL_PCI_WRITE_CMD	 0xf0000000
 #define  DMA_RWCTRL_PCI_WRITE_CMD_SHIFT	 28
+#define  DMA_RWCTRL_WRITE_BNDRY_64_PCIE	 0x10000000
+#define  DMA_RWCTRL_WRITE_BNDRY_128_PCIE 0x30000000
+#define  DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE 0x70000000
 #define TG3PCI_PCISTATE			0x00000070
 #define  PCISTATE_FORCE_RESET		 0x00000001
 #define  PCISTATE_INT_NOT_ACTIVE	 0x00000002
@@ -202,7 +218,11 @@
 #define TG3PCI_STD_RING_PROD_IDX	0x00000098 /* 64-bit */
 #define TG3PCI_RCV_RET_RING_CON_IDX	0x000000a0 /* 64-bit */
 #define TG3PCI_SND_PROD_IDX		0x000000a8 /* 64-bit */
-/* 0xb0 --> 0x100 unused */
+/* 0xb0 --> 0xb8 unused */
+#define TG3PCI_DUAL_MAC_CTRL		0x000000b8
+#define  DUAL_MAC_CTRL_CH_MASK		 0x00000003
+#define  DUAL_MAC_CTRL_ID		 0x00000004
+/* 0xbc --> 0x100 unused */
 
 /* 0x100 --> 0x200 unused */
 
@@ -334,9 +354,12 @@
 #define  LED_CTRL_100MBPS_STATUS	 0x00000100
 #define  LED_CTRL_10MBPS_STATUS		 0x00000200
 #define  LED_CTRL_TRAFFIC_STATUS	 0x00000400
-#define  LED_CTRL_MAC_MODE		 0x00000000
-#define  LED_CTRL_PHY_MODE_1		 0x00000800
-#define  LED_CTRL_PHY_MODE_2		 0x00001000
+#define  LED_CTRL_MODE_MAC		 0x00000000
+#define  LED_CTRL_MODE_PHY_1		 0x00000800
+#define  LED_CTRL_MODE_PHY_2		 0x00001000
+#define  LED_CTRL_MODE_SHASTA_MAC	 0x00002000
+#define  LED_CTRL_MODE_SHARED		 0x00004000
+#define  LED_CTRL_MODE_COMBO		 0x00008000
 #define  LED_CTRL_BLINK_RATE_MASK	 0x7ff80000
 #define  LED_CTRL_BLINK_RATE_SHIFT	 19
 #define  LED_CTRL_BLINK_PER_OVERRIDE	 0x00080000
@@ -497,8 +520,50 @@
 #define MAC_EXTADDR_11_HIGH		0x00000588
 #define MAC_EXTADDR_11_LOW		0x0000058c
 #define MAC_SERDES_CFG			0x00000590
+#define  MAC_SERDES_CFG_EDGE_SELECT	 0x00001000
 #define MAC_SERDES_STAT			0x00000594
-/* 0x598 --> 0x600 unused */
+/* 0x598 --> 0x5b0 unused */
+#define SG_DIG_CTRL			0x000005b0
+#define  SG_DIG_USING_HW_AUTONEG	 0x80000000
+#define  SG_DIG_SOFT_RESET		 0x40000000
+#define  SG_DIG_DISABLE_LINKRDY		 0x20000000
+#define  SG_DIG_CRC16_CLEAR_N		 0x01000000
+#define  SG_DIG_EN10B			 0x00800000
+#define  SG_DIG_CLEAR_STATUS		 0x00400000
+#define  SG_DIG_LOCAL_DUPLEX_STATUS	 0x00200000
+#define  SG_DIG_LOCAL_LINK_STATUS	 0x00100000
+#define  SG_DIG_SPEED_STATUS_MASK	 0x000c0000
+#define  SG_DIG_SPEED_STATUS_SHIFT	 18
+#define  SG_DIG_JUMBO_PACKET_DISABLE	 0x00020000
+#define  SG_DIG_RESTART_AUTONEG		 0x00010000
+#define  SG_DIG_FIBER_MODE		 0x00008000
+#define  SG_DIG_REMOTE_FAULT_MASK	 0x00006000
+#define  SG_DIG_PAUSE_MASK		 0x00001800
+#define  SG_DIG_GBIC_ENABLE		 0x00000400
+#define  SG_DIG_CHECK_END_ENABLE	 0x00000200
+#define  SG_DIG_SGMII_AUTONEG_TIMER	 0x00000100
+#define  SG_DIG_CLOCK_PHASE_SELECT	 0x00000080
+#define  SG_DIG_GMII_INPUT_SELECT	 0x00000040
+#define  SG_DIG_MRADV_CRC16_SELECT	 0x00000020
+#define  SG_DIG_COMMA_DETECT_ENABLE	 0x00000010
+#define  SG_DIG_AUTONEG_TIMER_REDUCE	 0x00000008
+#define  SG_DIG_AUTONEG_LOW_ENABLE	 0x00000004
+#define  SG_DIG_REMOTE_LOOPBACK		 0x00000002
+#define  SG_DIG_LOOPBACK		 0x00000001
+#define SG_DIG_STATUS			0x000005b4
+#define  SG_DIG_CRC16_BUS_MASK		 0xffff0000
+#define  SG_DIG_PARTNER_FAULT_MASK	 0x00600000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_ASYM_PAUSE	 0x00100000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_PAUSE_CAPABLE	 0x00080000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_HALF_DUPLEX	 0x00040000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_FULL_DUPLEX	 0x00020000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_PARTNER_NEXT_PAGE	 0x00010000 /* If !MRADV_CRC16_SELECT */
+#define  SG_DIG_AUTONEG_STATE_MASK	 0x00000ff0
+#define  SG_DIG_COMMA_DETECTOR		 0x00000008
+#define  SG_DIG_MAC_ACK_STATUS		 0x00000004
+#define  SG_DIG_AUTONEG_COMPLETE	 0x00000002
+#define  SG_DIG_AUTONEG_ERROR		 0x00000001
+/* 0x5b8 --> 0x600 unused */
 #define MAC_TX_MAC_STATE_BASE		0x00000600 /* 16 bytes */
 #define MAC_RX_MAC_STATE_BASE		0x00000610 /* 20 bytes */
 /* 0x624 --> 0x800 unused */
@@ -1332,6 +1397,9 @@
 #define  SWARB_REQ3			 0x00008000
 #define    NVRAM_BUFFERED_PAGE_SIZE	   264
 #define    NVRAM_BUFFERED_PAGE_POS	   9
+#define NVRAM_ACCESS			0x00007024
+#define  ACCESS_ENABLE			 0x00000001
+#define  ACCESS_WR_ENABLE		 0x00000002
 /* 0x7024 --> 0x7400 unused */
 
 /* 0x7400 --> 0x8000 unused */
@@ -1355,11 +1423,9 @@
 
 #define NIC_SRAM_DATA_CFG			0x00000b58
 #define  NIC_SRAM_DATA_CFG_LED_MODE_MASK	 0x0000000c
-#define  NIC_SRAM_DATA_CFG_LED_MODE_UNKNOWN	 0x00000000
-#define  NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD	 0x00000004
-#define  NIC_SRAM_DATA_CFG_LED_OPEN_DRAIN	 0x00000004
-#define  NIC_SRAM_DATA_CFG_LED_LINK_SPD		 0x00000008
-#define  NIC_SRAM_DATA_CFG_LED_OUTPUT		 0x00000008
+#define  NIC_SRAM_DATA_CFG_LED_MODE_MAC		 0x00000000
+#define  NIC_SRAM_DATA_CFG_LED_MODE_PHY_1	 0x00000004
+#define  NIC_SRAM_DATA_CFG_LED_MODE_PHY_2	 0x00000008
 #define  NIC_SRAM_DATA_CFG_PHY_TYPE_MASK	 0x00000030
 #define  NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN	 0x00000000
 #define  NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER	 0x00000010
@@ -1386,7 +1452,9 @@
 #define NIC_SRAM_FW_ASF_STATUS_MBOX	0x00000c00
 #define NIC_SRAM_FW_DRV_STATE_MBOX	0x00000c04
 #define  DRV_STATE_START		 0x00000001
+#define  DRV_STATE_START_DONE		 0x80000001
 #define  DRV_STATE_UNLOAD		 0x00000002
+#define  DRV_STATE_UNLOAD_DONE		 0x80000002
 #define  DRV_STATE_WOL			 0x00000003
 #define  DRV_STATE_SUSPEND		 0x00000004
 
@@ -1395,6 +1463,14 @@
 #define NIC_SRAM_MAC_ADDR_HIGH_MBOX	0x00000c14
 #define NIC_SRAM_MAC_ADDR_LOW_MBOX	0x00000c18
 
+#define NIC_SRAM_DATA_CFG_2		0x00000d38
+
+#define  SHASTA_EXT_LED_MODE_MASK	 0x00018000
+#define  SHASTA_EXT_LED_LEGACY		 0x00000000
+#define  SHASTA_EXT_LED_SHARED		 0x00008000
+#define  SHASTA_EXT_LED_MAC		 0x00010000
+#define  SHASTA_EXT_LED_COMBO		 0x00018000
+
 #define NIC_SRAM_RX_MINI_BUFFER_DESC	0x00001000
 
 #define NIC_SRAM_DMA_DESC_POOL_BASE	0x00002000
@@ -1756,12 +1832,6 @@ struct tg3_hw_stats {
 	u8				__reserved4[0xb00-0x9c0];
 };
 
-enum phy_led_mode {
-	led_mode_auto,
-	led_mode_three_link,
-	led_mode_link10
-};
-
 /* 'mapping' is superfluous as the chip does not write into
  * the tx/rx post rings so we could just fetch it from there.
  * But the cache behavior is better how we are doing it now.
@@ -1817,6 +1887,89 @@ struct tg3_bufmgr_config {
 	u32		dma_high_water;
 };
 
+struct tg3_ethtool_stats {
+	/* Statistics maintained by Receive MAC. */
+	u64 	    	rx_octets;
+	u64		rx_fragments;
+	u64		rx_ucast_packets;
+	u64		rx_mcast_packets;
+	u64		rx_bcast_packets;
+	u64		rx_fcs_errors;
+	u64		rx_align_errors;
+	u64		rx_xon_pause_rcvd;
+	u64		rx_xoff_pause_rcvd;
+	u64		rx_mac_ctrl_rcvd;
+	u64		rx_xoff_entered;
+	u64		rx_frame_too_long_errors;
+	u64		rx_jabbers;
+	u64		rx_undersize_packets;
+	u64		rx_in_length_errors;
+	u64		rx_out_length_errors;
+	u64		rx_64_or_less_octet_packets;
+	u64		rx_65_to_127_octet_packets;
+	u64		rx_128_to_255_octet_packets;
+	u64		rx_256_to_511_octet_packets;
+	u64		rx_512_to_1023_octet_packets;
+	u64		rx_1024_to_1522_octet_packets;
+	u64		rx_1523_to_2047_octet_packets;
+	u64		rx_2048_to_4095_octet_packets;
+	u64		rx_4096_to_8191_octet_packets;
+	u64		rx_8192_to_9022_octet_packets;
+
+	/* Statistics maintained by Transmit MAC. */
+	u64		tx_octets;
+	u64		tx_collisions;
+	u64		tx_xon_sent;
+	u64		tx_xoff_sent;
+	u64		tx_flow_control;
+	u64		tx_mac_errors;
+	u64		tx_single_collisions;
+	u64		tx_mult_collisions;
+	u64		tx_deferred;
+	u64		tx_excessive_collisions;
+	u64		tx_late_collisions;
+	u64		tx_collide_2times;
+	u64		tx_collide_3times;
+	u64		tx_collide_4times;
+	u64		tx_collide_5times;
+	u64		tx_collide_6times;
+	u64		tx_collide_7times;
+	u64		tx_collide_8times;
+	u64		tx_collide_9times;
+	u64		tx_collide_10times;
+	u64		tx_collide_11times;
+	u64		tx_collide_12times;
+	u64		tx_collide_13times;
+	u64		tx_collide_14times;
+	u64		tx_collide_15times;
+	u64		tx_ucast_packets;
+	u64		tx_mcast_packets;
+	u64		tx_bcast_packets;
+	u64		tx_carrier_sense_errors;
+	u64		tx_discards;
+	u64		tx_errors;
+
+	/* Statistics maintained by Receive List Placement. */
+	u64		dma_writeq_full;
+	u64		dma_write_prioq_full;
+	u64		rxbds_empty;
+	u64		rx_discards;
+	u64		rx_errors;
+	u64		rx_threshold_hit;
+
+	/* Statistics maintained by Send Data Initiator. */
+	u64		dma_readq_full;
+	u64		dma_read_prioq_full;
+	u64		tx_comp_queue_full;
+
+	/* Statistics maintained by Host Coalescing. */
+	u64		ring_set_send_prod_index;
+	u64		ring_status_update;
+	u64		nic_irqs;
+	u64		nic_avoided_irqs;
+	u64		nic_tx_threshold_hit;
+};
+
 struct tg3 {
 	/* begin "general, frequently-used members" cacheline section */
 
@@ -1880,6 +2033,9 @@ struct tg3 {
 	/* begin "everything else" cacheline(s) section */
 	struct net_device_stats		net_stats;
 	struct net_device_stats		net_stats_prev;
+	struct tg3_ethtool_stats	estats;
+	struct tg3_ethtool_stats	estats_prev;
+
 	unsigned long			phy_crc_errors;
 
 	u32				rx_offset;
@@ -1929,6 +2085,10 @@ struct tg3 {
 #define TG3_FLG2_TSO_CAPABLE		0x00000020
 #define TG3_FLG2_PHY_ADC_BUG		0x00000040
 #define TG3_FLG2_PHY_5704_A0_BUG	0x00000080
+#define TG3_FLG2_PHY_BER_BUG		0x00000100
+#define TG3_FLG2_PCI_EXPRESS		0x00000200
+#define TG3_FLG2_ASF_NEW_HANDSHAKE	0x00000400
+#define TG3_FLG2_HW_AUTONEG		0x00000800
 
 	u32				split_mode_max_reqs;
 #define SPLIT_MODE_5704_MAX_REQ		3
@@ -1974,6 +2134,7 @@ struct tg3 {
 #define PHY_ID_BCM5703			0x60008160
 #define PHY_ID_BCM5704			0x60008190
 #define PHY_ID_BCM5705			0x600081a0
+#define PHY_ID_BCM5750			0x60008180
 #define PHY_ID_BCM8002			0x60010140
 #define PHY_ID_SERDES			0xfeedbee0
 #define PHY_ID_INVALID			0xffffffff
@@ -1983,7 +2144,7 @@ struct tg3 {
 #define PHY_REV_BCM5401_C0		0x6
 #define PHY_REV_BCM5411_X0		0x1 /* Found on Netgear GA302T */
 
-	enum phy_led_mode		led_mode;
+	u32				led_ctrl;
 
 	char				board_part_number[24];
 	u32				nic_sram_data_cfg;
@@ -1997,7 +2158,7 @@ struct tg3 {
 	((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \
 	 (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
 	 (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
-	 (X) == PHY_ID_BCM5705 || \
+	 (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \
 	 (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
 
 	struct tg3_hw_stats		*hw_stats;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/tulip/ChangeLog linux-2.4.27-rc4/drivers/net/tulip/ChangeLog
--- linux-2.4.26/drivers/net/tulip/ChangeLog	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/tulip/ChangeLog	1970-01-01 00:00:00.000000000 +0000
@@ -1,563 +0,0 @@
-2002-09-18  Ryan Bradetich  <rbradetich@uswest.net>
-
-	tulip hppa support:
-	* eeprom.c (tulip_build_fake_mediatable): new function
-	(tulip_parse_eeprom): call it, when no media table
-	* interrupt.c (phy_interrupt): new function
-	(tulip_interrupt): call it, before checking for no-irq-work
-	* tulip.c: add HAS_PHY_IRQ chip feature flag.
-	add csr12_shadow to tulip_private struct, only for hppa currently.
-	* tulip_core (tulip_init_one): support hppa wonky eeproms
-
-2002-05-11  Juan Quintela  <quintela@mandrakesoft.com>
-
-	* 21142.c (t21142_lnk_change): Revert earlier patch
-	to always reset phy; only conditionally do so now.
-
-2002-05-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core (tulip_pci_tbl): Add new "comet"
-	pci id.  Contributed by Ohta Kyuma.
-
-2002-03-07  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core (tulip_mwi_config): Use new PCI API functions
-	for enabling and disabled Memory-Write-Invalidate
-	PCI transaction.
-	Fix bugs in tulip MWI config also.
-
-2002-02-07  Uwe Bonnes  <bon@elektron.ikp.physik.tu-darmstadt.de>
-
-	* tulip_core (tulip_pci_tbl[]):
-	Add PCI id for comet tulip clone.
-
-2001-12-19  John Zielinski
-
-	* tulip_core.c (tulip_up, tulip_init_one):
-	More places to revert PHY autoconfiguration bit removal.
-
-2001-12-16  Andrew Lambeth  <wal@vmware.com>
-
-	* tulip_core.c (tulip_start_xmit): Use the more-portable
-	spin_lock_irqsave.
-
-2001-11-13  David S. Miller  <davem@redhat.com>
-
-	* tulip_core.c (tulip_mwi_config): Kill unused label early_out.
-
-2001-11-06  Richard Mortimer  <richm@oldelvet.netscapeonline.co.uk>
-
-	* tulip_core.c:  Correct set of values to mask out of csr0,
-	for DM9102A chips.  Limit burst/alignment of DM9102A chips
-	on Sparcs.
-
-2001-11-06  Jun Sun  <jsun@mvista.com>
-
-	* tulip_core.c:  Support finding MAC address on
-	two MIPS boards, DDB5476 and DDB5477.
-
-2001-11-06  Kevin B. Hendricks  <khendricks@ivey.uwo.ca>
-
-	* Makefile, tulip.h, tulip_core.c, pnic2.c, 21142.c:
-	Fixes for PNIC II support.
-
-2001-11-06  David S. Miller  <davem@redhat.com>
-
-	* tulip_core.c: Support reading MAC address from
-	Sparc OBP property local-mac-address.
-
-2001-07-17  Erik A. Hendriks  <hendriks@lanl.gov>
-
-	* 21142.c: Merge fix from tulip.c 0.92w which prevents the
-	overwriting of csr6 bits we want to preserve.
-
-2001-07-10  Jeff Golds  <jgolds@resilience.com>
-
-	* tulip_core.c: Fix two comments
-
-2001-07-06  Stephen Degler  <sdegler@degler.net>
-
-	* media.c:
-	The media selection process at the end of NWAY is busted
-	because for the case of MII/SYM it needs to be:
-
-        csr13 <- 0
-        csr14 <- 0
-        csr6 <-  the value calculated is okay.
-
-	In the other media cases csr14 is computed by
-	t21142_csr14val[dev->if_port], which seems ok.  The value of
-	zero as opposed to 3FFFFF comes straight from appendix D of the
-	21143 data book, and it makes logical sense because you're
-	bypassing all the SIA interface when you usa MII or SYM (see
-	figure 1-1 in the data book if your're visually oriented)
-
-2001-07-03  Jeff Golds  <jgolds@resilience.com>
-
-	* tulip_core.c (tulip_clean_tx_ring):
-	Clear status for in-progress Tx's, and count
-	Tx errors for all packets being released.
-
-2001-06-16  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip.h, tulip_core.c:
-	Integrate MMIO support from devel branch, but default
-	it to off for stable kernel and driver series.
-
-2001-06-16  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_init_one):
-	Free descriptor rings on error.
-
-2001-06-16  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_mwi_config, tulip_init_one):
-	Large update to csr0 bus configuration code.  This is not stable
-	yet, so it is only conditionally enabled, via CONFIG_TULIP_MWI.
-
-2001-06-16  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c:
-	Initialize timer in tulip_init_one and tulip_down,
-	not in tulip_up.
-
-2001-06-14  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c:
-	- Update tulip_suspend, tulip_resume for new PCI PM API.
-	- Surround suspend/resume code with CONFIG_PM.
-
-2001-06-12  Jeff Golds  <jgolds@resilience.com>
-
-	* tulip_core.c:
-	- Reset sw ring ptrs in tulip_up.  Fixes PM resume case.
-	- Clean rx and tx rings on device down.
-
-2001-06-05  David Miller  <davem@redhat.com>
-
-	* tulip_core (set_rx_mode):  Do not use set_bit
-	on an integer variable.  Also fix endianness issue.
-
-2001-06-04  Jeff Garzik  <jgarzik@pobox.com>
-
-	* interrupt.c:
-	Simplify rx processing when CONFIG_NET_HW_FLOWCONTROL is
-	active, and in the process fix a bug where flow control
-	and low load caused rx not to be acknowledged properly.
-
-2001-06-01  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip.h:
-	- Remove tulip_outl_csr helper, redundant.
-	- Add tulip_start_rxtx inline helper.
-	- tulip_stop_rxtx helper: Add synchronization. Always use current
-	  csr6 value, instead of tp->csr6 value or value passed as arg.
-	- tulip_restart_rxtx helper: Add synchronization. Always
-	  use tp->csr6 for desired mode, not value passed as arg.
-	- New RxOn, TxOn, RxTx constants for csr6 modes.
-	- Remove now-redundant constants csr6_st, csr6_sr.
-
-	* 21142.c, interrupt.c, media.c, pnic.c, tulip_core.c:
-	Update for above rxtx helper changes.
-
-	* interrupt.c:
-	- whitespace cleanup around #ifdef CONFIG_NET_HW_FLOWCONTROL,
-	  convert tabs to spaces.
-	- Move tp->stats.rx_missed_errors update outside the ifdef.
-
-2001-05-18  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Added ethtool support.
-	  ETHTOOL_GDRVINFO ioctl only, for now.
-
-2001-05-14  Robert Olsson <Robert.Olsson@data.slu.se>
-
-	* Restored HW_FLOWCONTROL from Linux 2.1 series tulip (ANK)
-	  plus Jamal's NETIF_RX_* feedback control.
-
-2001-05-14  Robert Olsson <Robert.Olsson@data.slu.se>
-
-	* Added support for 21143's Interrupt Mitigation.
-	  Jamal original instigator.
-
-2001-05-14  Robert Olsson <Robert.Olsson@data.slu.se>
-
-	* tulip_refill_rx prototype added to tulip.h
-
-2001-05-13  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Remove HAS_PCI_MWI flag from Comet, untested.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c, tulip.h: Remove Conexant PCI id, no chip
-	docs are available to fix problems with support.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_init_one): Do not call
-	unregister_netdev in error cleanup.  Remnant of old
-	usage of init_etherdev.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* media.c (tulip_find_mii): Simple write the updated BMCR
-	twice, as it seems the best thing to do for both broken and
-	sane chips.
-	If the mii_advert value, as read from MII_ADVERTISE, is zero,
-	then generate a value we should advertise from the capability
-	bits in BMSR.
-	Fill in tp->advertising for all cases.
-	Just to be safe, clear all unwanted bits.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (private_ioctl):  Fill in tp->advertising
-	when advertising value is changed by the user.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Mark Comet chips as needed the updated MWI
-	csr0 configuration.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* media.c, tulip_core.c:  Move MII scan into
-	from inlined inside tulip_init_one to new function
-	tulip_find_mii in media.c.
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* media.c (tulip_check_duplex):
-	Only restart Rx/Tx engines if they are active
-	(and csr6 changes)
-
-2001-05-12  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_mwi_config):
-	Clamp values read from PCI cache line size register to
-	values acceptable to tulip chip.  Done for safety and
-	-almost- certainly unneeded.
-
-2001-05-11  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_init_one):
-	Instead of unconditionally enabling autonegotiation, disable
-	autonegotiation if not using the default port.  Further,
-	flip the nway bit immediately, and then update the
-	speed/duplex in a separate MII transaction.  We do this
-	because some boards require that nway be disabled separately,
-	before media selection is forced.
-
-	TODO: Investigate if we can simply write the same value
-	to BMCR twice, to avoid setting unnecessarily changing
-	phy settings.
-
-2001-05-11  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip.h, tulip_core.c:  If HAS_PCI_MWI is set for a
-	given chip, adjust the csr0 values not according to
-	provided values but according to system cache line size.
-	Currently cache alignment is matched as closely to cache
-	line size as possible.  Currently programmable burst limit
-	is set (ie. never unlimited), and always equal to cache
-	alignment and system cache size.  Currently MWI bit is set
-	only if the MWI bit is present in the PCI command register.
-
-2001-05-11  Jeff Garzik  <jgarzik@pobox.com>
-
-	* media.c (tulip_select_media):
-	For media types 1 and 3, only use the provided eeprom
-	advertising value if it is non-zero.
-	(tulip_check_duplex):
-	Do not exit ASAP if full_duplex_lock is set.  This
-	ensures that the csr6 value is written if an update
-	is needed.
-
-2001-05-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	Merge PNIC-II-specific stuff from Becker's tulip.c:
-
-	* tulip.h, 21142.c (pnic2_lnk_change): new function
-	* tulip_core.c (tulip_init_one): use it
-
-	* tulip_core.c (tulip_tx_timeout): Add specific
-	debugging for PNIC2.
-
-2001-05-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_init_one): Print out
-	tulip%d instead of PCI device number, for
-	consistency.
-
-2001-05-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* Merge changes from Becker's tulip.c:
-	Fix bugs in ioctl.
-	Fix several bugs by distinguishing between MII
-	and SYM advertising values.
-	Set CSR14 autonegotiation bit for media types 2 and 4,
-	where the SIA CSR setup values are not provided.
-
-2001-05-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* media.c (tulip_select_media): Only update MII
-	advertising value if startup arg < 2.
-
-	* tulip.h: Do not enable CSR13/14/15 autoconfiguration
-	for 21041.
-
-	* tulip_core.c:
-	21041: add specific code for reset, and do not set CAC bit
-	When resetting media, for media table type 11 media, pass
-	value 2 as 'startup' arg to select_media, to avoid updating
-	MII advertising value.
-
-2001-05-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* pnic.c (pnic_check_duplex): remove
-	pnic.c (pnic_lnk_change, pnic_timer): use
-	tulip_check_duplex not pnic_check_duplex.
-
-	* media.c (tulip_check_duplex):
-	Clean up to use symbolic names instead of numeric constants.
-	Set TxThreshold mode as necessary as well as clearing it.
-	Update csr6 if csr6 changes, not simply if duplex changes.
-
-	(found by Manfred Spraul)
-
-2001-05-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* 21142.c, eeprom.c, tulip.h, tulip_core.c:
-	Remove DPRINTK as another, better method of
-	debug message printing is available.
-
-2001-05-09  Jeff Garzik  <jgarzik@pobox.com>
-
-	* 21142.c (t21142_lnk_change): Pass arg startup==1
-	to tulip_select_media, in order to force csr13 to be
-	zeroed out prior to going to full duplex mode.  Fixes
-	autonegotiation on a quad-port Znyx card.
-	(from Stephen Dengler)
-
-2001-05-09  Russell King  <rmk@arm.linux.org.uk>
-
-	* interrupt.c: Better PCI bus error reporting.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Now that dev->name is only available late
-	  in the probe, insert a hack to replace a not-evaluated
-	  "eth%d" string with an evaluated "tulip%d" string.
-	  Also, remove obvious comment and an indentation cleanup.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: If we are a module, always print out the
-	  version string.  If we are built into the kernel, only print
-	  the version string if at least one tulip is detected.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	Merged from Becker's tulip.c 0.92t:
-
-	* tulip_core.c: Add support for Conexant LANfinity.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Only suspend/resume if the interface
-	  is up and running.  Use alloc_etherdev and pci_request_regions.
-	  Spelling fix.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Remove code that existed when one or more of
-	  the following defines existed.  These defines were never used
-	  by normal users in practice: TULIP_FULL_DUPLEX,
-	  TULIP_DEFAULT_MEDIA, and TULIP_NO_MEDIA_SWITCH.
-
-	* tulip.h, eeprom.c: Move EE_* constants from tulip.h to eeprom.c.
-	* tulip.h, media.c: Move MDIO_* constants from tulip.h to media.c.
-
-	* media.c: Add barrier() to mdio_read/write's PNIC status check
-	  loops.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	Merged from Becker's tulip.c 0.92t:
-
-	* tulip.h: Add MEDIA_MASK constant for bounding medianame[]
-	  array lookups.
-	* eeprom.c, media.c, timer.c, tulip_core.c: Use it.
-
-	* media.c, tulip_core.c: mdio_{read,write} cleanup.  Since this
-	  is called [pretty much] directly from ioctl, we mask
-	  read/write arguments to limit the values passed.
-	  Added mii_lock.  Added comet_miireg2offset and better
-	  Comet-specific mdio_read/write code.	Pay closer attention
-	  to the bits we set in ioctl.	Remove spinlocks from ioctl,
-	  they are in mdio_read/write now.  Use mask to limit
-	  phy number in tulip_init_one's MII scan.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	Merged from Becker's tulip.c 0.92t:
-
-	* 21142.c, tulip_core.c: PNIC2 MAC address and NWay fixes.
-	* tulip.h: Add FullDuplex constant, used in above change.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* timer.c: Do not call netif_carrier_{on,off}, it is not used in
-	  the main tree.  Leave code in, disabled, as markers for future
-	  carrier notification.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	Merged from Becker's tulip.c 0.92t, except for the tulip.h
-	whitespace cleanup:
-
-	* interrupt.c: If Rx stops, make sure to update the
-	  multicast filter before restarting.
-	* tulip.h: Add COMET_MAC_ADDR feature flag, clean up flags.
-	  Add Accept* Rx mode bit constants.
-	  Add mc_filter[] to driver private struct.
-	* tulip_core.c: Add new Comet PCI id 0x1113:0x9511.
-	  Add COMET_MAC_ADDR feature flag to comet entry in board info array.
-	  Prefer to test COMET_MAC_ADDR flag to testing chip_id for COMET,
-	  when dealing with the Comet's MAC address.
-	  Enable Tx underrun recovery for Comet chips.
-	  Use new Accept* constants in set_rx_mode.
-	  Prefer COMET_MAC_ADDR flag test to chip_id test in set_rx_mode.
-	  Store built mc_filter for later use in intr handler by Comets.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: Use tp->cur_tx when building the
-	  setup frame, instead of assuming that the setup
-	  frame is always built in slot zero.  This case is
-	  hit during PM resume.
-
-2001-04-03  Jeff Garzik  <jgarzik@pobox.com>
-
-	* *.c: Update file headers (copyright, urls, etc.)
-	* Makefile: re-order to that chip-specific modules on own line
-	* eeprom.c: BSS/zero-init cleanup (Andrey Panin)
-	* tulip_core.c: merge medianame[] update from tulip.c.
-	  Additional arch-specific rx_copybreak, csr0 values. (various)
-
-2001-02-20  Jeff Garzik  <jgarzik@pobox.com>
-
-	* media.c (tulip_select_media): No need to initialize
-	new_csr6, all cases initialize it properly.
-
-2001-02-18  Manfred Spraul  <manfred@colorfullife.com>
-
-	* interrupt.c (tulip_refill_rx): Make public.
-	If PNIC chip stops due to lack of Rx buffers, restart it.
-	(tulip_interrupt): PNIC doesn't have a h/w timer, emulate
-	with software timers.
-	* pnic.c (pnic_check_duplex): New function, PNIC-specific
-	version of tulip_check_duplex.
-	(pnic_lnk_change): Call pnic_check_duplex.  If we use an
-	external MII, then we mustn't use the internal negotiation.
-	(pnic_timer): Support Rx refilling on work overflow in
-	interrupt handler, as PNIC doesn't support a h/w timer.
-	* tulip_core.c (tulip_tbl[]): Modify default csr6
-
-2001-02-11  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_init_one): Call pci_enable_device
-	to ensure wakeup/resource assignment before checking those
-	values.
-	(tulip_init_one): Replace PCI ids with constants from pci_id.h.
-	(tulip_suspend, tulip_resume, tulip_remove_one): Call
-	pci_power_on/off (commented out for now).
-
-2001-02-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip.h: Add CFDD_xxx bits for Tulip power management
-	* tulip_core.c (tulip_set_power_state): New function,
-	manipulating Tulip chip power state where supported.
-	(tulip_up, tulip_down, tulip_init_one): Use it.
-
-2001-02-10  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_tx_timeout): Call netif_wake_queue
-	to ensure the next Tx is always sent to us.
-
-2001-01-27  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (tulip_remove_one): Fix mem leak by freeing
-	tp->media_tbl.  Add check for !dev, reformat code appropriately.
-
-2001-01-27  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_tbl[]: Comment all entries to make order and chip_id
-	relationship more clear.
-	* tulip_pci_tbl[]: Add new Accton PCI id (COMET chipset).
-
-2001-01-16  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: static vars no longer explicitly
-	initialized to zero.
-	* eeprom.c (tulip_read_eeprom): Make sure to delay between
-	EE_ENB and EE_ENB|EE_SHIFT_CLK.  Merged from becker tulip.c.
-
-2001-01-05  Peter De Schrijver  <p2@mind.be>
-
-	* eeprom.c (tulip_parse_eeprom): Interpret a bit more of 21142
-	extended format type 3 info blocks in a tulip SROM.
-
-2001-01-03  Matti Aarnio  <matti.aarnio@zmailer.org>
-
-	* media.c (tulip_select_media): Support media types 5 and 6
-
-2001-??-??  ??
-
-	* tulip_core.c: Add comment about LanMedia needing
-	a different driver.
-	Enable workarounds for early PCI chipsets.
-	Add IA64 csr0 support, update HPPA csr0 support.
-
-2000-12-17  Alan Cox  <alan@redhat.com>
-
-        * eeprom.c, timer.c, tulip.h, tulip_core.c: Merge support
-	for the Davicom's quirks into the main tulip.
-	Patch by Tobias Ringstrom
-
-2000-11-08  Jim Studt  <jim@federated.com>
-
-	* eeprom.c (tulip_parse_eeprom):  Check array bounds for
-	medianame[] and block_name[] arrays to avoid oops due
-	to bad values returned from hardware.
-
-2000-11-02  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c (set_rx_mode): This is synchronized via
-	dev->xmit_lock, so only the queueing of the setup frame needs to
-	be locked, against tulip_interrupt.
-
-2000-11-02  Alexey Kuznetov  <kuznet@ms2.inr.ac.ru>
-
-	* timer.c (tulip_timer): Call netif_carrier_{on,off} to report
-	link state to the rest of the kernel, and userspace.
-	* interrupt.c (tulip_interrupt): Remove tx_full.
-	* tulip.h: Likewise.
-	* tulip_core.c (tulip_init_ring, tulip_start_xmit, set_rx_mode):
-	Likewise.
-
-2000-10-18  Jeff Garzik  <jgarzik@pobox.com>
-
-	* tulip_core.c: (tulip_init_one) Print out ethernet interface
-	on error.  Print out a message when pci_enable_device fails.
-	Handle DMA alloc failure.
-
-2000-10-18  Jeff Garzik  <jgarzik@pobox.com>
-
-	* Makefile: New file.
-	* tulip_core.c (tulip_init_one): Correct error messages
-	on PIO/MMIO region reserve failure.
-	(tulip_init_one) Add new check to ensure that PIO region is
-	sufficient for our needs.
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/tulip/timer.c linux-2.4.27-rc4/drivers/net/tulip/timer.c
--- linux-2.4.26/drivers/net/tulip/timer.c	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/tulip/timer.c	2004-07-30 16:24:18.000000000 +0000
@@ -211,10 +211,16 @@ void comet_timer(unsigned long data)
 	if (tulip_debug > 1)
 		printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability "
 			   "%4.4x.\n",
-			   dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8));
+			   dev->name,
+			   tulip_mdio_read(dev, tp->phys[0], 1),
+			   tulip_mdio_read(dev, tp->phys[0], 5));
 	/* mod_timer synchronizes us with potential add_timer calls
 	 * from interrupts.
 	 */
+	if (tulip_check_duplex(dev) < 0)
+		{ netif_carrier_off(dev); }
+	else
+		{ netif_carrier_on(dev); }
 	mod_timer(&tp->timer, RUN_AT(next_tick));
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/tulip/tulip_core.c linux-2.4.27-rc4/drivers/net/tulip/tulip_core.c
--- linux-2.4.26/drivers/net/tulip/tulip_core.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/tulip/tulip_core.c	2004-07-30 16:29:18.000000000 +0000
@@ -176,7 +176,7 @@ struct tulip_chip_table tulip_tbl[] = {
 
   /* COMET */
   { "ADMtek Comet", 256, 0x0001abef,
-	MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer },
+	HAS_MII | MC_HASH_ONLY | COMET_MAC_ADDR, comet_timer },
 
   /* COMPEX9881 */
   { "Compex 9881 PMAC", 128, 0x0001ebef,
@@ -226,6 +226,7 @@ static struct pci_device_id tulip_pci_tb
 	{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
 	{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+	{ 0x1186, 0x1541, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1186, 0x1561, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
@@ -320,8 +321,8 @@ static void tulip_up(struct net_device *
 	tp->dirty_rx = tp->dirty_tx = 0;
 
 	if (tp->flags & MC_HASH_ONLY) {
-		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
-		u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
+		u32 addr_low = le32_to_cpu(get_unaligned((u32 *)dev->dev_addr));
+		u32 addr_high = le16_to_cpu(get_unaligned((u16 *)(dev->dev_addr+4)));
 		if (tp->chip_id == AX88140) {
 			outl(0, ioaddr + CSR13);
 			outl(addr_low,  ioaddr + CSR14);
@@ -1544,8 +1545,8 @@ static int __devinit tulip_init_one (str
 		}
 	} else if (chip_idx == COMET) {
 		/* No need to read the EEPROM. */
-		put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
-		put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
+		put_unaligned(cpu_to_le32(inl(ioaddr + 0xA4)), (u32 *)dev->dev_addr);
+		put_unaligned(cpu_to_le16(inl(ioaddr + 0xA8)), (u16 *)(dev->dev_addr + 4));
 		for (i = 0; i < 6; i ++)
 			sum += dev->dev_addr[i];
 	} else {
@@ -1884,11 +1885,11 @@ static void __devexit tulip_remove_one (
 		return;
 
 	tp = dev->priv;
+	unregister_netdev (dev);
 	pci_free_consistent (pdev,
 			     sizeof (struct tulip_rx_desc) * RX_RING_SIZE +
 			     sizeof (struct tulip_tx_desc) * TX_RING_SIZE,
 			     tp->rx_ring, tp->rx_ring_dma);
-	unregister_netdev (dev);
 	if (tp->mtable)
 		kfree (tp->mtable);
 #ifndef USE_IO_OPS
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/tun.c linux-2.4.27-rc4/drivers/net/tun.c
--- linux-2.4.26/drivers/net/tun.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/tun.c	2004-07-30 16:28:12.000000000 +0000
@@ -138,8 +138,8 @@ int tun_net_init(struct net_device *dev)
 		dev->addr_len = 0;
 		dev->mtu = 1500;
 
-		/* Type PPP seems most suitable */
-		dev->type = ARPHRD_PPP; 
+		/* Zero header length */
+		dev->type = ARPHRD_NONE; 
 		dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
 		dev->tx_queue_len = 10;
 		break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/via-rhine.c linux-2.4.27-rc4/drivers/net/via-rhine.c
--- linux-2.4.26/drivers/net/via-rhine.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/via-rhine.c	2004-07-30 16:28:06.000000000 +0000
@@ -28,10 +28,10 @@
 
 
 	Linux kernel version history:
-	
+
 	LK1.1.0:
 	- Jeff Garzik: softnet 'n stuff
-	
+
 	LK1.1.1:
 	- Justin Guyett: softnet and locking fixes
 	- Jeff Garzik: use PCI interface
@@ -58,7 +58,7 @@
 	LK1.1.6:
 	- Urban Widmark: merges from Beckers 1.08b version (VT6102 + mdio)
 	                 set netif_running_on/off on startup, del_timer_sync
-	
+
 	LK1.1.7:
 	- Manfred Spraul: added reset into tx_timeout
 
@@ -83,7 +83,7 @@
 	LK1.1.13 (jgarzik):
 	- Add ethtool support
 	- Replace some MII-related magic numbers with constants
-	
+
 	LK1.1.14 (Ivan G.):
  	- fixes comments for Rhine-III
 	- removes W_MAX_TIMEOUT (unused)
@@ -92,7 +92,7 @@
 	- sends chip_id as a parameter to wait_for_reset since np is not
 	  initialized on first call
 	- changes mmio "else if (chip_id==VT6102)" to "else" so it will work
-	  for Rhine-III's (documentation says same bit is correct)		
+	  for Rhine-III's (documentation says same bit is correct)
 	- transmit frame queue message is off by one - fixed
 	- adds IntrNormalSummary to "Something Wicked" exclusion list
 	  so normal interrupts will not trigger the message (src: Donald Becker)
@@ -316,10 +316,10 @@ IIId. Synchronization
 
 The driver runs as two independent, single-threaded flows of control.  One
 is the send-packet routine, which enforces single-threaded use by the
-dev->priv->lock spinlock. The other thread is the interrupt handler, which 
+dev->priv->lock spinlock. The other thread is the interrupt handler, which
 is single threaded by the hardware and interrupt handling software.
 
-The send packet thread has partial control over the Tx ring. It locks the 
+The send packet thread has partial control over the Tx ring. It locks the
 dev->priv->lock whenever it's queuing a Tx packet. If the next slot in the ring
 is not available it stops the transmit queue by calling netif_stop_queue.
 
@@ -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)
 {
@@ -630,7 +639,7 @@ static int __devinit via_rhine_init_one 
 #ifdef USE_MEM
 	long ioaddr0;
 #endif
-	
+
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
 	static int printed_version;
@@ -651,7 +660,7 @@ static int __devinit via_rhine_init_one 
 		printk(KERN_ERR "32-bit PCI DMA addresses not supported by the card!?\n");
 		goto err_out;
 	}
-	
+
 	/* sanity check */
 	if ((pci_resource_len (pdev, 0) < io_size) ||
 	    (pci_resource_len (pdev, 1) < io_size)) {
@@ -671,7 +680,8 @@ static int __devinit via_rhine_init_one 
 		goto err_out;
 	}
 	SET_MODULE_OWNER(dev);
-	
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
 	if (pci_request_regions(pdev, shortname))
 		goto err_out_free_netdev;
 
@@ -783,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;
 
@@ -834,6 +847,8 @@ static int __devinit via_rhine_init_one 
 					netif_carrier_on(dev);
 				else
 					netif_carrier_off(dev);
+
+				break;
 			}
 		}
 		np->mii_cnt = phy_idx;
@@ -867,7 +882,7 @@ err_out_free_res:
 #endif
 	pci_release_regions(pdev);
 err_out_free_netdev:
-	kfree (dev);
+	free_netdev (dev);
 err_out:
 	return -ENODEV;
 }
@@ -878,7 +893,7 @@ static int alloc_ring(struct net_device*
 	void *ring;
 	dma_addr_t ring_dma;
 
-	ring = pci_alloc_consistent(np->pdev, 
+	ring = pci_alloc_consistent(np->pdev,
 				    RX_RING_SIZE * sizeof(struct rx_desc) +
 				    TX_RING_SIZE * sizeof(struct tx_desc),
 				    &ring_dma);
@@ -890,7 +905,7 @@ static int alloc_ring(struct net_device*
 		np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,
 								   &np->tx_bufs_dma);
 		if (np->tx_bufs == NULL) {
-			pci_free_consistent(np->pdev, 
+			pci_free_consistent(np->pdev,
 				    RX_RING_SIZE * sizeof(struct rx_desc) +
 				    TX_RING_SIZE * sizeof(struct tx_desc),
 				    ring, ring_dma);
@@ -910,7 +925,7 @@ void free_ring(struct net_device* dev)
 {
 	struct netdev_private *np = dev->priv;
 
-	pci_free_consistent(np->pdev, 
+	pci_free_consistent(np->pdev,
 			    RX_RING_SIZE * sizeof(struct rx_desc) +
 			    TX_RING_SIZE * sizeof(struct tx_desc),
 			    np->rx_ring, np->rx_ring_dma);
@@ -935,7 +950,7 @@ static void alloc_rbufs(struct net_devic
 	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 	np->rx_head_desc = &np->rx_ring[0];
 	next = np->rx_ring_dma;
-	
+
 	/* Init the ring entries */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].rx_status = 0;
@@ -1138,7 +1153,7 @@ static int via_rhine_open(struct net_dev
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n",
 			   dev->name, np->pdev->irq);
-	
+
 	i = alloc_ring(dev);
 	if (i)
 		return i;
@@ -1253,7 +1268,7 @@ static void via_rhine_tx_timeout (struct
 	/* Reinitialize the hardware. */
 	wait_for_reset(dev, np->chip_id, dev->name);
 	init_registers(dev);
-	
+
 	spin_unlock(&np->lock);
 	enable_irq(np->pdev->irq);
 
@@ -1303,7 +1318,7 @@ static int via_rhine_start_tx(struct sk_
 		np->tx_ring[entry].addr = cpu_to_le32(np->tx_skbuff_dma[entry]);
 	}
 
-	np->tx_ring[entry].desc_length = 
+	np->tx_ring[entry].desc_length =
 		cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
 
 	/* lock eth irq */
@@ -1351,7 +1366,7 @@ static irqreturn_t via_rhine_interrupt(i
 	int handled = 0;
 
 	ioaddr = dev->base_addr;
-	
+
 	while ((intr_status = get_intr_status(dev))) {
 		handled = 1;
 
@@ -1569,7 +1584,7 @@ static void via_rhine_rx(struct net_devi
 				break;			/* Better luck next round. */
 			skb->dev = dev;			/* Mark as being used by this device. */
 			np->rx_skbuff_dma[entry] =
-				pci_map_single(np->pdev, skb->tail, np->rx_buf_sz, 
+				pci_map_single(np->pdev, skb->tail, np->rx_buf_sz,
 							   PCI_DMA_FROMDEVICE);
 			np->rx_ring[entry].addr = cpu_to_le32(np->rx_skbuff_dma[entry]);
 		}
@@ -1877,7 +1892,7 @@ static int via_rhine_close(struct net_de
 static void __devexit via_rhine_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	
+
 	unregister_netdev(dev);
 
 	pci_release_regions(pdev);
@@ -1886,7 +1901,7 @@ static void __devexit via_rhine_remove_o
 	iounmap((char *)(dev->base_addr));
 #endif
 
-	kfree(dev);
+	free_netdev(dev);
 	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/wan/farsync.c linux-2.4.27-rc4/drivers/net/wan/farsync.c
--- linux-2.4.26/drivers/net/wan/farsync.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/wan/farsync.c	2004-07-30 16:29:51.000000000 +0000
@@ -1,9 +1,9 @@
 /*
- *      FarSync X21 driver for Linux (generic HDLC version)
+ *      FarSync WAN driver for Linux (2.4.x kernel version)
  *
  *      Actually sync driver for X.21, V.35 and V.24 on FarSync T-series cards
  *
- *      Copyright (C) 2001 FarSite Communications Ltd.
+ *      Copyright (C) 2001-2004 FarSite Communications Ltd.
  *      www.farsite.co.uk
  *
  *      This program is free software; you can redistribute it and/or
@@ -11,66 +11,81 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  *
- *      Author: R.J.Dunlop      <bob.dunlop@farsite.co.uk>
+ *      Author:      R.J.Dunlop    <bob.dunlop@farsite.co.uk>
+ *      Maintainer:  Kevin Curtis  <kevin.curtis@farsite.co.uk>
  */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/version.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <linux/if.h>
 #include <linux/hdlc.h>
+#include <asm/delay.h>
 
 #include "farsync.h"
 
-
 /*
  *      Module info
  */
 MODULE_AUTHOR("R.J.Dunlop <bob.dunlop@farsite.co.uk>");
-MODULE_DESCRIPTION("FarSync T-Series X21 driver. FarSite Communications Ltd.");
+MODULE_DESCRIPTION("FarSync T-Series WAN driver. FarSite Communications Ltd.");
+MODULE_PARM(fst_txq_low, "i");
+MODULE_PARM(fst_txq_high, "i");
+MODULE_PARM(fst_max_reads, "i");
+MODULE_PARM(fst_excluded_cards, "i");
+MODULE_PARM(fst_excluded_list, "0-32i");
 MODULE_LICENSE("GPL");
 
 EXPORT_NO_SYMBOLS;
 
-
 /*      Driver configuration and global parameters
  *      ==========================================
  */
 
-/*      Number of ports (per card) supported
+/*      Number of ports (per card) and cards supported
  */
 #define FST_MAX_PORTS           4
-
-
-/*      PCI vendor and device IDs
- */
-#define FSC_PCI_VENDOR_ID       0x1619  /* FarSite Communications Ltd */
-#define T2P_PCI_DEVICE_ID       0x0400  /* T2P X21 2 port card */
-#define T4P_PCI_DEVICE_ID       0x0440  /* T4P X21 4 port card */
-
+#define FST_MAX_CARDS           32
 
 /*      Default parameters for the link
  */
-#define FST_TX_QUEUE_LEN        100     /* At 8Mbps a longer queue length is
-                                         * useful, the syncppp module forces
-                                         * this down assuming a slower line I
-                                         * guess.
-                                         */
-#define FST_MAX_MTU             8000    /* Huge but possible */
-#define FST_DEF_MTU             1500    /* Common sane value */
+#define FST_TX_QUEUE_LEN        100	/* At 8Mbps a longer queue length is
+					 * useful, the syncppp module forces
+					 * this down assuming a slower line I
+					 * guess.
+					 */
+#define FST_TXQ_DEPTH           16	/* This one is for the buffering
+					 * of frames on the way down to the card
+					 * so that we can keep the card busy
+					 * and maximise throughput
+					 */
+#define FST_HIGH_WATER_MARK     12	/* Point at which we flow control
+					 * network layer */
+#define FST_LOW_WATER_MARK      8	/* Point at which we remove flow
+					 * control from network layer */
+#define FST_MAX_MTU             8000	/* Huge but possible */
+#define FST_DEF_MTU             1500	/* Common sane value */
 
 #define FST_TX_TIMEOUT          (2*HZ)
 
-
 #ifdef ARPHRD_RAWHDLC
-#define ARPHRD_MYTYPE   ARPHRD_RAWHDLC  /* Raw frames */
+#define ARPHRD_MYTYPE   ARPHRD_RAWHDLC	/* Raw frames */
 #else
-#define ARPHRD_MYTYPE   ARPHRD_HDLC     /* Cisco-HDLC (keepalives etc) */
+#define ARPHRD_MYTYPE   ARPHRD_HDLC	/* Cisco-HDLC (keepalives etc) */
 #endif
 
+/*
+ * Modules parameters and associated varaibles
+ */
+int fst_txq_low = FST_LOW_WATER_MARK;
+int fst_txq_high = FST_HIGH_WATER_MARK;
+int fst_max_reads = 7;
+int fst_excluded_cards = 0;
+int fst_excluded_list[FST_MAX_CARDS];
 
 /*      Card shared memory layout
  *      =========================
@@ -87,58 +102,57 @@ EXPORT_NO_SYMBOLS;
  *      be used to check that we have not got out of step with the firmware
  *      contained in the .CDE files.
  */
-#define SMC_VERSION 11
+#define SMC_VERSION 24
 
-#define FST_MEMSIZE 0x100000    /* Size of card memory (1Mb) */
+#define FST_MEMSIZE 0x100000	/* Size of card memory (1Mb) */
 
-#define SMC_BASE 0x00002000L    /* Base offset of the shared memory window main
-                                 * configuration structure */
-#define BFM_BASE 0x00010000L    /* Base offset of the shared memory window DMA
-                                 * buffers */
+#define SMC_BASE 0x00002000L	/* Base offset of the shared memory window main
+				 * configuration structure */
+#define BFM_BASE 0x00010000L	/* Base offset of the shared memory window DMA
+				 * buffers */
 
-#define LEN_TX_BUFFER 8192      /* Size of packet buffers */
+#define LEN_TX_BUFFER 8192	/* Size of packet buffers */
 #define LEN_RX_BUFFER 8192
 
-#define LEN_SMALL_TX_BUFFER 256 /* Size of obsolete buffs used for DOS diags */
+#define LEN_SMALL_TX_BUFFER 256	/* Size of obsolete buffs used for DOS diags */
 #define LEN_SMALL_RX_BUFFER 256
 
-#define NUM_TX_BUFFER 2         /* Must be power of 2. Fixed by firmware */
+#define NUM_TX_BUFFER 2		/* Must be power of 2. Fixed by firmware */
 #define NUM_RX_BUFFER 8
 
 /* Interrupt retry time in milliseconds */
 #define INT_RETRY_TIME 2
 
-
 /*      The Am186CH/CC processors support a SmartDMA mode using circular pools
  *      of buffer descriptors. The structure is almost identical to that used
  *      in the LANCE Ethernet controllers. Details available as PDF from the
  *      AMD web site: http://www.amd.com/products/epd/processors/\
  *                    2.16bitcont/3.am186cxfa/a21914/21914.pdf
  */
-struct txdesc {                 /* Transmit descriptor */
-        volatile u16 ladr;      /* Low order address of packet. This is a
-                                 * linear address in the Am186 memory space
-                                 */
-        volatile u8  hadr;      /* High order address. Low 4 bits only, high 4
-                                 * bits must be zero
-                                 */
-        volatile u8  bits;      /* Status and config */
-        volatile u16 bcnt;      /* 2s complement of packet size in low 15 bits.
-                                 * Transmit terminal count interrupt enable in
-                                 * top bit.
-                                 */
-                 u16 unused;    /* Not used in Tx */
+struct txdesc {			/* Transmit descriptor */
+	volatile u16 ladr;	/* Low order address of packet. This is a
+				 * linear address in the Am186 memory space
+				 */
+	volatile u8 hadr;	/* High order address. Low 4 bits only, high 4
+				 * bits must be zero
+				 */
+	volatile u8 bits;	/* Status and config */
+	volatile u16 bcnt;	/* 2s complement of packet size in low 15 bits.
+				 * Transmit terminal count interrupt enable in
+				 * top bit.
+				 */
+	u16 unused;		/* Not used in Tx */
 };
 
-struct rxdesc {                 /* Receive descriptor */
-        volatile u16 ladr;      /* Low order address of packet */
-        volatile u8  hadr;      /* High order address */
-        volatile u8  bits;      /* Status and config */
-        volatile u16 bcnt;      /* 2s complement of buffer size in low 15 bits.
-                                 * Receive terminal count interrupt enable in
-                                 * top bit.
-                                 */
-        volatile u16 mcnt;      /* Message byte count (15 bits) */
+struct rxdesc {			/* Receive descriptor */
+	volatile u16 ladr;	/* Low order address of packet */
+	volatile u8 hadr;	/* High order address */
+	volatile u8 bits;	/* Status and config */
+	volatile u16 bcnt;	/* 2s complement of buffer size in low 15 bits.
+				 * Receive terminal count interrupt enable in
+				 * top bit.
+				 */
+	volatile u16 mcnt;	/* Message byte count (15 bits) */
 };
 
 /* Convert a length into the 15 bit 2's complement */
@@ -149,57 +163,99 @@ struct rxdesc {                 /* Recei
 #define cnv_bcnt(len)   (-(len))
 
 /* Status and config bits for the above */
-#define DMA_OWN         0x80            /* SmartDMA owns the descriptor */
-#define TX_STP          0x02            /* Tx: start of packet */
-#define TX_ENP          0x01            /* Tx: end of packet */
-#define RX_ERR          0x40            /* Rx: error (OR of next 4 bits) */
-#define RX_FRAM         0x20            /* Rx: framing error */
-#define RX_OFLO         0x10            /* Rx: overflow error */
-#define RX_CRC          0x08            /* Rx: CRC error */
-#define RX_HBUF         0x04            /* Rx: buffer error */
-#define RX_STP          0x02            /* Rx: start of packet */
-#define RX_ENP          0x01            /* Rx: end of packet */
-
+#define DMA_OWN         0x80	/* SmartDMA owns the descriptor */
+#define TX_STP          0x02	/* Tx: start of packet */
+#define TX_ENP          0x01	/* Tx: end of packet */
+#define RX_ERR          0x40	/* Rx: error (OR of next 4 bits) */
+#define RX_FRAM         0x20	/* Rx: framing error */
+#define RX_OFLO         0x10	/* Rx: overflow error */
+#define RX_CRC          0x08	/* Rx: CRC error */
+#define RX_HBUF         0x04	/* Rx: buffer error */
+#define RX_STP          0x02	/* Rx: start of packet */
+#define RX_ENP          0x01	/* Rx: end of packet */
 
-/* Interrupts from the card are caused by various events and these are presented
+/* Interrupts from the card are caused by various events which are presented
  * in a circular buffer as several events may be processed on one physical int
  */
 #define MAX_CIRBUFF     32
 
 struct cirbuff {
-        u8 rdindex;             /* read, then increment and wrap */
-        u8 wrindex;             /* write, then increment and wrap */
-        u8 evntbuff[MAX_CIRBUFF];
+	u8 rdindex;		/* read, then increment and wrap */
+	u8 wrindex;		/* write, then increment and wrap */
+	u8 evntbuff[MAX_CIRBUFF];
 };
 
 /* Interrupt event codes.
  * Where appropriate the two low order bits indicate the port number
  */
-#define CTLA_CHG        0x18    /* Control signal changed */
+#define CTLA_CHG        0x18	/* Control signal changed */
 #define CTLB_CHG        0x19
 #define CTLC_CHG        0x1A
 #define CTLD_CHG        0x1B
 
-#define INIT_CPLT       0x20    /* Initialisation complete */
-#define INIT_FAIL       0x21    /* Initialisation failed */
+#define INIT_CPLT       0x20	/* Initialisation complete */
+#define INIT_FAIL       0x21	/* Initialisation failed */
 
-#define ABTA_SENT       0x24    /* Abort sent */
+#define ABTA_SENT       0x24	/* Abort sent */
 #define ABTB_SENT       0x25
 #define ABTC_SENT       0x26
 #define ABTD_SENT       0x27
 
-#define TXA_UNDF        0x28    /* Transmission underflow */
+#define TXA_UNDF        0x28	/* Transmission underflow */
 #define TXB_UNDF        0x29
 #define TXC_UNDF        0x2A
 #define TXD_UNDF        0x2B
 
+#define F56_INT         0x2C
+#define M32_INT         0x2D
+
+#define TE1_ALMA        0x30
 
 /* Port physical configuration. See farsync.h for field values */
 struct port_cfg {
-        u16  lineInterface;     /* Physical interface type */
-        u8   x25op;             /* Unused at present */
-        u8   internalClock;     /* 1 => internal clock, 0 => external */
-        u32  lineSpeed;         /* Speed in bps */
+	u16 lineInterface;	/* Physical interface type */
+	u8 x25op;		/* Unused at present */
+	u8 internalClock;	/* 1 => internal clock, 0 => external */
+	u8 transparentMode;	/* 1 => on, 0 => off */
+	u8 invertClock;		/* 0 => normal, 1 => inverted */
+	u8 padBytes[6];		/* Padding */
+	u32 lineSpeed;		/* Speed in bps */
+};
+
+/* TE1 port physical configuration */
+struct su_config {
+	u32 dataRate;
+	u8 clocking;
+	u8 framing;
+	u8 structure;
+	u8 interface;
+	u8 coding;
+	u8 lineBuildOut;
+	u8 equalizer;
+	u8 transparentMode;
+	u8 loopMode;
+	u8 range;
+	u8 txBufferMode;
+	u8 rxBufferMode;
+	u8 startingSlot;
+	u8 losThreshold;
+	u8 enableIdleCode;
+	u8 idleCode;
+	u8 spare[44];
+};
+
+/* TE1 Status */
+struct su_status {
+	u32 receiveBufferDelay;
+	u32 framingErrorCount;
+	u32 codeViolationCount;
+	u32 crcErrorCount;
+	u32 lineAttenuation;
+	u8 portStarted;
+	u8 lossOfSignal;
+	u8 receiveRemoteAlarm;
+	u8 alarmIndicationSignal;
+	u8 spare[40];
 };
 
 /* Finally sling all the above together into the shared memory structure.
@@ -209,114 +265,151 @@ struct port_cfg {
  * See farsync.h for some field values.
  */
 struct fst_shared {
-                                /* DMA descriptor rings */
-        struct rxdesc rxDescrRing[FST_MAX_PORTS][NUM_RX_BUFFER];
-        struct txdesc txDescrRing[FST_MAX_PORTS][NUM_TX_BUFFER];
+	/* DMA descriptor rings */
+	struct rxdesc rxDescrRing[FST_MAX_PORTS][NUM_RX_BUFFER];
+	struct txdesc txDescrRing[FST_MAX_PORTS][NUM_TX_BUFFER];
+
+	/* Obsolete small buffers */
+	u8 smallRxBuffer[FST_MAX_PORTS][NUM_RX_BUFFER][LEN_SMALL_RX_BUFFER];
+	u8 smallTxBuffer[FST_MAX_PORTS][NUM_TX_BUFFER][LEN_SMALL_TX_BUFFER];
 
-                                /* Obsolete small buffers */
-        u8  smallRxBuffer[FST_MAX_PORTS][NUM_RX_BUFFER][LEN_SMALL_RX_BUFFER];
-        u8  smallTxBuffer[FST_MAX_PORTS][NUM_TX_BUFFER][LEN_SMALL_TX_BUFFER];
+	u8 taskStatus;		/* 0x00 => initialising, 0x01 => running,
+				 * 0xFF => halted
+				 */
 
-        u8  taskStatus;         /* 0x00 => initialising, 0x01 => running,
-                                 * 0xFF => halted
-                                 */
+	u8 interruptHandshake;	/* Set to 0x01 by adapter to signal interrupt,
+				 * set to 0xEE by host to acknowledge interrupt
+				 */
 
-        u8  interruptHandshake; /* Set to 0x01 by adapter to signal interrupt,
-                                 * set to 0xEE by host to acknowledge interrupt
-                                 */
+	u16 smcVersion;		/* Must match SMC_VERSION */
 
-        u16 smcVersion;         /* Must match SMC_VERSION */
+	u32 smcFirmwareVersion;	/* 0xIIVVRRBB where II = product ID, VV = major
+				 * version, RR = revision and BB = build
+				 */
 
-        u32 smcFirmwareVersion; /* 0xIIVVRRBB where II = product ID, VV = major
-                                 * version, RR = revision and BB = build
-                                 */
+	u16 txa_done;		/* Obsolete completion flags */
+	u16 rxa_done;
+	u16 txb_done;
+	u16 rxb_done;
+	u16 txc_done;
+	u16 rxc_done;
+	u16 txd_done;
+	u16 rxd_done;
 
-        u16 txa_done;           /* Obsolete completion flags */
-        u16 rxa_done;
-        u16 txb_done;
-        u16 rxb_done;
-        u16 txc_done;
-        u16 rxc_done;
-        u16 txd_done;
-        u16 rxd_done;
+	u16 mailbox[4];		/* Diagnostics mailbox. Not used */
 
-        u16 mailbox[4];         /* Diagnostics mailbox. Not used */
+	struct cirbuff interruptEvent;	/* interrupt causes */
 
-        struct cirbuff interruptEvent;  /* interrupt causes */
+	u32 v24IpSts[FST_MAX_PORTS];	/* V.24 control input status */
+	u32 v24OpSts[FST_MAX_PORTS];	/* V.24 control output status */
 
-        u32 v24IpSts[FST_MAX_PORTS];    /* V.24 control input status */
-        u32 v24OpSts[FST_MAX_PORTS];    /* V.24 control output status */
+	struct port_cfg portConfig[FST_MAX_PORTS];
 
-        struct port_cfg portConfig[FST_MAX_PORTS];
+	u16 clockStatus[FST_MAX_PORTS];	/* lsb: 0=> present, 1=> absent */
 
-        u16 clockStatus[FST_MAX_PORTS]; /* lsb: 0=> present, 1=> absent */
+	u16 cableStatus;	/* lsb: 0=> present, 1=> absent */
 
-        u16 cableStatus;                /* lsb: 0=> present, 1=> absent */
+	u16 txDescrIndex[FST_MAX_PORTS];	/* transmit descriptor ring index */
+	u16 rxDescrIndex[FST_MAX_PORTS];	/* receive descriptor ring index */
 
-        u16 txDescrIndex[FST_MAX_PORTS]; /* transmit descriptor ring index */
-        u16 rxDescrIndex[FST_MAX_PORTS]; /* receive descriptor ring index */
+	u16 portMailbox[FST_MAX_PORTS][2];	/* command, modifier */
+	u16 cardMailbox[4];	/* Not used */
 
-        u16 portMailbox[FST_MAX_PORTS][2];      /* command, modifier */
-        u16 cardMailbox[4];                     /* Not used */
+	/* Number of times the card thinks the host has
+	 * missed an interrupt by not acknowledging
+	 * within 2mS (I guess NT has problems)
+	 */
+	u32 interruptRetryCount;
 
-                                /* Number of times that card thinks the host has
-                                 * missed an interrupt by not acknowledging
-                                 * within 2mS (I guess NT has problems)
-                                 */
-        u32 interruptRetryCount;
+	/* Driver private data used as an ID. We'll not
+	 * use this as I'd rather keep such things
+	 * in main memory rather than on the PCI bus
+	 */
+	u32 portHandle[FST_MAX_PORTS];
 
-                                /* Driver private data used as an ID. We'll not
-                                 * use this on Linux I'd rather keep such things
-                                 * in main memory rather than on the PCI bus
-                                 */
-        u32 portHandle[FST_MAX_PORTS];
+	/* Count of Tx underflows for stats */
+	u32 transmitBufferUnderflow[FST_MAX_PORTS];
 
-                                /* Count of Tx underflows for stats */
-        u32 transmitBufferUnderflow[FST_MAX_PORTS];
+	/* Debounced V.24 control input status */
+	u32 v24DebouncedSts[FST_MAX_PORTS];
 
-                                /* Debounced V.24 control input status */
-        u32 v24DebouncedSts[FST_MAX_PORTS];
+	/* Adapter debounce timers. Don't touch */
+	u32 ctsTimer[FST_MAX_PORTS];
+	u32 ctsTimerRun[FST_MAX_PORTS];
+	u32 dcdTimer[FST_MAX_PORTS];
+	u32 dcdTimerRun[FST_MAX_PORTS];
 
-                                /* Adapter debounce timers. Don't touch */
-        u32 ctsTimer[FST_MAX_PORTS];
-        u32 ctsTimerRun[FST_MAX_PORTS];
-        u32 dcdTimer[FST_MAX_PORTS];
-        u32 dcdTimerRun[FST_MAX_PORTS];
+	u32 numberOfPorts;	/* Number of ports detected at startup */
 
-        u32 numberOfPorts;      /* Number of ports detected at startup */
+	u16 _reserved[64];
 
-        u16 _reserved[64];
+	u16 cardMode;		/* Bit-mask to enable features:
+				 * Bit 0: 1 enables LED identify mode
+				 */
 
-        u16 cardMode;           /* Bit-mask to enable features:
-                                 * Bit 0: 1 enables LED identify mode
-                                 */
+	u16 portScheduleOffset;
 
-        u16 portScheduleOffset;
+	struct su_config suConfig;	/* TE1 Bits */
+	struct su_status suStatus;
 
-        u32 endOfSmcSignature;  /* endOfSmcSignature MUST be the last member of
-                                 * the structure and marks the end of the shared
-                                 * memory. Adapter code initializes its value as
-                                 * END_SIG.
-                                 */
+	u32 endOfSmcSignature;	/* endOfSmcSignature MUST be the last member of
+				 * the structure and marks the end of shared
+				 * memory. Adapter code initializes it as
+				 * END_SIG.
+				 */
 };
 
 /* endOfSmcSignature value */
 #define END_SIG                 0x12345678
 
 /* Mailbox values. (portMailbox) */
-#define NOP             0       /* No operation */
-#define ACK             1       /* Positive acknowledgement to PC driver */
-#define NAK             2       /* Negative acknowledgement to PC driver */
-#define STARTPORT       3       /* Start an HDLC port */
-#define STOPPORT        4       /* Stop an HDLC port */
-#define ABORTTX         5       /* Abort the transmitter for a port */
-#define SETV24O         6       /* Set V24 outputs */
+#define NOP             0	/* No operation */
+#define ACK             1	/* Positive acknowledgement to PC driver */
+#define NAK             2	/* Negative acknowledgement to PC driver */
+#define STARTPORT       3	/* Start an HDLC port */
+#define STOPPORT        4	/* Stop an HDLC port */
+#define ABORTTX         5	/* Abort the transmitter for a port */
+#define SETV24O         6	/* Set V24 outputs */
+
+/* PLX Chip Register Offsets */
+#define CNTRL_9052      0x50	/* Control Register */
+#define CNTRL_9054      0x6c	/* Control Register */
 
+#define INTCSR_9052     0x4c	/* Interrupt control/status register */
+#define INTCSR_9054     0x68	/* Interrupt control/status register */
+
+/* 9054 DMA Registers */
+/*
+ * Note that we will be using DMA Channel 0 for copying rx data
+ * and Channel 1 for copying tx data
+ */
+#define DMAMODE0        0x80
+#define DMAPADR0        0x84
+#define DMALADR0        0x88
+#define DMASIZ0         0x8c
+#define DMADPR0         0x90
+#define DMAMODE1        0x94
+#define DMAPADR1        0x98
+#define DMALADR1        0x9c
+#define DMASIZ1         0xa0
+#define DMADPR1         0xa4
+#define DMACSR0         0xa8
+#define DMACSR1         0xa9
+#define DMAARB          0xac
+#define DMATHR          0xb0
+#define DMADAC0         0xb4
+#define DMADAC1         0xb8
+#define DMAMARBR        0xac
+
+#define FST_MIN_DMA_LEN 64
+#define FST_RX_DMA_INT  0x01
+#define FST_TX_DMA_INT  0x02
+#define FST_CARD_INT    0x04
 
 /* Larger buffers are positioned in memory at offset BFM_BASE */
 struct buf_window {
-        u8 txBuffer[FST_MAX_PORTS][NUM_TX_BUFFER][LEN_TX_BUFFER];
-        u8 rxBuffer[FST_MAX_PORTS][NUM_RX_BUFFER][LEN_RX_BUFFER];
+	u8 txBuffer[FST_MAX_PORTS][NUM_TX_BUFFER][LEN_TX_BUFFER];
+	u8 rxBuffer[FST_MAX_PORTS][NUM_RX_BUFFER][LEN_RX_BUFFER];
 };
 
 /* Calculate offset of a buffer object within the shared memory window */
@@ -324,39 +417,64 @@ struct buf_window {
 
 #pragma pack()
 
-
 /*      Device driver private information
  *      =================================
  */
 /*      Per port (line or channel) information
  */
 struct fst_port_info {
-        hdlc_device             hdlc;   /* HDLC device struct - must be first */
-        struct fst_card_info   *card;   /* Card we're associated with */
-        int                     index;  /* Port index on the card */
-        int                     hwif;   /* Line hardware (lineInterface copy) */
-        int                     run;    /* Port is running */
-        int                     rxpos;  /* Next Rx buffer to use */
-        int                     txpos;  /* Next Tx buffer to use */
-        int                     txipos; /* Next Tx buffer to check for free */
-        int                     txcnt;  /* Count of Tx buffers in use */
+	hdlc_device hdlc;	/* HDLC device struct - must be first */
+	struct fst_card_info *card;	/* Card we're associated with */
+	int index;		/* Port index on the card */
+	int hwif;		/* Line hardware (lineInterface copy) */
+	int run;		/* Port is running */
+	int mode;		/* Normal or FarSync raw */
+	int rxpos;		/* Next Rx buffer to use */
+	int txpos;		/* Next Tx buffer to use */
+	int txipos;		/* Next Tx buffer to check for free */
+	int start;		/* Indication of start/stop to network */
+	/*
+	 * A sixteen entry transmit queue
+	 */
+	int txqs;		/* index to get next buffer to tx */
+	int txqe;		/* index to queue next packet */
+	struct sk_buff *txq[FST_TXQ_DEPTH];	/* The queue */
+	int rxqdepth;
 };
 
 /*      Per card information
  */
 struct fst_card_info {
-        char          *mem;             /* Card memory mapped to kernel space */
-        char          *ctlmem;          /* Control memory for PCI cards */
-        unsigned int   phys_mem;        /* Physical memory window address */
-        unsigned int   phys_ctlmem;     /* Physical control memory address */
-        unsigned int   irq;             /* Interrupt request line number */
-        unsigned int   nports;          /* Number of serial ports */
-        unsigned int   type;            /* Type index of card */
-        unsigned int   state;           /* State of card */
-        spinlock_t     card_lock;       /* Lock for SMP access */
-        unsigned short pci_conf;        /* PCI card config in I/O space */
-                                        /* Per port info */
-        struct fst_port_info ports[ FST_MAX_PORTS ];
+	char *mem;		/* Card memory mapped to kernel space */
+	char *ctlmem;		/* Control memory for PCI cards */
+	unsigned int phys_mem;	/* Physical memory window address */
+	unsigned int phys_ctlmem;	/* Physical control memory address */
+	unsigned int irq;	/* Interrupt request line number */
+	unsigned int nports;	/* Number of serial ports */
+	unsigned int type;	/* Type index of card */
+	unsigned int state;	/* State of card */
+	spinlock_t card_lock;	/* Lock for SMP access */
+	unsigned short pci_conf;	/* PCI card config in I/O space */
+	/* Per port info */
+	struct fst_port_info ports[FST_MAX_PORTS];
+	struct pci_dev *device;	/* Information about the pci device */
+	int card_no;		/* Inst of the card on the system */
+	int family;		/* TxP or TxU */
+	int dmarx_in_progress;
+	int dmatx_in_progress;
+	unsigned long int_count;
+	unsigned long int_time_ave;
+	void *rx_dma_handle_host;
+	dma_addr_t rx_dma_handle_card;
+	void *tx_dma_handle_host;
+	dma_addr_t tx_dma_handle_card;
+	struct sk_buff *dma_skb_rx;
+	struct fst_port_info *dma_port_rx;
+	struct fst_port_info *dma_port_tx;
+	int dma_len_rx;
+	int dma_len_tx;
+	int dma_txpos;
+	int dma_rxpos;
 };
 
 /* Convert an HDLC device pointer into a port info pointer and similar */
@@ -364,7 +482,6 @@ struct fst_card_info {
 #define dev_to_port(D)  hdlc_to_port(dev_to_hdlc(D))
 #define port_to_dev(P)  hdlc_to_dev(&(P)->hdlc)
 
-
 /*
  *      Shared memory window access macros
  *
@@ -384,7 +501,6 @@ struct fst_card_info {
 #define FST_WRW(C,E,W)  writew ((W), (C)->mem + WIN_OFFSET(E))
 #define FST_WRL(C,E,L)  writel ((L), (C)->mem + WIN_OFFSET(E))
 
-
 /*
  *      Debug support
  */
@@ -403,30 +519,148 @@ static int fst_debug_mask = { FST_DEBUG 
                                 printk ( KERN_DEBUG FST_NAME ": " fmt, ## A )
 
 #else
-# define dbg(X...)      /* NOP */
+#define dbg(X...)		/* NOP */
 #endif
 
-
 /*      Printing short cuts
  */
 #define printk_err(fmt,A...)    printk ( KERN_ERR     FST_NAME ": " fmt, ## A )
 #define printk_warn(fmt,A...)   printk ( KERN_WARNING FST_NAME ": " fmt, ## A )
 #define printk_info(fmt,A...)   printk ( KERN_INFO    FST_NAME ": " fmt, ## A )
 
-
 /*
  *      PCI ID lookup table
  */
 static struct pci_device_id fst_pci_dev_id[] __devinitdata = {
-        { FSC_PCI_VENDOR_ID, T2P_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-                                        FST_TYPE_T2P },
-        { FSC_PCI_VENDOR_ID, T4P_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-                                        FST_TYPE_T4P },
-        { 0, }                          /* End */
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2P, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_T2P},
+
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T4P, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_T4P},
+
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T1U, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_T1U},
+
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T2U, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_T2U},
+
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_T4U, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_T4U},
+
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_TE1, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_TE1},
+
+	{PCI_VENDOR_ID_FARSITE, PCI_DEVICE_ID_FARSITE_TE1C, PCI_ANY_ID, 
+	 PCI_ANY_ID, 0, 0, FST_TYPE_TE1},
+	{0,}			/* End */
 };
 
-MODULE_DEVICE_TABLE ( pci, fst_pci_dev_id );
+MODULE_DEVICE_TABLE(pci, fst_pci_dev_id);
+
+/*
+ *      Device Driver Work Queues
+ *
+ *      So that we don't spend too much time processing events in the 
+ *      Interrupt Service routine, we will declare a work queue per Card 
+ *      and make the ISR schedule a task in the queue for later execution.
+ */
+
+static void do_bottom_half_tx(struct fst_card_info *card);
+static void do_bottom_half_rx(struct fst_card_info *card);
+static void fst_process_tx_work_q(unsigned long work_q);
+static void fst_process_int_work_q(unsigned long work_q);
+
+DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
+DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+
+struct fst_card_info *fst_card_array[FST_MAX_CARDS];
+spinlock_t fst_work_q_lock;
+u64 fst_work_txq;
+u64 fst_work_intq;
+
+static void
+fst_q_work_item(u64 * queue, int card_index)
+{
+	unsigned long flags;
+	u64 mask;
 
+	/*
+	 * Grab the queue exclusively
+	 */
+	spin_lock_irqsave(&fst_work_q_lock, flags);
+
+	/*
+	 * Making an entry in the queue is simply a matter of setting
+	 * a bit for the card indicating that there is work to do in the
+	 * bottom half for the card.  Note the limitation of 64 cards.
+	 * That ought to be enough
+	 */
+	mask = 1 << card_index;
+	*queue |= mask;
+	spin_unlock_irqrestore(&fst_work_q_lock, flags);
+}
+
+static void
+fst_process_tx_work_q(unsigned long work_q)
+{
+	unsigned long flags;
+	u64 work_txq;
+	int i;
+
+	/*
+	 * Grab the queue exclusively
+	 */
+	dbg(DBG_TX, "fst_process_tx_work_q\n");
+	spin_lock_irqsave(&fst_work_q_lock, flags);
+	work_txq = fst_work_txq;
+	fst_work_txq = 0;
+	spin_unlock_irqrestore(&fst_work_q_lock, flags);
+
+	/*
+	 * Call the bottom half for each card with work waiting
+	 */
+	for (i = 0; i < FST_MAX_CARDS; i++) {
+		if (work_txq & 0x01) {
+			if (fst_card_array[i] != NULL) {
+				dbg(DBG_TX, "Calling tx bh for card %d\n", i);
+				do_bottom_half_tx(fst_card_array[i]);
+			}
+		}
+		work_txq = work_txq >> 1;
+	}
+}
+
+static void
+fst_process_int_work_q(unsigned long work_q)
+{
+	unsigned long flags;
+	u64 work_intq;
+	int i;
+
+	/*
+	 * Grab the queue exclusively
+	 */
+	dbg(DBG_INTR, "fst_process_int_work_q\n");
+	spin_lock_irqsave(&fst_work_q_lock, flags);
+	work_intq = fst_work_intq;
+	fst_work_intq = 0;
+	spin_unlock_irqrestore(&fst_work_q_lock, flags);
+
+	/*
+	 * Call the bottom half for each card with work waiting
+	 */
+	for (i = 0; i < FST_MAX_CARDS; i++) {
+		if (work_intq & 0x01) {
+			if (fst_card_array[i] != NULL) {
+				dbg(DBG_INTR,
+				    "Calling rx & tx bh for card %d\n", i);
+				do_bottom_half_rx(fst_card_array[i]);
+				do_bottom_half_tx(fst_card_array[i]);
+			}
+		}
+		work_intq = work_intq >> 1;
+	}
+}
 
 /*      Card control functions
  *      ======================
@@ -436,1002 +670,1709 @@ MODULE_DEVICE_TABLE ( pci, fst_pci_dev_i
  * Used to be a simple write to card control space but a glitch in the latest
  * AMD Am186CH processor means that we now have to do it by asserting and de-
  * asserting the PLX chip PCI Adapter Software Reset. Bit 30 in CNTRL register
- * at offset 0x50.
+ * at offset 9052_CNTRL.  Note the updates for the TXU.
  */
 static inline void
-fst_cpureset ( struct fst_card_info *card )
+fst_cpureset(struct fst_card_info *card)
 {
-        unsigned int regval;
+	unsigned char interrupt_line_register;
+	unsigned long j = jiffies + 1;
+	unsigned int regval;
+
+	if (card->family == FST_FAMILY_TXU) {
+		if (pci_read_config_byte
+		    (card->device, PCI_INTERRUPT_LINE, &interrupt_line_register)) {
+			dbg(DBG_ASS,
+			    "Error in reading interrupt line register\n");
+		}
+		/*
+		 * Assert PLX software reset and Am186 hardware reset
+		 * and then deassert the PLX software reset but 186 still in reset
+		 */
+		outw(0x440f, card->pci_conf + CNTRL_9054 + 2);
+		outw(0x040f, card->pci_conf + CNTRL_9054 + 2);
+		/*
+		 * We are delaying here to allow the 9054 to reset itself
+		 */
+		j = jiffies + 1;
+		while (jiffies < j)
+			/* Do nothing */ ;
+		outw(0x240f, card->pci_conf + CNTRL_9054 + 2);
+		/*
+		 * We are delaying here to allow the 9054 to reload its eeprom
+		 */
+		j = jiffies + 1;
+		while (jiffies < j)
+			/* Do nothing */ ;
+		outw(0x040f, card->pci_conf + CNTRL_9054 + 2);
+
+		if (pci_write_config_byte
+		    (card->device, PCI_INTERRUPT_LINE, interrupt_line_register)) {
+			dbg(DBG_ASS,
+			    "Error in writing interrupt line register\n");
+		}
 
-        regval = inl ( card->pci_conf + 0x50 );
+	} else {
+		regval = inl(card->pci_conf + CNTRL_9052);
 
-        outl ( regval |  0x40000000, card->pci_conf + 0x50 );
-        outl ( regval & ~0x40000000, card->pci_conf + 0x50 );
+		outl(regval | 0x40000000, card->pci_conf + CNTRL_9052);
+		outl(regval & ~0x40000000, card->pci_conf + CNTRL_9052);
+	}
 }
 
 /*      Release the processor from reset
  */
 static inline void
-fst_cpurelease ( struct fst_card_info *card )
+fst_cpurelease(struct fst_card_info *card)
 {
-        (void) readb ( card->ctlmem );
+	if (card->family == FST_FAMILY_TXU) {
+		/*
+		 * Force posted writes to complete
+		 */
+		(void) readb(card->mem);
+
+		/*
+		 * Release LRESET DO = 1
+		 * Then release Local Hold, DO = 1
+		 */
+		outw(0x040e, card->pci_conf + CNTRL_9054 + 2);
+		outw(0x040f, card->pci_conf + CNTRL_9054 + 2);
+	} else {
+		(void) readb(card->ctlmem);
+	}
 }
 
 /*      Clear the cards interrupt flag
  */
 static inline void
-fst_clear_intr ( struct fst_card_info *card )
+fst_clear_intr(struct fst_card_info *card)
 {
-        /* Poke the appropriate PLX chip register (same as enabling interrupts)
-         */
-        outw ( 0x0543, card->pci_conf + 0x4C );
+	if (card->family == FST_FAMILY_TXU) {
+		(void) readb(card->ctlmem);
+	} else {
+		/* Poke the appropriate PLX chip register (same as enabling interrupts)
+		 */
+		outw(0x0543, card->pci_conf + INTCSR_9052);
+	}
+}
+
+/*      Enable card interrupts
+ */
+static inline void
+fst_enable_intr(struct fst_card_info *card)
+{
+	if (card->family == FST_FAMILY_TXU) {
+		outl(0x0f0c0900, card->pci_conf + INTCSR_9054);
+	} else {
+		outw(0x0543, card->pci_conf + INTCSR_9052);
+	}
 }
 
 /*      Disable card interrupts
  */
 static inline void
-fst_disable_intr ( struct fst_card_info *card )
+fst_disable_intr(struct fst_card_info *card)
 {
-        outw ( 0x0000, card->pci_conf + 0x4C );
+	if (card->family == FST_FAMILY_TXU) {
+		outl(0x00000000, card->pci_conf + INTCSR_9054);
+	} else {
+		outw(0x0000, card->pci_conf + INTCSR_9052);
+	}
 }
 
+/*      Process the result of trying to pass a recieved frame up the stack
+ */
+static void
+fst_process_rx_status(int rx_status, char *name)
+{
+	switch (rx_status) {
+	case NET_RX_SUCCESS:
+		{
+			/*
+			 * Nothing to do here
+			 */
+			break;
+		}
+
+	case NET_RX_CN_LOW:
+		{
+			dbg(DBG_ASS, "%s: Receive Low Congestion\n", name);
+			break;
+		}
+
+	case NET_RX_CN_MOD:
+		{
+			dbg(DBG_ASS, "%s: Receive Moderate Congestion\n", name);
+			break;
+		}
+
+	case NET_RX_CN_HIGH:
+		{
+			dbg(DBG_ASS, "%s: Receive High Congestion\n", name);
+			break;
+		}
+
+	case NET_RX_DROP:
+		{
+			dbg(DBG_ASS, "%s: Received packet dropped\n", name);
+			break;
+		}
+	}
+}
+
+/*      Initilaise DMA for PLX 9054
+ */
+static inline void
+fst_init_dma(struct fst_card_info *card)
+{
+	/*
+	 * This is only required for the PLX 9054
+	 */
+	if (card->family == FST_FAMILY_TXU) {
+	        pci_set_master(card->device);
+		outl(0x00020441, card->pci_conf + DMAMODE0);
+		outl(0x00020441, card->pci_conf + DMAMODE1);
+		outl(0x0, card->pci_conf + DMATHR);
+	}
+}
+
+/*      Tx dma complete interrupt
+ */
+static void
+fst_tx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,
+		    int len, int txpos)
+{
+	/*
+	 * Everything is now set, just tell the card to go
+	 */
+	dbg(DBG_TX, "fst_tx_dma_complete\n");
+	FST_WRB(card, txDescrRing[port->index][txpos].bits,
+		DMA_OWN | TX_STP | TX_ENP);
+	port->hdlc.stats.tx_packets++;
+	port->hdlc.stats.tx_bytes += len;
+	port_to_dev(port)->trans_start = jiffies;
+}
+
+/*      Rx dma complete interrupt
+ */
+static void
+fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,
+		    int len, struct sk_buff *skb, int rxp)
+{
+
+	int pi;
+	int rx_status;
+
+	dbg(DBG_TX, "fst_rx_dma_complete\n");
+	pi = port->index;
+	memcpy(skb_put(skb, len), card->rx_dma_handle_host, len);
+
+	/* Reset buffer descriptor */
+	FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);
+
+	/* Update stats */
+	port->hdlc.stats.rx_packets++;
+	port->hdlc.stats.rx_bytes += len;
+
+	/* Push upstream */
+	dbg(DBG_RX, "Pushing the frame up the stack\n");
+	skb->mac.raw = skb->data;
+	skb->dev = hdlc_to_dev(&port->hdlc);
+	if (port->mode == FST_RAW) {
+		/*
+		 * Mark it for our own raw sockets interface
+		 */
+		skb->protocol = htons(ETH_P_CUST);
+		skb->pkt_type = PACKET_HOST;
+	} else {
+		skb->protocol = hdlc_type_trans(skb, skb->dev);
+	}
+	rx_status = netif_rx(skb);
+	fst_process_rx_status(rx_status, port_to_dev(port)->name);
+	if (rx_status == NET_RX_DROP)
+		port->hdlc.stats.rx_dropped++;
+	port_to_dev(port)->last_rx = jiffies;
+}
+
+/*
+ *      Receive a frame through the DMA
+ */
+static inline void
+fst_rx_dma(struct fst_card_info *card, unsigned char *skb,
+	   unsigned char *mem, int len)
+{
+	/*
+	 * This routine will setup the DMA and start it
+	 */
+
+	dbg(DBG_RX, "In fst_rx_dma %p %p %d\n", skb, mem, len);
+	if (card->dmarx_in_progress) {
+		dbg(DBG_ASS, "In fst_rx_dma while dma in progress\n");
+	}
+
+	outl((unsigned long) skb, card->pci_conf + DMAPADR0);	/* Copy to here */
+	outl((unsigned long) mem, card->pci_conf + DMALADR0);	/* from here */
+	outl(len, card->pci_conf + DMASIZ0);	/* for this length */
+	outl(0x00000000c, card->pci_conf + DMADPR0);	/* In this direction */
+
+	/*
+	 * We use the dmarx_in_progress flag to flag the channel as busy
+	 */
+	card->dmarx_in_progress = 1;
+	outb(0x03, card->pci_conf + DMACSR0);	/* Start the transfer */
+}
+
+/*
+ *      Send a frame through the DMA
+ */
+static inline void
+fst_tx_dma(struct fst_card_info *card, unsigned char *skb,
+	   unsigned char *mem, int len)
+{
+	/*
+	 * This routine will setup the DMA and start it.
+	 */
+
+	dbg(DBG_TX, "In fst_tx_dma %p %p %d\n", skb, mem, len);
+	if (card->dmatx_in_progress) {
+		dbg(DBG_ASS, "In fst_tx_dma while dma in progress\n");
+	}
+
+	outl((unsigned long) skb, card->pci_conf + DMAPADR1);	/* Copy from here */
+	outl((unsigned long) mem, card->pci_conf + DMALADR1);	/* to here */
+	outl(len, card->pci_conf + DMASIZ1);	/* for this length */
+	outl(0x000000004, card->pci_conf + DMADPR1);	/* In this direction */
+
+	/*
+	 * We use the dmatx_in_progress to flag the channel as busy
+	 */
+	card->dmatx_in_progress = 1;
+	outb(0x03, card->pci_conf + DMACSR1);	/* Start the transfer */
+}
 
 /*      Issue a Mailbox command for a port.
  *      Note we issue them on a fire and forget basis, not expecting to see an
  *      error and not waiting for completion.
  */
 static void
-fst_issue_cmd ( struct fst_port_info *port, unsigned short cmd )
+fst_issue_cmd(struct fst_port_info *port, unsigned short cmd)
 {
-        struct fst_card_info *card;
-        unsigned short mbval;
-        unsigned long flags;
-        int safety;
-
-        card = port->card;
-        spin_lock_irqsave ( &card->card_lock, flags );
-        mbval = FST_RDW ( card, portMailbox[port->index][0]);
-
-        safety = 0;
-        /* Wait for any previous command to complete */
-        while ( mbval > NAK )
-        {
-                spin_unlock_irqrestore ( &card->card_lock, flags );
-                schedule_timeout ( 1 );
-                spin_lock_irqsave ( &card->card_lock, flags );
-
-                if ( ++safety > 1000 )
-                {
-                        printk_err ("Mailbox safety timeout\n");
-                        break;
-                }
-
-                mbval = FST_RDW ( card, portMailbox[port->index][0]);
-        }
-        if ( safety > 0 )
-        {
-                dbg ( DBG_CMD,"Mailbox clear after %d jiffies\n", safety );
-        }
-        if ( mbval == NAK )
-        {
-                dbg ( DBG_CMD,"issue_cmd: previous command was NAK'd\n");
-        }
-
-        FST_WRW ( card, portMailbox[port->index][0], cmd );
-
-        if ( cmd == ABORTTX || cmd == STARTPORT )
-        {
-                port->txpos  = 0;
-                port->txipos = 0;
-                port->txcnt  = 0;
-        }
+	struct fst_card_info *card;
+	unsigned short mbval;
+	unsigned long flags;
+	int safety;
+
+	card = port->card;
+	spin_lock_irqsave(&card->card_lock, flags);
+	mbval = FST_RDW(card, portMailbox[port->index][0]);
+
+	safety = 0;
+	/* Wait for any previous command to complete */
+	while (mbval > NAK) {
+		spin_unlock_irqrestore(&card->card_lock, flags);
+		schedule_timeout(1);
+		spin_lock_irqsave(&card->card_lock, flags);
+
+		if (++safety > 2000) {
+			printk_err("Mailbox safety timeout\n");
+			break;
+		}
 
-        spin_unlock_irqrestore ( &card->card_lock, flags );
-}
+		mbval = FST_RDW(card, portMailbox[port->index][0]);
+	}
+	if (safety > 0) {
+		dbg(DBG_CMD, "Mailbox clear after %d jiffies\n", safety);
+	}
+	if (mbval == NAK) {
+		dbg(DBG_CMD, "issue_cmd: previous command was NAK'd\n");
+	}
+
+	FST_WRW(card, portMailbox[port->index][0], cmd);
 
+	if (cmd == ABORTTX || cmd == STARTPORT) {
+		port->txpos = 0;
+		port->txipos = 0;
+		port->start = 0;
+	}
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
+}
 
 /*      Port output signals control
  */
 static inline void
-fst_op_raise ( struct fst_port_info *port, unsigned int outputs )
+fst_op_raise(struct fst_port_info *port, unsigned int outputs)
 {
-        outputs |= FST_RDL ( port->card, v24OpSts[port->index]);
-        FST_WRL ( port->card, v24OpSts[port->index], outputs );
+	outputs |= FST_RDL(port->card, v24OpSts[port->index]);
+	FST_WRL(port->card, v24OpSts[port->index], outputs);
 
-        if ( port->run )
-                fst_issue_cmd ( port, SETV24O );
+	if (port->run)
+		fst_issue_cmd(port, SETV24O);
 }
 
 static inline void
-fst_op_lower ( struct fst_port_info *port, unsigned int outputs )
+fst_op_lower(struct fst_port_info *port, unsigned int outputs)
 {
-        outputs = ~outputs & FST_RDL ( port->card, v24OpSts[port->index]);
-        FST_WRL ( port->card, v24OpSts[port->index], outputs );
+	outputs = ~outputs & FST_RDL(port->card, v24OpSts[port->index]);
+	FST_WRL(port->card, v24OpSts[port->index], outputs);
 
-        if ( port->run )
-                fst_issue_cmd ( port, SETV24O );
+	if (port->run)
+		fst_issue_cmd(port, SETV24O);
 }
 
-
 /*
  *      Setup port Rx buffers
  */
 static void
-fst_rx_config ( struct fst_port_info *port )
+fst_rx_config(struct fst_port_info *port)
 {
-        int i;
-        int pi;
-        unsigned int offset;
-        unsigned long flags;
-        struct fst_card_info *card;
-
-        pi   = port->index;
-        card = port->card;
-        spin_lock_irqsave ( &card->card_lock, flags );
-        for ( i = 0 ; i < NUM_RX_BUFFER ; i++ )
-        {
-                offset = BUF_OFFSET ( rxBuffer[pi][i][0]);
-
-                FST_WRW ( card, rxDescrRing[pi][i].ladr, (u16) offset );
-                FST_WRB ( card, rxDescrRing[pi][i].hadr, (u8)( offset >> 16 ));
-                FST_WRW ( card, rxDescrRing[pi][i].bcnt,
-                                        cnv_bcnt ( LEN_RX_BUFFER ));
-                FST_WRW ( card, rxDescrRing[pi][i].mcnt, 0 );
-                FST_WRB ( card, rxDescrRing[pi][i].bits, DMA_OWN );
-        }
-        port->rxpos  = 0;
-        spin_unlock_irqrestore ( &card->card_lock, flags );
+	int i;
+	int pi;
+	unsigned int offset;
+	unsigned long flags;
+	struct fst_card_info *card;
+
+	pi = port->index;
+	card = port->card;
+	spin_lock_irqsave(&card->card_lock, flags);
+	for (i = 0; i < NUM_RX_BUFFER; i++) {
+		offset = BUF_OFFSET(rxBuffer[pi][i][0]);
+
+		FST_WRW(card, rxDescrRing[pi][i].ladr, (u16) offset);
+		FST_WRB(card, rxDescrRing[pi][i].hadr, (u8) (offset >> 16));
+		FST_WRW(card, rxDescrRing[pi][i].bcnt, cnv_bcnt(LEN_RX_BUFFER));
+		FST_WRW(card, rxDescrRing[pi][i].mcnt, LEN_RX_BUFFER);
+		FST_WRB(card, rxDescrRing[pi][i].bits, DMA_OWN);
+	}
+	port->rxpos = 0;
+	spin_unlock_irqrestore(&card->card_lock, flags);
 }
 
-
 /*
  *      Setup port Tx buffers
  */
 static void
-fst_tx_config ( struct fst_port_info *port )
+fst_tx_config(struct fst_port_info *port)
 {
-        int i;
-        int pi;
-        unsigned int offset;
-        unsigned long flags;
-        struct fst_card_info *card;
-
-        pi   = port->index;
-        card = port->card;
-        spin_lock_irqsave ( &card->card_lock, flags );
-        for ( i = 0 ; i < NUM_TX_BUFFER ; i++ )
-        {
-                offset = BUF_OFFSET ( txBuffer[pi][i][0]);
-
-                FST_WRW ( card, txDescrRing[pi][i].ladr, (u16) offset );
-                FST_WRB ( card, txDescrRing[pi][i].hadr, (u8)( offset >> 16 ));
-                FST_WRW ( card, txDescrRing[pi][i].bcnt, 0 );
-                FST_WRB ( card, txDescrRing[pi][i].bits, 0 );
-        }
-        port->txpos  = 0;
-        port->txipos = 0;
-        port->txcnt  = 0;
-        spin_unlock_irqrestore ( &card->card_lock, flags );
+	int i;
+	int pi;
+	unsigned int offset;
+	unsigned long flags;
+	struct fst_card_info *card;
+
+	pi = port->index;
+	card = port->card;
+	spin_lock_irqsave(&card->card_lock, flags);
+	for (i = 0; i < NUM_TX_BUFFER; i++) {
+		offset = BUF_OFFSET(txBuffer[pi][i][0]);
+
+		FST_WRW(card, txDescrRing[pi][i].ladr, (u16) offset);
+		FST_WRB(card, txDescrRing[pi][i].hadr, (u8) (offset >> 16));
+		FST_WRW(card, txDescrRing[pi][i].bcnt, 0);
+		FST_WRB(card, txDescrRing[pi][i].bits, 0);
+	}
+	port->txpos = 0;
+	port->txipos = 0;
+	port->start = 0;
+	spin_unlock_irqrestore(&card->card_lock, flags);
 }
 
+/*      TE1 Alarm change interrupt event
+ */
+static void
+fst_intr_te1_alarm(struct fst_card_info *card, struct fst_port_info *port)
+{
+	u8 los;
+	u8 rra;
+	u8 ais;
+
+	los = FST_RDB(card, suStatus.lossOfSignal);
+	rra = FST_RDB(card, suStatus.receiveRemoteAlarm);
+	ais = FST_RDB(card, suStatus.alarmIndicationSignal);
+
+	if (los) {
+		/*
+		 * Lost the link
+		 */
+		if (netif_carrier_ok(port_to_dev(port))) {
+			dbg(DBG_INTR, "Net carrier off\n");
+			netif_carrier_off(port_to_dev(port));
+		}
+	} else {
+		/*
+		 * Link available
+		 */
+		if (!netif_carrier_ok(port_to_dev(port))) {
+			dbg(DBG_INTR, "Net carrier on\n");
+			netif_carrier_on(port_to_dev(port));
+		}
+	}
+
+	if (los)
+		dbg(DBG_INTR, "Assert LOS Alarm\n");
+	else
+		dbg(DBG_INTR, "De-assert LOS Alarm\n");
+	if (rra)
+		dbg(DBG_INTR, "Assert RRA Alarm\n");
+	else
+		dbg(DBG_INTR, "De-assert RRA Alarm\n");
+
+	if (ais)
+		dbg(DBG_INTR, "Assert AIS Alarm\n");
+	else
+		dbg(DBG_INTR, "De-assert AIS Alarm\n");
+}
 
 /*      Control signal change interrupt event
  */
 static void
-fst_intr_ctlchg ( struct fst_card_info *card, struct fst_port_info *port )
+fst_intr_ctlchg(struct fst_card_info *card, struct fst_port_info *port)
 {
-        int signals;
+	int signals;
+
+	signals = FST_RDL(card, v24DebouncedSts[port->index]);
 
-        signals = FST_RDL ( card, v24DebouncedSts[port->index]);
+	if (signals & (((port->hwif == X21) || (port->hwif == X21D))
+		       ? IPSTS_INDICATE : IPSTS_DCD)) {
+		if (!netif_carrier_ok(port_to_dev(port))) {
+			dbg(DBG_INTR, "DCD active\n");
+			netif_carrier_on(port_to_dev(port));
+		}
+	} else {
+		if (netif_carrier_ok(port_to_dev(port))) {
+			dbg(DBG_INTR, "DCD lost\n");
+			netif_carrier_off(port_to_dev(port));
+		}
+	}
+}
 
-        if ( signals & (( port->hwif == X21 ) ? IPSTS_INDICATE : IPSTS_DCD ))
-        {
-                if ( ! netif_carrier_ok ( port_to_dev ( port )))
-                {
-                        dbg ( DBG_INTR,"DCD active\n");
-                        netif_carrier_on ( port_to_dev ( port ));
-                }
-        }
-        else
-        {
-                if ( netif_carrier_ok ( port_to_dev ( port )))
-                {
-                        dbg ( DBG_INTR,"DCD lost\n");
-                        netif_carrier_off ( port_to_dev ( port ));
-                }
-        }
+/*      Log Rx Errors
+ */
+static void
+fst_log_rx_error(struct fst_card_info *card, struct fst_port_info *port,
+		 unsigned char dmabits, int rxp, unsigned short len)
+{
+	/* 
+	 * Increment the appropriate error counter
+	 */
+	port->hdlc.stats.rx_errors++;
+	if (dmabits & RX_OFLO) {
+		port->hdlc.stats.rx_fifo_errors++;
+		dbg(DBG_ASS, "Rx fifo error on card %d port %d buffer %d\n",
+		    card->card_no, port->index, rxp);
+	}
+	if (dmabits & RX_CRC) {
+		port->hdlc.stats.rx_crc_errors++;
+		dbg(DBG_ASS, "Rx crc error on card %d port %d\n",
+		    card->card_no, port->index);
+	}
+	if (dmabits & RX_FRAM) {
+		port->hdlc.stats.rx_frame_errors++;
+		dbg(DBG_ASS, "Rx frame error on card %d port %d\n",
+		    card->card_no, port->index);
+	}
+	if (dmabits == (RX_STP | RX_ENP)) {
+		port->hdlc.stats.rx_length_errors++;
+		dbg(DBG_ASS, "Rx length error (%d) on card %d port %d\n",
+		    len, card->card_no, port->index);
+	}
 }
 
+/*      Rx Error Recovery
+ */
+static void
+fst_recover_rx_error(struct fst_card_info *card, struct fst_port_info *port,
+		     unsigned char dmabits, int rxp, unsigned short len)
+{
+	int i;
+	int pi;
+
+	pi = port->index;
+	/* 
+	 * Discard buffer descriptors until we see the start of the
+	 * next frame.  Note that for long frames this could be in
+	 * a subsequent interrupt. 
+	 */
+	i = 0;
+	while ((dmabits & (DMA_OWN | RX_STP)) == 0) {
+		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);
+		rxp = (rxp+1) % NUM_RX_BUFFER;
+		if (++i > NUM_RX_BUFFER) {
+			dbg(DBG_ASS, "intr_rx: Discarding more bufs"
+			    " than we have\n");
+			break;
+		}
+		dmabits = FST_RDB(card, rxDescrRing[pi][rxp].bits);
+		dbg(DBG_ASS, "DMA Bits of next buffer was %x\n", dmabits);
+	}
+	dbg(DBG_ASS, "There were %d subsequent buffers in error\n", i);
+
+	/* Discard the terminal buffer */
+	if (!(dmabits & DMA_OWN)) {
+		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);
+		rxp = (rxp+1) % NUM_RX_BUFFER;
+	}
+	port->rxpos = rxp;
+	return;
+
+}
 
 /*      Rx complete interrupt
  */
 static void
-fst_intr_rx ( struct fst_card_info *card, struct fst_port_info *port )
+fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port)
 {
-        unsigned char dmabits;
-        int pi;
-        int rxp;
-        unsigned short len;
-        struct sk_buff *skb;
-        int i;
-
-
-        /* Check we have a buffer to process */
-        pi  = port->index;
-        rxp = port->rxpos;
-        dmabits = FST_RDB ( card, rxDescrRing[pi][rxp].bits );
-        if ( dmabits & DMA_OWN )
-        {
-                dbg ( DBG_RX | DBG_INTR,"intr_rx: No buffer port %d pos %d\n",
-                                        pi, rxp );
-                return;
-        }
-
-        /* Get buffer length */
-        len = FST_RDW ( card, rxDescrRing[pi][rxp].mcnt );
-        /* Discard the CRC */
-        len -= 2;
-
-        /* Check buffer length and for other errors. We insist on one packet
-         * in one buffer. This simplifies things greatly and since we've
-         * allocated 8K it shouldn't be a real world limitation
-         */
-        dbg ( DBG_RX,"intr_rx: %d,%d: flags %x len %d\n", pi, rxp, dmabits,
-                                        len );
-        if ( dmabits != ( RX_STP | RX_ENP ) || len > LEN_RX_BUFFER - 2 )
-        {
-                port->hdlc.stats.rx_errors++;
-
-                /* Update error stats and discard buffer */
-                if ( dmabits & RX_OFLO )
-                {
-                        port->hdlc.stats.rx_fifo_errors++;
-                }
-                if ( dmabits & RX_CRC )
-                {
-                        port->hdlc.stats.rx_crc_errors++;
-                }
-                if ( dmabits & RX_FRAM )
-                {
-                        port->hdlc.stats.rx_frame_errors++;
-                }
-                if ( dmabits == ( RX_STP | RX_ENP ))
-                {
-                        port->hdlc.stats.rx_length_errors++;
-                }
-
-                /* Discard buffer descriptors until we see the end of packet
-                 * marker
-                 */
-                i = 0;
-                while (( dmabits & ( DMA_OWN | RX_ENP )) == 0 )
-                {
-                        FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
-                        if ( ++rxp >= NUM_RX_BUFFER )
-                                rxp = 0;
-                        if ( ++i > NUM_RX_BUFFER )
-                        {
-                                dbg ( DBG_ASS,"intr_rx: Discarding more bufs"
-                                                " than we have\n");
-                                break;
-                        }
-                        dmabits = FST_RDB ( card, rxDescrRing[pi][rxp].bits );
-                }
-
-                /* Discard the terminal buffer */
-                if ( ! ( dmabits & DMA_OWN ))
-                {
-                        FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
-                        if ( ++rxp >= NUM_RX_BUFFER )
-                                rxp = 0;
-                }
-                port->rxpos = rxp;
-                return;
-        }
-
-        /* Allocate SKB */
-        if (( skb = dev_alloc_skb ( len )) == NULL )
-        {
-                dbg ( DBG_RX,"intr_rx: can't allocate buffer\n");
-
-                port->hdlc.stats.rx_dropped++;
-
-                /* Return descriptor to card */
-                FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
-
-                if ( ++rxp >= NUM_RX_BUFFER )
-                        port->rxpos = 0;
-                else
-                        port->rxpos = rxp;
-                return;
-        }
-
-        memcpy_fromio ( skb_put ( skb, len ),
-                                card->mem + BUF_OFFSET ( rxBuffer[pi][rxp][0]),
-                                len );
-
-        /* Reset buffer descriptor */
-        FST_WRB ( card, rxDescrRing[pi][rxp].bits, DMA_OWN );
-        if ( ++rxp >= NUM_RX_BUFFER )
-                port->rxpos = 0;
-        else
-                port->rxpos = rxp;
-
-        /* Update stats */
-        port->hdlc.stats.rx_packets++;
-        port->hdlc.stats.rx_bytes += len;
-
-        /* Push upstream */
-        skb->mac.raw = skb->data;
-        skb->dev = hdlc_to_dev ( &port->hdlc );
-        skb->protocol = hdlc_type_trans(skb, skb->dev);
-        netif_rx ( skb );
+	unsigned char dmabits;
+	int pi;
+	int rxp;
+	int rx_status;
+	unsigned short len;
+	struct sk_buff *skb;
+
+	/* Check we have a buffer to process */
+	pi = port->index;
+	rxp = port->rxpos;
+	dmabits = FST_RDB(card, rxDescrRing[pi][rxp].bits);
+	if (dmabits & DMA_OWN) {
+		dbg(DBG_RX | DBG_INTR, "intr_rx: No buffer port %d pos %d\n",
+		    pi, rxp);
+		return;
+	}
+	if (card->dmarx_in_progress) {
+		return;
+	}
+
+	/* Get buffer length */
+	len = FST_RDW(card, rxDescrRing[pi][rxp].mcnt);
+	/* Discard the CRC */
+	len -= 2;
+	if (len == 0) {
+		/*
+		 * This seems to happen on the TE1 interface sometimes
+		 * so throw the frame away and log the event.
+		 */
+		printk_err("Frame received with 0 length. Card %d Port %d\n",
+			   card->card_no, port->index);
+		/* Return descriptor to card */
+		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);
+
+		rxp = (rxp+1) % NUM_RX_BUFFER;
+		port->rxpos = rxp;
+		return;
+	}
 
-        port_to_dev ( port )->last_rx = jiffies;
+	/* Check buffer length and for other errors. We insist on one packet
+	 * in one buffer. This simplifies things greatly and since we've
+	 * allocated 8K it shouldn't be a real world limitation
+	 */
+	dbg(DBG_RX, "intr_rx: %d,%d: flags %x len %d\n", pi, rxp, dmabits, len);
+	if (dmabits != (RX_STP | RX_ENP) || len > LEN_RX_BUFFER - 2) {
+		fst_log_rx_error(card, port, dmabits, rxp, len);
+		fst_recover_rx_error(card, port, dmabits, rxp, len);
+		return;
+	}
+
+	/* Allocate SKB */
+	if ((skb = dev_alloc_skb(len)) == NULL) {
+		dbg(DBG_RX, "intr_rx: can't allocate buffer\n");
+
+		port->hdlc.stats.rx_dropped++;
+
+		/* Return descriptor to card */
+		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);
+
+		rxp = (rxp+1) % NUM_RX_BUFFER;
+		port->rxpos = rxp;
+		return;
+	}
+
+	/*
+	 * We know the length we need to receive, len.
+	 * It's not worth using the DMA for reads of less than
+	 * FST_MIN_DMA_LEN
+	 */
+
+	if ((len < FST_MIN_DMA_LEN) || (card->family == FST_FAMILY_TXP)) {
+		memcpy_fromio(skb_put(skb, len),
+			      card->mem + BUF_OFFSET(rxBuffer[pi][rxp][0]),
+			      len);
+
+		/* Reset buffer descriptor */
+		FST_WRB(card, rxDescrRing[pi][rxp].bits, DMA_OWN);
+
+		/* Update stats */
+		port->hdlc.stats.rx_packets++;
+		port->hdlc.stats.rx_bytes += len;
+
+		/* Push upstream */
+		dbg(DBG_RX, "Pushing frame up the stack\n");
+		skb->mac.raw = skb->data;
+		skb->dev = hdlc_to_dev(&port->hdlc);
+		if (port->mode == FST_RAW) {
+			/*
+			 * Mark it for our own raw sockets interface
+			 */
+			skb->protocol = htons(ETH_P_CUST);
+			skb->pkt_type = PACKET_HOST;
+		} else {
+			skb->protocol = hdlc_type_trans(skb, skb->dev);
+		}
+		rx_status = netif_rx(skb);
+		fst_process_rx_status(rx_status, port_to_dev(port)->name);
+		if (rx_status == NET_RX_DROP) {
+			port->hdlc.stats.rx_dropped++;
+		}
+		port_to_dev(port)->last_rx = jiffies;
+	} else {
+		card->dma_skb_rx = skb;
+		card->dma_port_rx = port;
+		card->dma_len_rx = len;
+		card->dma_rxpos = rxp;
+		fst_rx_dma(card, (char *) card->rx_dma_handle_card,
+			   (char *) BUF_OFFSET(rxBuffer[pi][rxp][0]), len);
+	}
+	if (rxp != port->rxpos) {
+		dbg(DBG_ASS, "About to increment rxpos by more than 1\n");
+		dbg(DBG_ASS, "rxp = %d rxpos = %d\n", rxp, port->rxpos);
+	}
+	rxp = (rxp+1) % NUM_RX_BUFFER;
+	port->rxpos = rxp;
 }
 
+/*
+ *      The bottom halfs to the ISR
+ *
+ */
+
+static void
+do_bottom_half_tx(struct fst_card_info *card)
+{
+	struct fst_port_info *port;
+	int pi;
+	int txq_length;
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	/*
+	 *  Find a free buffer for the transmit
+	 *  Step through each port on this card
+	 */
+
+	dbg(DBG_TX, "do_bottom_half_tx\n");
+	for (pi = 0, port = card->ports; pi < card->nports; pi++, port++) {
+		if (!port->run)
+			continue;
+
+		while (!
+		       (FST_RDB(card, txDescrRing[pi][port->txpos].bits) &
+			DMA_OWN)
+&& !(card->dmatx_in_progress)) {
+			/*
+			 * There doesn't seem to be a txdone event per-se
+			 * We seem to have to deduce it, by checking the DMA_OWN
+			 * bit on the next buffer we think we can use
+			 */
+			spin_lock_irqsave(&card->card_lock, flags);
+			if ((txq_length = port->txqe - port->txqs) < 0) {
+				/*
+				 * This is the case where one has wrapped and the
+				 * maths gives us a negative number
+				 */
+				txq_length = txq_length + FST_TXQ_DEPTH;
+			}
+			spin_unlock_irqrestore(&card->card_lock, flags);
+			if (txq_length > 0) {
+				/*
+				 * There is something to send
+				 */
+				spin_lock_irqsave(&card->card_lock, flags);
+				skb = port->txq[port->txqs];
+				port->txqs++;
+				if (port->txqs == FST_TXQ_DEPTH) {
+					port->txqs = 0;
+				}
+				spin_unlock_irqrestore(&card->card_lock, flags);
+				/*
+				 * copy the data and set the required indicators on the
+				 * card.
+				 */
+				FST_WRW(card, txDescrRing[pi][port->txpos].bcnt,
+					cnv_bcnt(skb->len));
+				if ((skb->len < FST_MIN_DMA_LEN)
+				    || (card->family == FST_FAMILY_TXP)) {
+					/* Enqueue the packet with normal io */
+					memcpy_toio(card->mem +
+						    BUF_OFFSET(txBuffer[pi]
+							       [port->
+								txpos][0]),
+						    skb->data, skb->len);
+					FST_WRB(card,
+						txDescrRing[pi][port->txpos].
+						bits,
+						DMA_OWN | TX_STP | TX_ENP);
+					port->hdlc.stats.tx_packets++;
+					port->hdlc.stats.tx_bytes += skb->len;
+					port_to_dev(port)->trans_start =
+					    jiffies;
+				} else {
+					/* Or do it through dma */
+					memcpy(card->tx_dma_handle_host,
+					       skb->data, skb->len);
+					card->dma_port_tx = port;
+					card->dma_len_tx = skb->len;
+					card->dma_txpos = port->txpos;
+					fst_tx_dma(card,
+						   (char *) card->
+						   tx_dma_handle_card,
+						   (char *)
+						   BUF_OFFSET(txBuffer[pi]
+							      [port->txpos][0]),
+						   skb->len);
+				}
+				if (++port->txpos >= NUM_TX_BUFFER)
+					port->txpos = 0;
+				/*
+				 * If we have flow control on, can we now release it?
+				 */
+				if (port->start) {
+					if (txq_length < fst_txq_low) {
+						netif_wake_queue(port_to_dev
+								 (port));
+						port->start = 0;
+					}
+				}
+				dev_kfree_skb(skb);
+			} else {
+				/*
+				 * Nothing to send so break out of the while loop
+				 */
+				break;
+			}
+		}
+	}
+}
+
+static void
+do_bottom_half_rx(struct fst_card_info *card)
+{
+	struct fst_port_info *port;
+	int pi;
+	int rx_count = 0;
+
+	/* Check for rx completions on all ports on this card */
+	dbg(DBG_RX, "do_bottom_half_rx\n");
+	for (pi = 0, port = card->ports; pi < card->nports; pi++, port++) {
+		if (!port->run)
+			continue;
+		while (!(FST_RDB(card, rxDescrRing[pi][port->rxpos].bits)
+			 & DMA_OWN) && !(card->dmarx_in_progress)) {
+			if (rx_count > fst_max_reads) {
+				/*
+				 * Don't spend forever in receive processing
+				 * Schedule another event
+				 */
+				fst_q_work_item(&fst_work_intq, card->card_no);
+				tasklet_schedule(&fst_int_task);
+				break;	/* Leave the loop */
+			}
+			fst_intr_rx(card, port);
+			rx_count++;
+		}
+	}
+}
 
 /*
  *      The interrupt service routine
  *      Dev_id is our fst_card_info pointer
  */
 static void
-fst_intr ( int irq, void *dev_id, struct pt_regs *regs )
+fst_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-        struct fst_card_info *card;
-        struct fst_port_info *port;
-        int rdidx;                      /* Event buffer indices */
-        int wridx;
-        int event;                      /* Actual event for processing */
-        int pi;
-
-        if (( card = dev_id ) == NULL )
-        {
-                dbg ( DBG_INTR,"intr: spurious %d\n", irq );
-                return;
-        }
-
-        dbg ( DBG_INTR,"intr: %d %p\n", irq, card );
-
-        spin_lock ( &card->card_lock );
-
-        /* Clear and reprime the interrupt source */
-        fst_clear_intr ( card );
-
-        /* Set the software acknowledge */
-        FST_WRB ( card, interruptHandshake, 0xEE );
-
-        /* Drain the event queue */
-        rdidx = FST_RDB ( card, interruptEvent.rdindex );
-        wridx = FST_RDB ( card, interruptEvent.wrindex );
-        while ( rdidx != wridx )
-        {
-                event = FST_RDB ( card, interruptEvent.evntbuff[rdidx]);
-
-                port = &card->ports[event & 0x03];
-
-                dbg ( DBG_INTR,"intr: %x\n", event );
-
-                switch ( event )
-                {
-                case CTLA_CHG:
-                case CTLB_CHG:
-                case CTLC_CHG:
-                case CTLD_CHG:
-                        if ( port->run )
-                                fst_intr_ctlchg ( card, port );
-                        break;
-
-                case ABTA_SENT:
-                case ABTB_SENT:
-                case ABTC_SENT:
-                case ABTD_SENT:
-                        dbg ( DBG_TX,"Abort complete port %d\n", event & 0x03 );
-                        break;
-
-                case TXA_UNDF:
-                case TXB_UNDF:
-                case TXC_UNDF:
-                case TXD_UNDF:
-                        /* Difficult to see how we'd get this given that we
-                         * 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++;
-                        break;
-
-                case INIT_CPLT:
-                        dbg ( DBG_INIT,"Card init OK intr\n");
-                        break;
-
-                case INIT_FAIL:
-                        dbg ( DBG_INIT,"Card init FAILED intr\n");
-                        card->state = FST_IFAILED;
-                        break;
-
-                default:
-                        printk_err ("intr: unknown card event code. ignored\n");
-                        break;
-                }
-
-                /* Bump and wrap the index */
-                if ( ++rdidx >= MAX_CIRBUFF )
-                        rdidx = 0;
-        }
-        FST_WRB ( card, interruptEvent.rdindex, rdidx );
-
-        for ( pi = 0, port = card->ports ; pi < card->nports ; pi++, port++ )
-        {
-                if ( ! port->run )
-                        continue;
-
-                /* Check for rx completions */
-                while ( ! ( FST_RDB ( card, rxDescrRing[pi][port->rxpos].bits )
-                                                                & DMA_OWN ))
-                {
-                        fst_intr_rx ( card, port );
-                }
-
-                /* Check for Tx completions */
-                while ( port->txcnt > 0 && ! ( FST_RDB ( card,
-                        txDescrRing[pi][port->txipos].bits ) & DMA_OWN ))
-                {
-                        --port->txcnt;
-                        if ( ++port->txipos >= NUM_TX_BUFFER )
-                                port->txipos = 0;
-                        netif_wake_queue ( port_to_dev ( port ));
-                }
-        }
+	struct fst_card_info *card;
+	struct fst_port_info *port;
+	int rdidx;		/* Event buffer indices */
+	int wridx;
+	int event;		/* Actual event for processing */
+	unsigned int dma_intcsr = 0;
+	unsigned int do_card_interrupt;
+	unsigned int int_retry_count;
+
+	if ((card = dev_id) == NULL) {
+		dbg(DBG_INTR, "intr: spurious %d\n", irq);
+		return;
+	}
 
-        spin_unlock ( &card->card_lock );
-}
+	/*
+	 * Check to see if the interrupt was for this card
+	 * return if not
+	 * Note that the call to clear the interrupt is important
+	 */
+	dbg(DBG_INTR, "intr: %d %p\n", irq, card);
+	if (card->state != FST_RUNNING) {
+		printk_err
+		    ("Interrupt received for card %d in a non running state (%d)\n",
+		     card->card_no, card->state);
+
+		/* 
+		 * It is possible to really be running, i.e. we have re-loaded
+		 * a running card
+		 * Clear and reprime the interrupt source 
+		 */
+		fst_clear_intr(card);
+		return;
+	}
+
+	/* Clear and reprime the interrupt source */
+	fst_clear_intr(card);
+
+	/*
+	 * Is the interrupt for this card (handshake == 1)
+	 */
+	do_card_interrupt = 0;
+	if (FST_RDB(card, interruptHandshake) == 1) {
+		do_card_interrupt += FST_CARD_INT;
+		/* Set the software acknowledge */
+		FST_WRB(card, interruptHandshake, 0xEE);
+	}
+	if (card->family == FST_FAMILY_TXU) {
+		/*
+		 * Is it a DMA Interrupt
+		 */
+		dma_intcsr = inl(card->pci_conf + INTCSR_9054);
+		if (dma_intcsr & 0x00200000) {
+			/*
+			 * DMA Channel 0 (Rx transfer complete)
+			 */
+			dbg(DBG_RX, "DMA Rx xfer complete\n");
+			outb(0x8, card->pci_conf + DMACSR0);
+			fst_rx_dma_complete(card, card->dma_port_rx,
+					    card->dma_len_rx, card->dma_skb_rx,
+					    card->dma_rxpos);
+			card->dmarx_in_progress = 0;
+			do_card_interrupt += FST_RX_DMA_INT;
+		}
+		if (dma_intcsr & 0x00400000) {
+			/*
+			 * DMA Channel 1 (Tx transfer complete)
+			 */
+			dbg(DBG_TX, "DMA Tx xfer complete\n");
+			outb(0x8, card->pci_conf + DMACSR1);
+			fst_tx_dma_complete(card, card->dma_port_tx,
+					    card->dma_len_tx, card->dma_txpos);
+			card->dmatx_in_progress = 0;
+			do_card_interrupt += FST_TX_DMA_INT;
+		}
+	}
 
+	/*
+	 * Have we been missing Interrupts
+	 */
+	int_retry_count = FST_RDL(card, interruptRetryCount);
+	if (int_retry_count) {
+		dbg(DBG_ASS, "Card %d int_retry_count is  %d\n",
+		    card->card_no, int_retry_count);
+		FST_WRL(card, interruptRetryCount, 0);
+	}
+
+	if (!do_card_interrupt) {
+		return;
+	}
+
+	/* Scehdule the bottom half of the ISR */
+	fst_q_work_item(&fst_work_intq, card->card_no);
+	tasklet_schedule(&fst_int_task);
+
+	/* Drain the event queue */
+	rdidx = FST_RDB(card, interruptEvent.rdindex) & 0x1f;
+	wridx = FST_RDB(card, interruptEvent.wrindex) & 0x1f;
+	while (rdidx != wridx) {
+		event = FST_RDB(card, interruptEvent.evntbuff[rdidx]);
+		port = &card->ports[event & 0x03];
+
+		dbg(DBG_INTR, "Processing Interrupt event: %x\n", event);
+
+		switch (event) {
+		case TE1_ALMA:
+			dbg(DBG_INTR, "TE1 Alarm intr\n");
+			if (port->run)
+				fst_intr_te1_alarm(card, port);
+			break;
+
+		case CTLA_CHG:
+		case CTLB_CHG:
+		case CTLC_CHG:
+		case CTLD_CHG:
+			if (port->run)
+				fst_intr_ctlchg(card, port);
+			break;
+
+		case ABTA_SENT:
+		case ABTB_SENT:
+		case ABTC_SENT:
+		case ABTD_SENT:
+			dbg(DBG_TX, "Abort complete port %d\n", port->index);
+			break;
+
+		case TXA_UNDF:
+		case TXB_UNDF:
+		case TXC_UNDF:
+		case TXD_UNDF:
+			/* Difficult to see how we'd get this given that we
+			 * always load up the entire packet for DMA.
+			 */
+			dbg(DBG_TX, "Tx underflow port %d\n", port->index);
+
+			port->hdlc.stats.tx_errors++;
+			port->hdlc.stats.tx_fifo_errors++;
+			dbg(DBG_ASS, "Tx underflow on card %d port %d\n",
+			    card->card_no, port->index);
+			break;
+
+		case INIT_CPLT:
+			dbg(DBG_INIT, "Card init OK intr\n");
+			break;
+
+		case INIT_FAIL:
+			dbg(DBG_INIT, "Card init FAILED intr\n");
+			card->state = FST_IFAILED;
+			break;
+
+		default:
+			printk_err("intr: unknown card event %d. ignored\n",
+				   event);
+			break;
+		}
+
+		/* Bump and wrap the index */
+		if (++rdidx >= MAX_CIRBUFF)
+			rdidx = 0;
+	}
+	FST_WRB(card, interruptEvent.rdindex, rdidx);
+}
 
 /*      Check that the shared memory configuration is one that we can handle
  *      and that some basic parameters are correct
  */
 static void
-check_started_ok ( struct fst_card_info *card )
+check_started_ok(struct fst_card_info *card)
 {
-        int i;
+	int i;
 
-        /* Check structure version and end marker */
-        if ( FST_RDW ( card, smcVersion ) != SMC_VERSION )
-        {
-                printk_err ("Bad shared memory version %d expected %d\n",
-                                FST_RDW ( card, smcVersion ), SMC_VERSION );
-                card->state = FST_BADVERSION;
-                return;
-        }
-        if ( FST_RDL ( card, endOfSmcSignature ) != END_SIG )
-        {
-                printk_err ("Missing shared memory signature\n");
-                card->state = FST_BADVERSION;
-                return;
-        }
-        /* Firmware status flag, 0x00 = initialising, 0x01 = OK, 0xFF = fail */
-        if (( i = FST_RDB ( card, taskStatus )) == 0x01 )
-        {
-                card->state = FST_RUNNING;
-        }
-        else if ( i == 0xFF )
-        {
-                printk_err ("Firmware initialisation failed. Card halted\n");
-                card->state = FST_HALTED;
-                return;
-        }
-        else if ( i != 0x00 )
-        {
-                printk_err ("Unknown firmware status 0x%x\n", i );
-                card->state = FST_HALTED;
-                return;
-        }
-
-        /* Finally check the number of ports reported by firmware against the
-         * number we assumed at card detection. Should never happen with
-         * existing firmware etc so we just report it for the moment.
-         */
-        if ( FST_RDL ( card, numberOfPorts ) != card->nports )
-        {
-                printk_warn ("Port count mismatch."
-                                " Firmware thinks %d we say %d\n",
-                                FST_RDL ( card, numberOfPorts ), card->nports );
-        }
-}
+	/* Check structure version and end marker */
+	if (FST_RDW(card, smcVersion) != SMC_VERSION) {
+		printk_err("Bad shared memory version %d expected %d\n",
+			   FST_RDW(card, smcVersion), SMC_VERSION);
+		card->state = FST_BADVERSION;
+		return;
+	}
+	if (FST_RDL(card, endOfSmcSignature) != END_SIG) {
+		printk_err("Missing shared memory signature\n");
+		card->state = FST_BADVERSION;
+		return;
+	}
+	/* Firmware status flag, 0x00 = initialising, 0x01 = OK, 0xFF = fail */
+	if ((i = FST_RDB(card, taskStatus)) == 0x01) {
+		card->state = FST_RUNNING;
+	} else if (i == 0xFF) {
+		printk_err("Firmware initialisation failed. Card halted\n");
+		card->state = FST_HALTED;
+		return;
+	} else if (i != 0x00) {
+		printk_err("Unknown firmware status 0x%x\n", i);
+		card->state = FST_HALTED;
+		return;
+	}
 
+	/* Finally check the number of ports reported by firmware against the
+	 * number we assumed at card detection. Should never happen with
+	 * existing firmware etc so we just report it for the moment.
+	 */
+	if (FST_RDL(card, numberOfPorts) != card->nports) {
+		printk_warn("Port count mismatch on card %d."
+			    " Firmware thinks %d we say %d\n", card->card_no,
+			    FST_RDL(card, numberOfPorts), card->nports);
+	}
+}
 
 static int
-set_conf_from_info ( struct fst_card_info *card, struct fst_port_info *port,
-                struct fstioc_info *info )
+set_conf_from_info(struct fst_card_info *card, struct fst_port_info *port,
+		   struct fstioc_info *info)
 {
-        int err;
+	int err;
+	unsigned char my_framing;
 
-        /* Set things according to the user set valid flags.
-         * Several of the old options have been invalidated/replaced by the
-         * generic HDLC package.
-         */
-        err = 0;
-        if ( info->valid & FSTVAL_PROTO )
-                err = -EINVAL;
-        if ( info->valid & FSTVAL_CABLE )
-                err = -EINVAL;
-        if ( info->valid & FSTVAL_SPEED )
-                err = -EINVAL;
+	/* Set things according to the user set valid flags 
+	 * Several of the old options have been invalidated/replaced by the 
+	 * generic hdlc package.
+	 */
+	err = 0;
+	if (info->valid & FSTVAL_PROTO) {
+		if (info->proto == FST_RAW)
+			port->mode = FST_RAW;
+		else
+			port->mode = FST_GEN_HDLC;
+	}
+
+	if (info->valid & FSTVAL_CABLE)
+		err = -EINVAL;
 
-        if ( info->valid & FSTVAL_MODE )
-                FST_WRW ( card, cardMode, info->cardMode );
+	if (info->valid & FSTVAL_SPEED)
+		err = -EINVAL;
+
+	if (info->valid & FSTVAL_PHASE)
+		FST_WRB(card, portConfig[port->index].invertClock,
+			info->invertClock);
+	if (info->valid & FSTVAL_MODE)
+		FST_WRW(card, cardMode, info->cardMode);
+	if (info->valid & FSTVAL_TE1) {
+		FST_WRL(card, suConfig.dataRate, info->lineSpeed);
+		FST_WRB(card, suConfig.clocking, info->clockSource);
+		my_framing = FRAMING_E1;
+		if (info->framing == E1)
+			my_framing = FRAMING_E1;
+		if (info->framing == T1)
+			my_framing = FRAMING_T1;
+		if (info->framing == J1)
+			my_framing = FRAMING_J1;
+		FST_WRB(card, suConfig.framing, my_framing);
+		FST_WRB(card, suConfig.structure, info->structure);
+		FST_WRB(card, suConfig.interface, info->interface);
+		FST_WRB(card, suConfig.coding, info->coding);
+		FST_WRB(card, suConfig.lineBuildOut, info->lineBuildOut);
+		FST_WRB(card, suConfig.equalizer, info->equalizer);
+		FST_WRB(card, suConfig.transparentMode, info->transparentMode);
+		FST_WRB(card, suConfig.loopMode, info->loopMode);
+		FST_WRB(card, suConfig.range, info->range);
+		FST_WRB(card, suConfig.txBufferMode, info->txBufferMode);
+		FST_WRB(card, suConfig.rxBufferMode, info->rxBufferMode);
+		FST_WRB(card, suConfig.startingSlot, info->startingSlot);
+		FST_WRB(card, suConfig.losThreshold, info->losThreshold);
+		if (info->idleCode)
+			FST_WRB(card, suConfig.enableIdleCode, 1);
+		else
+			FST_WRB(card, suConfig.enableIdleCode, 0);
+		FST_WRB(card, suConfig.idleCode, info->idleCode);
 #if FST_DEBUG
-        if ( info->valid & FSTVAL_DEBUG )
-                fst_debug_mask = info->debug;
+		if (info->valid & FSTVAL_TE1) {
+			printk("Setting TE1 data\n");
+			printk("Line Speed = %d\n", info->lineSpeed);
+			printk("Start slot = %d\n", info->startingSlot);
+			printk("Clock source = %d\n", info->clockSource);
+			printk("Framing = %d\n", my_framing);
+			printk("Structure = %d\n", info->structure);
+			printk("interface = %d\n", info->interface);
+			printk("Coding = %d\n", info->coding);
+			printk("Line build out = %d\n", info->lineBuildOut);
+			printk("Equaliser = %d\n", info->equalizer);
+			printk("Transparent mode = %d\n",
+			       info->transparentMode);
+			printk("Loop mode = %d\n", info->loopMode);
+			printk("Range = %d\n", info->range);
+			printk("Tx Buffer mode = %d\n", info->txBufferMode);
+			printk("Rx Buffer mode = %d\n", info->rxBufferMode);
+			printk("LOS Threshold = %d\n", info->losThreshold);
+			printk("Idle Code = %d\n", info->idleCode);
+		}
+#endif
+	}
+#if FST_DEBUG
+	if (info->valid & FSTVAL_DEBUG) {
+		fst_debug_mask = info->debug;
+	}
 #endif
 
-        return err;
+	return err;
 }
 
 static void
-gather_conf_info ( struct fst_card_info *card, struct fst_port_info *port,
-                struct fstioc_info *info )
+gather_conf_info(struct fst_card_info *card, struct fst_port_info *port,
+		 struct fstioc_info *info)
 {
-        int i;
+	int i;
 
-        memset ( info, 0, sizeof ( struct fstioc_info ));
+	memset(info, 0, sizeof (struct fstioc_info));
 
-        i = port->index;
-        info->nports = card->nports;
-        info->type   = card->type;
-        info->state  = card->state;
-        info->proto  = FST_GEN_HDLC;
-        info->index  = i;
+	i = port->index;
+	info->kernelVersion = LINUX_VERSION_CODE;
+	info->nports = card->nports;
+	info->type = card->type;
+	info->state = card->state;
+	info->proto = FST_GEN_HDLC;
+	info->index = i;
 #if FST_DEBUG
-        info->debug  = fst_debug_mask;
+	info->debug = fst_debug_mask;
 #endif
 
-        /* Only mark information as valid if card is running.
-         * Copy the data anyway in case it is useful for diagnostics
-         */
-        info->valid
-                = (( card->state == FST_RUNNING ) ? FSTVAL_ALL : FSTVAL_CARD )
+	/* Only mark information as valid if card is running.
+	 * Copy the data anyway in case it is useful for diagnostics
+	 */
+	info->valid = ((card->state == FST_RUNNING) ? FSTVAL_ALL : FSTVAL_CARD)
 #if FST_DEBUG
-                | FSTVAL_DEBUG
+	    | FSTVAL_DEBUG
 #endif
-                ;
+	    ;
 
-        info->lineInterface = FST_RDW ( card, portConfig[i].lineInterface );
-        info->internalClock = FST_RDB ( card, portConfig[i].internalClock );
-        info->lineSpeed     = FST_RDL ( card, portConfig[i].lineSpeed );
-        info->v24IpSts      = FST_RDL ( card, v24IpSts[i] );
-        info->v24OpSts      = FST_RDL ( card, v24OpSts[i] );
-        info->clockStatus   = FST_RDW ( card, clockStatus[i] );
-        info->cableStatus   = FST_RDW ( card, cableStatus );
-        info->cardMode      = FST_RDW ( card, cardMode );
-        info->smcFirmwareVersion  = FST_RDL ( card, smcFirmwareVersion );
+	info->lineInterface = FST_RDW(card, portConfig[i].lineInterface);
+	info->internalClock = FST_RDB(card, portConfig[i].internalClock);
+	info->lineSpeed = FST_RDL(card, portConfig[i].lineSpeed);
+	info->invertClock = FST_RDB(card, portConfig[i].invertClock);
+	info->v24IpSts = FST_RDL(card, v24IpSts[i]);
+	info->v24OpSts = FST_RDL(card, v24OpSts[i]);
+	info->clockStatus = FST_RDW(card, clockStatus[i]);
+	info->cableStatus = FST_RDW(card, cableStatus);
+	info->cardMode = FST_RDW(card, cardMode);
+	info->smcFirmwareVersion = FST_RDL(card, smcFirmwareVersion);
+
+	/*
+	 * The T2U can report cable presence for both A or B
+	 * in bits 0 and 1 of cableStatus.  See which port we are and 
+	 * do the mapping.
+	 */
+	if (card->family == FST_FAMILY_TXU) {
+		if (port->index == 0) {
+			/*
+			 * Port A
+			 */
+			info->cableStatus = info->cableStatus & 1;
+		} else {
+			/*
+			 * Port B
+			 */
+			info->cableStatus = info->cableStatus >> 1;
+			info->cableStatus = info->cableStatus & 1;
+		}
+	}
+	/*
+	 * Some additional bits if we are TE1
+	 */
+	if (card->type == FST_TYPE_TE1) {
+		info->lineSpeed = FST_RDL(card, suConfig.dataRate);
+		info->clockSource = FST_RDB(card, suConfig.clocking);
+		info->framing = FST_RDB(card, suConfig.framing);
+		info->structure = FST_RDB(card, suConfig.structure);
+		info->interface = FST_RDB(card, suConfig.interface);
+		info->coding = FST_RDB(card, suConfig.coding);
+		info->lineBuildOut = FST_RDB(card, suConfig.lineBuildOut);
+		info->equalizer = FST_RDB(card, suConfig.equalizer);
+		info->loopMode = FST_RDB(card, suConfig.loopMode);
+		info->range = FST_RDB(card, suConfig.range);
+		info->txBufferMode = FST_RDB(card, suConfig.txBufferMode);
+		info->rxBufferMode = FST_RDB(card, suConfig.rxBufferMode);
+		info->startingSlot = FST_RDB(card, suConfig.startingSlot);
+		info->losThreshold = FST_RDB(card, suConfig.losThreshold);
+		if (FST_RDB(card, suConfig.enableIdleCode))
+			info->idleCode = FST_RDB(card, suConfig.idleCode);
+		else
+			info->idleCode = 0;
+		info->receiveBufferDelay =
+		    FST_RDL(card, suStatus.receiveBufferDelay);
+		info->framingErrorCount =
+		    FST_RDL(card, suStatus.framingErrorCount);
+		info->codeViolationCount =
+		    FST_RDL(card, suStatus.codeViolationCount);
+		info->crcErrorCount = FST_RDL(card, suStatus.crcErrorCount);
+		info->lineAttenuation = FST_RDL(card, suStatus.lineAttenuation);
+		info->lossOfSignal = FST_RDB(card, suStatus.lossOfSignal);
+		info->receiveRemoteAlarm =
+		    FST_RDB(card, suStatus.receiveRemoteAlarm);
+		info->alarmIndicationSignal =
+		    FST_RDB(card, suStatus.alarmIndicationSignal);
+	}
 }
 
-
 static int
-fst_set_iface ( struct fst_card_info *card, struct fst_port_info *port,
-                struct ifreq *ifr )
+fst_set_iface(struct fst_card_info *card, struct fst_port_info *port,
+	      struct ifreq *ifr)
 {
-        sync_serial_settings sync;
-        int i;
+	sync_serial_settings sync;
+	int i;
+
+	if (ifr->ifr_settings.size != sizeof (sync)) {
+		return -ENOMEM;
+	}
+
+	if (copy_from_user
+	    (&sync, ifr->ifr_settings.ifs_ifsu.sync, sizeof (sync))) {
+		return -EFAULT;
+	}
+
+	if (sync.loopback)
+		return -EINVAL;
+
+	i = port->index;
+
+	switch (ifr->ifr_settings.type) {
+	case IF_IFACE_V35:
+		FST_WRW(card, portConfig[i].lineInterface, V35);
+		port->hwif = V35;
+		break;
+
+	case IF_IFACE_V24:
+		FST_WRW(card, portConfig[i].lineInterface, V24);
+		port->hwif = V24;
+		break;
+
+	case IF_IFACE_X21:
+		FST_WRW(card, portConfig[i].lineInterface, X21);
+		port->hwif = X21;
+		break;
+
+	case IF_IFACE_X21D:
+		FST_WRW(card, portConfig[i].lineInterface, X21D);
+		port->hwif = X21D;
+		break;
+
+	case IF_IFACE_T1:
+		FST_WRW(card, portConfig[i].lineInterface, T1);
+		port->hwif = T1;
+		break;
+
+	case IF_IFACE_E1:
+		FST_WRW(card, portConfig[i].lineInterface, E1);
+		port->hwif = E1;
+		break;
+
+	case IF_IFACE_SYNC_SERIAL:
+		break;
+
+	default:
+		return -EINVAL;
+	}
 
-        if (copy_from_user (&sync, ifr->ifr_settings.ifs_ifsu.sync,
-			    sizeof (sync)))
-                return -EFAULT;
-
-        if ( sync.loopback )
-                return -EINVAL;
-
-        i = port->index;
-
-        switch (ifr->ifr_settings.type)
-        {
-        case IF_IFACE_V35:
-                FST_WRW ( card, portConfig[i].lineInterface, V35 );
-                port->hwif = V35;
-                break;
-
-        case IF_IFACE_V24:
-                FST_WRW ( card, portConfig[i].lineInterface, V24 );
-                port->hwif = V24;
-                break;
-
-        case IF_IFACE_X21:
-                FST_WRW ( card, portConfig[i].lineInterface, X21 );
-                port->hwif = X21;
-                break;
-
-        case IF_IFACE_SYNC_SERIAL:
-                break;
-
-        default:
-                return -EINVAL;
-        }
-
-        switch ( sync.clock_type )
-        {
-        case CLOCK_EXT:
-                FST_WRB ( card, portConfig[i].internalClock, EXTCLK );
-                break;
-
-        case CLOCK_INT:
-                FST_WRB ( card, portConfig[i].internalClock, INTCLK );
-                break;
-
-        default:
-                return -EINVAL;
-        }
-        FST_WRL ( card, portConfig[i].lineSpeed, sync.clock_rate );
-        return 0;
+	switch (sync.clock_type) {
+	case CLOCK_EXT:
+		FST_WRB(card, portConfig[i].internalClock, EXTCLK);
+		break;
+
+	case CLOCK_INT:
+		FST_WRB(card, portConfig[i].internalClock, INTCLK);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	FST_WRL(card, portConfig[i].lineSpeed, sync.clock_rate);
+	return 0;
 }
 
 static int
-fst_get_iface ( struct fst_card_info *card, struct fst_port_info *port,
-                struct ifreq *ifr )
+fst_get_iface(struct fst_card_info *card, struct fst_port_info *port,
+	      struct ifreq *ifr)
 {
-        sync_serial_settings sync;
-        int i;
+	sync_serial_settings sync;
+	int i;
 
-        /* First check what line type is set, we'll default to reporting X.21
-         * if nothing is set as IF_IFACE_SYNC_SERIAL implies it can't be
-         * changed
-         */
-        switch ( port->hwif )
-        {
-        case V35:
-                ifr->ifr_settings.type = IF_IFACE_V35;
-                break;
-        case V24:
-                ifr->ifr_settings.type = IF_IFACE_V24;
-                break;
-        case X21:
-        default:
-                ifr->ifr_settings.type = IF_IFACE_X21;
-                break;
-        }
-
-	if (ifr->ifr_settings.size < sizeof(sync)) {
-		ifr->ifr_settings.size = sizeof(sync); /* data size wanted */
-		return -ENOBUFS;
-	}
-
-        i = port->index;
-        sync.clock_rate = FST_RDL ( card, portConfig[i].lineSpeed );
-        /* Lucky card and linux use same encoding here */
-        sync.clock_type = FST_RDB ( card, portConfig[i].internalClock );
-        sync.loopback = 0;
-
-        if (copy_to_user (ifr->ifr_settings.ifs_ifsu.sync, &sync,
-			  sizeof(sync)))
-                return -EFAULT;
+	/* First check what line type is set, we'll default to reporting X.21
+	 * if nothing is set as IF_IFACE_SYNC_SERIAL implies it can't be
+	 * changed
+	 */
+	switch (port->hwif) {
+	case E1:
+		ifr->ifr_settings.type = IF_IFACE_E1;
+		break;
+	case T1:
+		ifr->ifr_settings.type = IF_IFACE_T1;
+		break;
+	case V35:
+		ifr->ifr_settings.type = IF_IFACE_V35;
+		break;
+	case V24:
+		ifr->ifr_settings.type = IF_IFACE_V24;
+		break;
+	case X21D:
+		ifr->ifr_settings.type = IF_IFACE_X21D;
+		break;
+	case X21:
+	default:
+		ifr->ifr_settings.type = IF_IFACE_X21;
+		break;
+	}
+	if (ifr->ifr_settings.size == 0) {
+		return 0;	/* only type requested */
+	}
+	if (ifr->ifr_settings.size < sizeof (sync)) {
+		return -ENOMEM;
+	}
 
-        return 0;
-}
+	i = port->index;
+	sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed);
+	/* Lucky card and linux use same encoding here */
+	sync.clock_type = FST_RDB(card, portConfig[i].internalClock) ==
+	    INTCLK ? CLOCK_INT : CLOCK_EXT;
+	sync.loopback = 0;
+
+	if (copy_to_user(ifr->ifr_settings.ifs_ifsu.sync, &sync, sizeof (sync))) {
+		return -EFAULT;
+	}
 
+	ifr->ifr_settings.size = sizeof (sync);
+	return 0;
+}
 
 static int
-fst_ioctl ( struct net_device *dev, struct ifreq *ifr, int cmd )
+fst_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-        struct fst_card_info *card;
-        struct fst_port_info *port;
-        struct fstioc_write wrthdr;
-        struct fstioc_info info;
-        unsigned long flags;
-
-        dbg ( DBG_IOCTL,"ioctl: %x, %p\n", cmd, ifr->ifr_data );
-
-        port = dev_to_port ( dev );
-        card = port->card;
-
-        if ( !capable ( CAP_NET_ADMIN ))
-                return -EPERM;
-
-        switch ( cmd )
-        {
-        case FSTCPURESET:
-                fst_cpureset ( card );
-                card->state = FST_RESET;
-                return 0;
-
-        case FSTCPURELEASE:
-                fst_cpurelease ( card );
-                card->state = FST_STARTING;
-                return 0;
-
-        case FSTWRITE:                  /* Code write (download) */
-
-                /* First copy in the header with the length and offset of data
-                 * to write
-                 */
-                if ( ifr->ifr_data == NULL )
-                {
-                        return -EINVAL;
-                }
-                if ( copy_from_user ( &wrthdr, ifr->ifr_data,
-                                        sizeof ( struct fstioc_write )))
-                {
-                        return -EFAULT;
-                }
-
-                /* Sanity check the parameters. We don't support partial writes
-                 * when going over the top
-                 */
-                if ( wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE
-				|| wrthdr.size + wrthdr.offset > FST_MEMSIZE )
-                {
-                        return -ENXIO;
-                }
-
-                /* Now copy the data to the card.
-                 * This will probably break on some architectures.
-                 * I'll fix it when I have something to test on.
-                 */
-                if ( copy_from_user ( card->mem + wrthdr.offset,
-                                ifr->ifr_data + sizeof ( struct fstioc_write ),
-                                wrthdr.size ))
-                {
-                        return -EFAULT;
-                }
-
-                /* Writes to the memory of a card in the reset state constitute
-                 * a download
-                 */
-                if ( card->state == FST_RESET )
-                {
-                        card->state = FST_DOWNLOAD;
-                }
-                return 0;
-
-        case FSTGETCONF:
-
-                /* If card has just been started check the shared memory config
-                 * version and marker
-                 */
-                if ( card->state == FST_STARTING )
-                {
-                        check_started_ok ( card );
-
-                        /* If everything checked out enable card interrupts */
-                        if ( card->state == FST_RUNNING )
-                        {
-                                spin_lock_irqsave ( &card->card_lock, flags );
-                                fst_clear_intr ( card );
-                                FST_WRB ( card, interruptHandshake, 0xEE );
-                                spin_unlock_irqrestore ( &card->card_lock,
-                                                                flags );
-                        }
-                }
-
-                if ( ifr->ifr_data == NULL )
-                {
-                        return -EINVAL;
-                }
-
-                gather_conf_info ( card, port, &info );
-
-                if ( copy_to_user ( ifr->ifr_data, &info, sizeof ( info )))
-                {
-                        return -EFAULT;
-                }
-                return 0;
-
-        case FSTSETCONF:
-
-                /* Most of the setting have been moved to the generic ioctls
-                 * this just covers debug and board ident mode now
-                 */
-                if ( copy_from_user ( &info,  ifr->ifr_data, sizeof ( info )))
-                {
-                        return -EFAULT;
-                }
-
-                return set_conf_from_info ( card, port, &info );
-
-        case SIOCWANDEV:
-                switch (ifr->ifr_settings.type)
-                {
-                case IF_GET_IFACE:
-                        return fst_get_iface ( card, port, ifr );
-
-                case IF_IFACE_SYNC_SERIAL:
-                case IF_IFACE_V35:
-                case IF_IFACE_V24:
-                case IF_IFACE_X21:
-                        return fst_set_iface ( card, port, ifr );
-
-                default:
-                        return hdlc_ioctl ( dev, ifr, cmd );
-                }
-
-        default:
-                /* Not one of ours. Pass through to HDLC package */
-                return hdlc_ioctl ( dev, ifr, cmd );
-        }
-}
-
-
-static void
-fst_openport ( struct fst_port_info *port )
-{
-        int signals;
-
-        /* Only init things if card is actually running. This allows open to
-         * succeed for downloads etc.
-         */
-        if ( port->card->state == FST_RUNNING )
-        {
-                if ( port->run )
-                {
-                        dbg ( DBG_OPEN,"open: found port already running\n");
-
-                        fst_issue_cmd ( port, STOPPORT );
-                        port->run = 0;
-                }
-
-                fst_rx_config ( port );
-                fst_tx_config ( port );
-                fst_op_raise ( port, OPSTS_RTS | OPSTS_DTR );
-
-                fst_issue_cmd ( port, STARTPORT );
-                port->run = 1;
-
-                signals = FST_RDL ( port->card, v24DebouncedSts[port->index]);
-                if ( signals & (( port->hwif == X21 ) ? IPSTS_INDICATE
-                                                      : IPSTS_DCD ))
-                        netif_carrier_on ( port_to_dev ( port ));
-                else
-                        netif_carrier_off ( port_to_dev ( port ));
-        }
-}
-
-static void
-fst_closeport ( struct fst_port_info *port )
-{
-        if ( port->card->state == FST_RUNNING )
-        {
-                if ( port->run )
-                {
-                        port->run = 0;
-                        fst_op_lower ( port, OPSTS_RTS | OPSTS_DTR );
-
-                        fst_issue_cmd ( port, STOPPORT );
-                }
-                else
-                {
-                        dbg ( DBG_OPEN,"close: port not running\n");
-                }
-        }
+	struct fst_card_info *card;
+	struct fst_port_info *port;
+	struct fstioc_write wrthdr;
+	struct fstioc_info info;
+	unsigned long flags;
+
+	dbg(DBG_IOCTL, "ioctl: %x, %p\n", cmd, ifr->ifr_data);
+
+	port = dev_to_port(dev);
+	card = port->card;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	switch (cmd) {
+	case FSTCPURESET:
+		fst_cpureset(card);
+		card->state = FST_RESET;
+		return 0;
+
+	case FSTCPURELEASE:
+		fst_cpurelease(card);
+		card->state = FST_STARTING;
+		return 0;
+
+	case FSTWRITE:		/* Code write (download) */
+
+		/* First copy in the header with the length and offset of data
+		 * to write
+		 */
+		if (ifr->ifr_data == NULL) {
+			return -EINVAL;
+		}
+		if (copy_from_user(&wrthdr, ifr->ifr_data,
+				   sizeof (struct fstioc_write))) {
+			return -EFAULT;
+		}
+
+		/* Sanity check the parameters. We don't support partial writes
+		 * when going over the top
+		 */
+		if (wrthdr.size > FST_MEMSIZE || wrthdr.offset > FST_MEMSIZE
+		    || wrthdr.size + wrthdr.offset > FST_MEMSIZE) {
+			return -ENXIO;
+		}
+
+		/* Now copy the data to the card.
+		 * This will probably break on some architectures.
+		 * I'll fix it when I have something to test on.
+		 */
+		if (copy_from_user(card->mem + wrthdr.offset,
+				   ifr->ifr_data + sizeof (struct fstioc_write),
+				   wrthdr.size)) {
+			return -EFAULT;
+		}
+
+		/* Writes to the memory of a card in the reset state constitute
+		 * a download
+		 */
+		if (card->state == FST_RESET) {
+			card->state = FST_DOWNLOAD;
+		}
+		return 0;
+
+	case FSTGETCONF:
+
+		/* If card has just been started check the shared memory config
+		 * version and marker
+		 */
+		if (card->state == FST_STARTING) {
+			check_started_ok(card);
+
+			/* If everything checked out enable card interrupts */
+			if (card->state == FST_RUNNING) {
+				spin_lock_irqsave(&card->card_lock, flags);
+				fst_enable_intr(card);
+				FST_WRB(card, interruptHandshake, 0xEE);
+				spin_unlock_irqrestore(&card->card_lock, flags);
+			}
+		}
+
+		if (ifr->ifr_data == NULL) {
+			return -EINVAL;
+		}
+
+		gather_conf_info(card, port, &info);
+
+		if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) {
+			return -EFAULT;
+		}
+		return 0;
+
+	case FSTSETCONF:
+
+		/*
+		 * Most of the settings have been moved to the generic ioctls
+		 * this just covers debug and board ident now
+		 */
+
+		if (card->state != FST_RUNNING) {
+			printk_err
+			    ("Attempt to configure card %d in non-running state (%d)\n",
+			     card->card_no, card->state);
+			return -EIO;
+		}
+		if (copy_from_user(&info, ifr->ifr_data, sizeof (info))) {
+			return -EFAULT;
+		}
+
+		return set_conf_from_info(card, port, &info);
+
+	case SIOCWANDEV:
+		switch (ifr->ifr_settings.type) {
+		case IF_GET_IFACE:
+			return fst_get_iface(card, port, ifr);
+
+		case IF_IFACE_SYNC_SERIAL:
+		case IF_IFACE_V35:
+		case IF_IFACE_V24:
+		case IF_IFACE_X21:
+		case IF_IFACE_X21D:
+		case IF_IFACE_T1:
+		case IF_IFACE_E1:
+			return fst_set_iface(card, port, ifr);
+
+		case IF_PROTO_RAW:
+			port->mode = FST_RAW;
+			return 0;
+
+		case IF_GET_PROTO:
+			if (port->mode == FST_RAW) {
+				ifr->ifr_settings.type = IF_PROTO_RAW;
+				return 0;
+			}
+			return hdlc_ioctl(dev, ifr, cmd);
+
+		default:
+			port->mode = FST_GEN_HDLC;
+			dbg(DBG_IOCTL, "Passing this type to hdlc %x\n",
+			    ifr->ifr_settings.type);
+			return hdlc_ioctl(dev, ifr, cmd);
+		}
+
+	default:
+		/* Not one of ours. Pass through to HDLC package */
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
 }
 
-
-static int
-fst_open ( struct net_device *dev )
+static void
+fst_openport(struct fst_port_info *port)
 {
-        int err;
+	int signals;
+	int txq_length;
 
-        err = hdlc_open ( dev_to_hdlc ( dev ));
-        if ( err )
-                return err;
+	/* Only init things if card is actually running. This allows open to
+	 * succeed for downloads etc.
+	 */
+	if (port->card->state == FST_RUNNING) {
+		if (port->run) {
+			dbg(DBG_OPEN, "open: found port already running\n");
+
+			fst_issue_cmd(port, STOPPORT);
+			port->run = 0;
+		}
+
+		fst_rx_config(port);
+		fst_tx_config(port);
+		fst_op_raise(port, OPSTS_RTS | OPSTS_DTR);
+
+		fst_issue_cmd(port, STARTPORT);
+		port->run = 1;
+
+		signals = FST_RDL(port->card, v24DebouncedSts[port->index]);
+		if (signals & (((port->hwif == X21) || (port->hwif == X21D))
+			       ? IPSTS_INDICATE : IPSTS_DCD))
+			netif_carrier_on(port_to_dev(port));
+		else
+			netif_carrier_off(port_to_dev(port));
+
+		txq_length = port->txqe - port->txqs;
+		port->txqe = 0;
+		port->txqs = 0;
+	}
 
-        MOD_INC_USE_COUNT;
+}
 
-        fst_openport ( dev_to_port ( dev ));
-        netif_wake_queue ( dev );
-        return 0;
+static void
+fst_closeport(struct fst_port_info *port)
+{
+	if (port->card->state == FST_RUNNING) {
+		if (port->run) {
+			port->run = 0;
+			fst_op_lower(port, OPSTS_RTS | OPSTS_DTR);
+
+			fst_issue_cmd(port, STOPPORT);
+		} else {
+			dbg(DBG_OPEN, "close: port not running\n");
+		}
+	}
 }
 
 static int
-fst_close ( struct net_device *dev )
+fst_open(struct net_device *dev)
 {
-        netif_stop_queue ( dev );
-        fst_closeport ( dev_to_port ( dev ));
-        hdlc_close ( dev_to_hdlc  ( dev ));
-        MOD_DEC_USE_COUNT;
-        return 0;
+	int err;
+	struct fst_port_info *port;
+
+	port = dev_to_port(dev);
+	MOD_INC_USE_COUNT;
+	if (port->mode != FST_RAW) {
+		err = hdlc_open(dev_to_hdlc(dev));
+		if (err)
+			return err;
+	}
+
+	fst_openport(port);
+	netif_wake_queue(dev);
+	return 0;
 }
 
 static int
-fst_attach ( hdlc_device *hdlc, unsigned short encoding, unsigned short parity )
+fst_close(struct net_device *dev)
 {
-        /* Setting currently fixed in FarSync card so we check and forget */
-        if ( encoding != ENCODING_NRZ || parity != PARITY_CRC16_PR1_CCITT )
-                return -EINVAL;
-        return 0;
+	struct fst_port_info *port;
+	struct fst_card_info *card;
+	unsigned char tx_dma_done;
+	unsigned char rx_dma_done;
+
+	port = dev_to_port(dev);
+	card = port->card;
+
+	tx_dma_done = inb(card->pci_conf + DMACSR1);
+	rx_dma_done = inb(card->pci_conf + DMACSR0);
+	dbg(DBG_OPEN,
+	    "Port Close: tx_dma_in_progress = %d (%x) rx_dma_in_progress = %d (%x)\n",
+	    card->dmatx_in_progress, tx_dma_done, card->dmarx_in_progress,
+	    rx_dma_done);
+
+	netif_stop_queue(dev);
+	fst_closeport(dev_to_port(dev));
+	if (port->mode != FST_RAW) {
+		hdlc_close(dev_to_hdlc(dev));
+	}
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
+static int
+fst_attach(hdlc_device * hdlc, 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)
+		return -EINVAL;
+	return 0;
+}
 
 static void
-fst_tx_timeout ( struct net_device *dev )
+fst_tx_timeout(struct net_device *dev)
 {
-        struct fst_port_info *port;
+	struct fst_port_info *port;
+	struct fst_card_info *card;
 
-        dbg ( DBG_INTR | DBG_TX,"tx_timeout\n");
+	port = dev_to_port(dev);
+	card = port->card;
 
-        port = dev_to_port ( dev );
-
-        port->hdlc.stats.tx_errors++;
-        port->hdlc.stats.tx_aborted_errors++;
-
-        if ( port->txcnt > 0 )
-                fst_issue_cmd ( port, ABORTTX );
-
-        dev->trans_start = jiffies;
-        netif_wake_queue ( dev );
+	port->hdlc.stats.tx_errors++;
+	port->hdlc.stats.tx_aborted_errors++;
+	dbg(DBG_ASS, "Tx timeout card %d port %d\n",
+	    card->card_no, port->index);
+	fst_issue_cmd(port, ABORTTX);
+
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+	port->start = 0;
 }
 
-
 static int
-fst_start_xmit ( struct sk_buff *skb, struct net_device *dev )
+fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-        struct fst_card_info *card;
-        struct fst_port_info *port;
-        unsigned char dmabits;
-        unsigned long flags;
-        int pi;
-        int txp;
-
-        port = dev_to_port ( dev );
-        card = port->card;
-
-        /* Drop packet with error if we don't have carrier */
-        if ( ! netif_carrier_ok ( dev ))
-        {
-                dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
-                port->hdlc.stats.tx_carrier_errors++;
-                return 0;
-        }
-
-        /* Drop it if it's too big! MTU failure ? */
-        if ( skb->len > LEN_TX_BUFFER )
-        {
-                dbg ( DBG_TX,"Packet too large %d vs %d\n", skb->len,
-                                                LEN_TX_BUFFER );
-                dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
-                return 0;
-        }
-
-        /* Check we have a buffer */
-        pi = port->index;
-        spin_lock_irqsave ( &card->card_lock, flags );
-        txp = port->txpos;
-        dmabits = FST_RDB ( card, txDescrRing[pi][txp].bits );
-        if ( dmabits & DMA_OWN )
-        {
-                spin_unlock_irqrestore ( &card->card_lock, flags );
-                dbg ( DBG_TX,"Out of Tx buffers\n");
-                dev_kfree_skb ( skb );
-                port->hdlc.stats.tx_errors++;
-                return 0;
-        }
-        if ( ++port->txpos >= NUM_TX_BUFFER )
-                port->txpos = 0;
-
-        if ( ++port->txcnt >= NUM_TX_BUFFER )
-                netif_stop_queue ( dev );
-
-        /* Release the card lock before we copy the data as we now have
-         * exclusive access to the buffer.
-         */
-        spin_unlock_irqrestore ( &card->card_lock, flags );
-
-        /* Enqueue the packet */
-        memcpy_toio ( card->mem + BUF_OFFSET ( txBuffer[pi][txp][0]),
-                                                skb->data, skb->len );
-        FST_WRW ( card, txDescrRing[pi][txp].bcnt, cnv_bcnt ( skb->len ));
-        FST_WRB ( card, txDescrRing[pi][txp].bits, DMA_OWN | TX_STP | TX_ENP );
+	struct fst_card_info *card;
+	struct fst_port_info *port;
+	unsigned long flags;
+	int txq_length;
+
+	port = dev_to_port(dev);
+	card = port->card;
+	dbg(DBG_TX, "fst_start_xmit: length = %d\n", skb->len);
+
+	/* Drop packet with error if we don't have carrier */
+	if (!netif_carrier_ok(dev)) {
+		dev_kfree_skb(skb);
+		port->hdlc.stats.tx_errors++;
+		port->hdlc.stats.tx_carrier_errors++;
+		dbg(DBG_ASS,
+		    "Tried to transmit but no carrier on card %d port %d\n",
+		    card->card_no, port->index);
+		return 0;
+	}
 
-        port->hdlc.stats.tx_packets++;
-        port->hdlc.stats.tx_bytes += skb->len;
+	/* Drop it if it's too big! MTU failure ? */
+	if (skb->len > LEN_TX_BUFFER) {
+		dbg(DBG_ASS, "Packet too large %d vs %d\n", skb->len,
+		    LEN_TX_BUFFER);
+		dev_kfree_skb(skb);
+		port->hdlc.stats.tx_errors++;
+		return 0;
+	}
 
-        dev_kfree_skb ( skb );
+	/*
+	 * We are always going to queue the packet
+	 * so that the bottom half is the only place we tx from
+	 * Check there is room in the port txq
+	 */
+	spin_lock_irqsave(&card->card_lock, flags);
+	if ((txq_length = port->txqe - port->txqs) < 0) {
+		/*
+		 * This is the case where the next free has wrapped but the
+		 * last used hasn't
+		 */
+		txq_length = txq_length + FST_TXQ_DEPTH;
+	}
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	if (txq_length > fst_txq_high) {
+		/*
+		 * We have got enough buffers in the pipeline.  Ask the network
+		 * layer to stop sending frames down
+		 */
+		netif_stop_queue(dev);
+		port->start = 1;	/* I'm using this to signal stop sent up */
+	}
 
-        dev->trans_start = jiffies;
-        return 0;
-}
+	if (txq_length == FST_TXQ_DEPTH - 1) {
+		/*
+		 * This shouldn't have happened but such is life
+		 */
+		dev_kfree_skb(skb);
+		port->hdlc.stats.tx_errors++;
+		dbg(DBG_ASS, "Tx queue overflow card %d port %d\n",
+		    card->card_no, port->index);
+		return 0;
+	}
 
+	/*
+	 * queue the buffer
+	 */
+	spin_lock_irqsave(&card->card_lock, flags);
+	port->txq[port->txqe] = skb;
+	port->txqe++;
+	if (port->txqe == FST_TXQ_DEPTH)
+		port->txqe = 0;
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+	/* Scehdule the bottom half which now does transmit processing */
+	fst_q_work_item(&fst_work_txq, card->card_no);
+	tasklet_schedule(&fst_tx_task);
+
+	return 0;
+}
 
 /*
  *      Card setup having checked hardware resources.
@@ -1441,256 +2382,302 @@ fst_start_xmit ( struct sk_buff *skb, st
  *      disabled.
  */
 static char *type_strings[] __devinitdata = {
-        "no hardware",                  /* Should never be seen */
-        "FarSync T2P",
-        "FarSync T4P"
+	"no hardware",		/* Should never be seen */
+	"FarSync T2P",
+	"FarSync T4P",
+	"FarSync T1U",
+	"FarSync T2U",
+	"FarSync T4U",
+	"FarSync TE1"
 };
 
 static void __devinit
-fst_init_card ( struct fst_card_info *card )
+fst_init_card(struct fst_card_info *card)
 {
-        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->rmem_start  = card->phys_mem
-                                 + BUF_OFFSET ( rxBuffer[i][0][0]);
-                dev->rmem_end    = card->phys_mem
-                                 + BUF_OFFSET ( rxBuffer[i][NUM_RX_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 )
-                {
-                        printk_err ("Cannot register HDLC device for port %d"
-                                    " (errno %d)\n", i, -err );
-                        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,
-                        type_strings[card->type], card->irq, card->nports );
-}
+	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;
+		card->ports[i].mode = FST_GEN_HDLC;
+
+		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) {
+			printk_err("Cannot register HDLC device for port %d"
+				   " (errno %d)\n", i, -err);
+			card->nports = i;
+			break;
+		}
+	}
 
+	spin_lock_init(&card->card_lock);
+
+	printk_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,
+	       type_strings[card->type], card->irq, card->nports);
+}
 
 /*
  *      Initialise card when detected.
  *      Returns 0 to indicate success, or errno otherwise.
  */
 static int __devinit
-fst_add_one ( struct pci_dev *pdev, const struct pci_device_id *ent )
+fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-        static int firsttime_done = 0;
-        struct fst_card_info *card;
-        int err = 0;
-
-        if ( ! firsttime_done )
-        {
-                printk ( KERN_INFO "FarSync X21 driver " FST_USER_VERSION
-                                " (c) 2001 FarSite Communications Ltd.\n");
-                firsttime_done = 1;
-        }
-
-        /* Allocate driver private data */
-        card = kmalloc ( sizeof ( struct fst_card_info ),  GFP_KERNEL);
-        if (card == NULL)
-        {
-                printk_err ("FarSync card found but insufficient memory for"
-                                " driver storage\n");
-                return -ENOMEM;
-        }
-        memset ( card, 0, sizeof ( struct fst_card_info ));
-
-        /* Record info we need*/
-        card->irq         = pdev->irq;
-        card->pci_conf    = pci_resource_start ( pdev, 1 );
-        card->phys_mem    = pci_resource_start ( pdev, 2 );
-        card->phys_ctlmem = pci_resource_start ( pdev, 3 );
-
-        card->type        = ent->driver_data;
-        card->nports      = ( ent->driver_data == FST_TYPE_T2P ) ? 2 : 4;
-
-        card->state       = FST_UNINIT;
-
-        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",
-                        card->pci_conf, card->phys_mem, card->phys_ctlmem );
-
-        /* Check we can get access to the memory and I/O regions */
-        if ( ! request_region ( card->pci_conf, 0x80,"PLX config regs"))
-        {
-                printk_err ("Unable to get config I/O @ 0x%04X\n",
-                                                card->pci_conf );
-                err = -ENODEV;
-                goto error_free_card;
-        }
-        if ( ! request_mem_region ( card->phys_mem, FST_MEMSIZE,"Shared RAM"))
-        {
-                printk_err ("Unable to get main memory @ 0x%08X\n",
-                                                card->phys_mem );
-                err = -ENODEV;
-                goto error_release_io;
-        }
-        if ( ! request_mem_region ( card->phys_ctlmem, 0x10,"Control memory"))
-        {
-                printk_err ("Unable to get control memory @ 0x%08X\n",
-                                                card->phys_ctlmem );
-                err = -ENODEV;
-                goto error_release_mem;
-        }
-
-        /* Try to enable the device */
-        if (( err = pci_enable_device ( pdev )) != 0 )
-        {
-                printk_err ("Failed to enable card. Err %d\n", -err );
-                goto error_release_ctlmem;
-        }
-
-        /* Get virtual addresses of memory regions */
-        if (( card->mem = ioremap ( card->phys_mem, FST_MEMSIZE )) == NULL )
-        {
-                printk_err ("Physical memory remap failed\n");
-                err = -ENODEV;
-                goto error_release_ctlmem;
-        }
-        if (( card->ctlmem = ioremap ( card->phys_ctlmem, 0x10 )) == NULL )
-        {
-                printk_err ("Control memory remap failed\n");
-                err = -ENODEV;
-                goto error_unmap_mem;
-        }
-        dbg ( DBG_PCI,"kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem);
-
-        /* Reset the card's processor */
-        fst_cpureset ( card );
-        card->state = FST_RESET;
-
-        /* Register the interrupt handler */
-        if ( request_irq ( card->irq, fst_intr, SA_SHIRQ, FST_DEV_NAME, card ))
-        {
-
-                printk_err ("Unable to register interrupt %d\n", card->irq );
-                err = -ENODEV;
-                goto error_unmap_ctlmem;
-        }
-
-        /* Record driver data for later use */
-        pci_set_drvdata(pdev, card);
-
-        /* Remainder of card setup */
-        fst_init_card ( card );
-
-        return 0;                       /* Success */
-
-
-                                        /* Failure. Release resources */
-error_unmap_ctlmem:
-        iounmap ( card->ctlmem );
-
-error_unmap_mem:
-        iounmap ( card->mem );
-
-error_release_ctlmem:
-        release_mem_region ( card->phys_ctlmem, 0x10 );
-
-error_release_mem:
-        release_mem_region ( card->phys_mem, FST_MEMSIZE );
-
-error_release_io:
-        release_region ( card->pci_conf, 0x80 );
-
-error_free_card:
-        kfree ( card );
-        return err;
-}
+	static int firsttime_done = 0;
+	static int no_of_cards_added = 0;
+	struct fst_card_info *card;
+	int err = 0;
+	int i;
+
+	if (!firsttime_done) {
+		printk_info("FarSync WAN driver " FST_USER_VERSION
+		       " (c) 2001-2004 FarSite Communications Ltd.\n");
+		firsttime_done = 1;
+		dbg(DBG_ASS, "The value of debug mask is %x\n", fst_debug_mask);
+	}
+
+	/*
+	 * We are going to be clever and allow certain cards not to be
+	 * configured.  An exclude list can be provided in /etc/modules.conf
+	 */
+	if (fst_excluded_cards != 0) {
+		/*
+		 * There are cards to exclude
+		 *
+		 */
+		for (i = 0; i < fst_excluded_cards; i++) {
+			if ((pdev->devfn) >> 3 == fst_excluded_list[i]) {
+				printk_info("FarSync PCI device %d not assigned\n",
+				       (pdev->devfn) >> 3);
+				return -EBUSY;
+			}
+		}
+	}
+
+	/* Allocate driver private data */
+	card = kmalloc(sizeof (struct fst_card_info), GFP_KERNEL);
+	if (card == NULL) {
+		printk_err("FarSync card found but insufficient memory for"
+			   " driver storage\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof (struct fst_card_info));
+
+	/* Try to enable the device */
+	if ((err = pci_enable_device(pdev)) != 0) {
+		printk_err("Failed to enable card. Err %d\n", -err);
+		kfree(card);
+		return err;
+	}
 
+	if ((err = pci_request_regions(pdev, "FarSync")) !=0) {
+	        printk_err("Failed to allocate regions. Err %d\n", -err);
+		pci_disable_device(pdev);
+		kfree(card);
+	        return err;
+	}
+
+	/* Get virtual addresses of memory regions */
+	card->pci_conf = pci_resource_start(pdev, 1);
+	card->phys_mem = pci_resource_start(pdev, 2);
+	card->phys_ctlmem = pci_resource_start(pdev, 3);
+	if ((card->mem = ioremap(card->phys_mem, FST_MEMSIZE)) == NULL) {
+		printk_err("Physical memory remap failed\n");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		kfree(card);
+		return -ENODEV;
+	}
+	if ((card->ctlmem = ioremap(card->phys_ctlmem, 0x10)) == NULL) {
+		printk_err("Control memory remap failed\n");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		kfree(card);
+		return -ENODEV;
+	}
+	dbg(DBG_PCI, "kernel mem %p, ctlmem %p\n", card->mem, card->ctlmem);
+
+	/* Register the interrupt handler */
+	if (request_irq(pdev->irq, fst_intr, SA_SHIRQ, FST_DEV_NAME, card)) {
+		printk_err("Unable to register interrupt %d\n", card->irq);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		iounmap(card->ctlmem);
+		iounmap(card->mem);
+		kfree(card);
+		return -ENODEV;
+	}
+
+	/* Record info we need */
+	card->irq = pdev->irq;
+	card->type = ent->driver_data;
+	card->family = ((ent->driver_data == FST_TYPE_T2P) ||
+			(ent->driver_data == FST_TYPE_T4P))
+	    ? FST_FAMILY_TXP : FST_FAMILY_TXU;
+	if ((ent->driver_data == FST_TYPE_T1U) ||
+	    (ent->driver_data == FST_TYPE_TE1))
+		card->nports = 1;
+	else
+		card->nports = ((ent->driver_data == FST_TYPE_T2P) ||
+				(ent->driver_data == FST_TYPE_T2U)) ? 2 : 4;
+
+	card->state = FST_UNINIT;
+	card->device = pdev;
+
+	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",
+	    card->pci_conf, card->phys_mem, card->phys_ctlmem);
+
+	/* Reset the card's processor */
+	fst_cpureset(card);
+	card->state = FST_RESET;
+
+	/* Initialise DMA (if required) */
+	fst_init_dma(card);
+
+	/* Record driver data for later use */
+	pci_set_drvdata(pdev, card);
+
+	/* Remainder of card setup */
+	fst_card_array[no_of_cards_added] = card;
+	card->card_no = no_of_cards_added++;	/* Record instance and bump it */
+	fst_init_card(card);
+	if (card->family == FST_FAMILY_TXU) {
+		/*
+		 * Allocate a dma buffer for transmit and receives
+		 */
+		card->rx_dma_handle_host =
+		    pci_alloc_consistent(card->device, FST_MAX_MTU,
+					 &card->rx_dma_handle_card);
+		if (card->rx_dma_handle_host == NULL) {
+			printk_err("Could not allocate rx dma buffer\n");
+			fst_disable_intr(card);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			iounmap(card->ctlmem);
+			iounmap(card->mem);
+			kfree(card);
+			return -ENOMEM;
+		}
+		card->tx_dma_handle_host =
+		    pci_alloc_consistent(card->device, FST_MAX_MTU,
+					 &card->tx_dma_handle_card);
+		if (card->tx_dma_handle_host == NULL) {
+			printk_err("Could not allocate tx dma buffer\n");
+			fst_disable_intr(card);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			iounmap(card->ctlmem);
+			iounmap(card->mem);
+			kfree(card);
+			return -ENOMEM;
+		}
+	}
+	return 0;		/* Success */
+}
 
 /*
  *      Cleanup and close down a card
  */
 static void __devexit
-fst_remove_one ( struct pci_dev *pdev )
+fst_remove_one(struct pci_dev *pdev)
 {
-        struct fst_card_info *card;
-        int i;
-
-        card = pci_get_drvdata(pdev);
+	struct fst_card_info *card;
+	int i;
 
-        for ( i = 0 ; i < card->nports ; i++ )
-        {
-                unregister_hdlc_device ( &card->ports[i].hdlc );
-        }
+	card = pci_get_drvdata(pdev);
 
-        fst_disable_intr ( card );
-        free_irq ( card->irq, card );
+	for (i = 0; i < card->nports; i++) {
+		unregister_hdlc_device(&card->ports[i].hdlc);
+	}
 
-        iounmap ( card->ctlmem );
-        iounmap ( card->mem );
+	fst_disable_intr(card);
+	free_irq(card->irq, card);
 
-        release_mem_region ( card->phys_ctlmem, 0x10 );
-        release_mem_region ( card->phys_mem, FST_MEMSIZE );
-        release_region ( card->pci_conf, 0x80 );
+	iounmap(card->ctlmem);
+	iounmap(card->mem);
 
-        kfree ( card );
+	pci_release_regions(pdev);
+#if 0
+	release_mem_region(card->phys_ctlmem, 0x10);
+	release_mem_region(card->phys_mem, FST_MEMSIZE);
+	if (card->family == FST_FAMILY_TXU) {
+		release_region(card->pci_conf, 0x100);
+	} else {
+		release_region(card->pci_conf, 0x80);
+	}
+#endif
+	if (card->family == FST_FAMILY_TXU) {
+		/*
+		 * Free dma buffers
+		 */
+		pci_free_consistent(card->device, FST_MAX_MTU,
+				    card->rx_dma_handle_host,
+				    card->rx_dma_handle_card);
+		pci_free_consistent(card->device, FST_MAX_MTU,
+				    card->tx_dma_handle_host,
+				    card->tx_dma_handle_card);
+	}
+	fst_card_array[card->card_no] = NULL;
 }
 
 static struct pci_driver fst_driver = {
-        name:           FST_NAME,
-        id_table:       fst_pci_dev_id,
-        probe:          fst_add_one,
-        remove:         __devexit_p(fst_remove_one),
-        suspend:        NULL,
-        resume:         NULL,
+	name:FST_NAME,
+	id_table:fst_pci_dev_id,
+	probe:fst_add_one,
+	remove:__devexit_p(fst_remove_one),
+	suspend:NULL,
+	resume:NULL,
 };
 
 static int __init
 fst_init(void)
 {
-        return pci_module_init ( &fst_driver );
+	int i;
+
+	for (i = 0; i < FST_MAX_CARDS; i++)
+		fst_card_array[i] = NULL;
+	spin_lock_init(&fst_work_q_lock);
+	return pci_module_init(&fst_driver);
 }
 
 static void __exit
 fst_cleanup_module(void)
 {
-        pci_unregister_driver ( &fst_driver );
+	printk_info("FarSync WAN driver unloading\n");
+	pci_unregister_driver(&fst_driver);
 }
 
-module_init ( fst_init );
-module_exit ( fst_cleanup_module );
-
+module_init(fst_init);
+module_exit(fst_cleanup_module);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/wan/farsync.h linux-2.4.27-rc4/drivers/net/wan/farsync.h
--- linux-2.4.26/drivers/net/wan/farsync.h	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/wan/farsync.h	2004-07-30 16:29:19.000000000 +0000
@@ -32,8 +32,13 @@
  *      A short common prefix is useful for routines within the driver to avoid
  *      conflict with other similar drivers and I chosen to use "fst_" for this
  *      purpose (FarSite T-series).
+ *
+ *      Finally the device driver needs a short network interface name. Since
+ *      "hdlc" is already in use I've chosen the even less informative "sync"
+ *      for the present.
  */
 #define FST_NAME                "fst"           /* In debug/info etc */
+#define FST_NDEV_NAME           "sync"          /* For net interface */
 #define FST_DEV_NAME            "farsync"       /* For misc interfaces */
 
 
@@ -45,7 +50,7 @@
  *      have individual versions (or IDs) that move much faster than the
  *      the release version as individual updates are tracked.
  */
-#define FST_USER_VERSION        "0.09"
+#define FST_USER_VERSION        "1.04"
 
 
 /*      Ioctl call command values
@@ -100,6 +105,7 @@ struct fstioc_info {
         unsigned int   state;           /* State of card */
         unsigned int   index;           /* Index of port ioctl was issued on */
         unsigned int   smcFirmwareVersion;
+        unsigned long  kernelVersion;   /* What Kernel version we are working with */
         unsigned short lineInterface;   /* Physical interface type */
         unsigned char  proto;           /* Line protocol */
         unsigned char  internalClock;   /* 1 => internal clock, 0 => external */
@@ -110,6 +116,31 @@ struct fstioc_info {
         unsigned short cableStatus;     /* lsb: 0=> present, 1=> absent */
         unsigned short cardMode;        /* lsb: LED id mode */
         unsigned short debug;           /* Debug flags */
+        unsigned char  transparentMode; /* Not used always 0 */
+        unsigned char  invertClock;     /* Invert clock feature for syncing */
+        unsigned char  startingSlot;    /* Time slot to use for start of tx */
+        unsigned char  clockSource;     /* External or internal */
+        unsigned char  framing;         /* E1, T1 or J1 */
+        unsigned char  structure;       /* unframed, double, crc4, f4, f12, */
+                                        /* f24 f72 */
+        unsigned char  interface;       /* rj48c or bnc */
+        unsigned char  coding;          /* hdb3 b8zs */
+        unsigned char  lineBuildOut;    /* 0, -7.5, -15, -22 */
+        unsigned char  equalizer;       /* short or lon haul settings */
+        unsigned char  loopMode;        /* various loopbacks */
+        unsigned char  range;           /* cable lengths */
+        unsigned char  txBufferMode;    /* tx elastic buffer depth */
+        unsigned char  rxBufferMode;    /* rx elastic buffer depth */
+        unsigned char  losThreshold;    /* Attenuation on LOS signal */
+        unsigned char  idleCode;        /* Value to send as idle timeslot */
+        unsigned int   receiveBufferDelay; /* delay thro rx buffer timeslots */
+        unsigned int   framingErrorCount; /* framing errors */
+        unsigned int   codeViolationCount; /* code violations */
+        unsigned int   crcErrorCount;   /* CRC errors */
+        int            lineAttenuation; /* in dB*/
+        unsigned short lossOfSignal;
+        unsigned short receiveRemoteAlarm;
+        unsigned short alarmIndicationSignal;
 };
 
 /* "valid" bitmask */
@@ -131,13 +162,23 @@ struct fstioc_info {
                                          */
 #define FSTVAL_PROTO    0x00000200      /* proto */
 #define FSTVAL_MODE     0x00000400      /* cardMode */
+#define FSTVAL_PHASE    0x00000800      /* Clock phase */
+#define FSTVAL_TE1      0x00001000      /* T1E1 Configuration */
 #define FSTVAL_DEBUG    0x80000000      /* debug */
-#define FSTVAL_ALL      0x000007FF      /* Note: does not include DEBUG flag */
+#define FSTVAL_ALL      0x00001FFF      /* Note: does not include DEBUG flag */
 
 /* "type" */
 #define FST_TYPE_NONE   0               /* Probably should never happen */
 #define FST_TYPE_T2P    1               /* T2P X21 2 port card */
 #define FST_TYPE_T4P    2               /* T4P X21 4 port card */
+#define FST_TYPE_T1U    3               /* T1U X21 1 port card */
+#define FST_TYPE_T2U    4               /* T2U X21 2 port card */
+#define FST_TYPE_T4U    5               /* T4U X21 4 port card */
+#define FST_TYPE_TE1    6               /* T1E1 X21 1 port card */
+
+/* "family" */
+#define FST_FAMILY_TXP  0               /* T2P or T4P */
+#define FST_FAMILY_TXU  1               /* T1U or T2U or T4U */
 
 /* "state" */
 #define FST_UNINIT      0               /* Raw uninitialised state following
@@ -155,6 +196,10 @@ struct fstioc_info {
 #define V24             1
 #define X21             2
 #define V35             3
+#define X21D            4
+#define T1              5
+#define E1              6
+#define J1              7
 
 /* "proto" */
 #define FST_HDLC        1               /* Cisco compatible HDLC */
@@ -187,6 +232,97 @@ struct fstioc_info {
 /* "cardMode" bitmask */
 #define CARD_MODE_IDENTIFY      0x0001
 
+/* 
+ * Constants for T1/E1 configuration
+ */
+
+/*
+ * Clock source
+ */
+#define CLOCKING_SLAVE       0
+#define CLOCKING_MASTER      1
+
+/*
+ * Framing
+ */
+#define FRAMING_E1           0
+#define FRAMING_J1           1
+#define FRAMING_T1           2
+
+/*
+ * Structure
+ */
+#define STRUCTURE_UNFRAMED   0
+#define STRUCTURE_E1_DOUBLE  1
+#define STRUCTURE_E1_CRC4    2
+#define STRUCTURE_E1_CRC4M   3
+#define STRUCTURE_T1_4       4
+#define STRUCTURE_T1_12      5
+#define STRUCTURE_T1_24      6
+#define STRUCTURE_T1_72      7
+
+/*
+ * Interface
+ */
+#define INTERFACE_RJ48C      0
+#define INTERFACE_BNC        1
+
+/*
+ * Coding
+ */
+
+#define CODING_HDB3          0
+#define CODING_NRZ           1
+#define CODING_CMI           2
+#define CODING_CMI_HDB3      3
+#define CODING_CMI_B8ZS      4
+#define CODING_AMI           5
+#define CODING_AMI_ZCS       6
+#define CODING_B8ZS          7
+
+/*
+ * Line Build Out
+ */
+#define LBO_0dB              0
+#define LBO_7dB5             1
+#define LBO_15dB             2
+#define LBO_22dB5            3
+
+/*
+ * Range for long haul t1 > 655ft
+ */
+#define RANGE_0_133_FT       0
+#define RANGE_0_40_M         RANGE_0_133_FT
+#define RANGE_133_266_FT     1
+#define RANGE_40_81_M        RANGE_133_266_FT
+#define RANGE_266_399_FT     2
+#define RANGE_81_122_M       RANGE_266_399_FT
+#define RANGE_399_533_FT     3
+#define RANGE_122_162_M       RANGE_399_533_FT
+#define RANGE_533_655_FT     4
+#define RANGE_162_200_M      RANGE_533_655_FT
+/*
+ * Receive Equaliser
+ */
+#define EQUALIZER_SHORT      0
+#define EQUALIZER_LONG       1
+
+/*
+ * Loop modes
+ */
+#define LOOP_NONE            0
+#define LOOP_LOCAL           1
+#define LOOP_PAYLOAD_EXC_TS0 2
+#define LOOP_PAYLOAD_INC_TS0 3
+#define LOOP_REMOTE          4
+
+/*
+ * Buffer modes
+ */
+#define BUFFER_2_FRAME       0
+#define BUFFER_1_FRAME       1
+#define BUFFER_96_BIT        2
+#define BUFFER_NONE          3
 
 /*      Debug support
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/wireless/airo.c linux-2.4.27-rc4/drivers/net/wireless/airo.c
--- linux-2.4.26/drivers/net/wireless/airo.c	2004-04-14 13:05:30.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/wireless/airo.c	2004-07-30 16:25:38.000000000 +0000
@@ -3666,19 +3666,22 @@ static ssize_t proc_read( struct file *f
 			  size_t len,
 			  loff_t *offset )
 {
-	int i;
-	int pos;
+	loff_t pos = *offset;
 	struct proc_data *priv = (struct proc_data*)file->private_data;
 
-	if( !priv->rbuffer ) return -EINVAL;
+	if (!priv->rbuffer)
+		return -EINVAL;
 
-	pos = *offset;
-	for( i = 0; i+pos < priv->readlen && i < len; i++ ) {
-		if (put_user( priv->rbuffer[i+pos], buffer+i ))
-			return -EFAULT;
-	}
-	*offset += i;
-	return i;
+	if (pos < 0)
+		return -EINVAL;
+	if (pos >= priv->readlen)
+		return 0;
+	if (len > priv->readlen - pos)
+		len = priv->readlen - pos;
+	if (copy_to_user(buffer, priv->rbuffer + pos, len))
+		return -EFAULT;
+	*offset = pos + len;
+	return len;
 }
 
 /*
@@ -3690,24 +3693,24 @@ static ssize_t proc_write( struct file *
 			   size_t len,
 			   loff_t *offset )
 {
-	int i;
-	int pos;
+	loff_t pos = *offset;
 	struct proc_data *priv = (struct proc_data*)file->private_data;
 
-	if ( !priv->wbuffer ) {
+	if (!priv->wbuffer)
 		return -EINVAL;
-	}
-
-	pos = *offset;
 
-	for( i = 0; i + pos <  priv->maxwritelen &&
-		     i < len; i++ ) {
-		if (get_user( priv->wbuffer[i+pos], buffer + i ))
-			return -EFAULT;
-	}
-	if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos;
-	*offset += i;
-	return i;
+	if (pos < 0)
+		return -EINVAL;
+	if (pos >= priv->maxwritelen)
+		return 0;
+	if (len > priv->maxwritelen - pos)
+		len = priv->maxwritelen - pos;
+	if (copy_from_user(priv->wbuffer + pos, buffer, len))
+		return -EFAULT;
+	if (pos + len > priv->writelen)
+		priv->writelen = pos + len;
+	*offset = pos + len;
+	return len;
 }
 
 static int proc_status_open( struct inode *inode, struct file *file ) {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/net/wireless/orinoco_pci.c linux-2.4.27-rc4/drivers/net/wireless/orinoco_pci.c
--- linux-2.4.26/drivers/net/wireless/orinoco_pci.c	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/net/wireless/orinoco_pci.c	2004-07-30 16:27:37.000000000 +0000
@@ -360,6 +360,7 @@ static int orinoco_pci_resume(struct pci
 
 static struct pci_device_id orinoco_pci_pci_id_table[] __devinitdata = {
 	{0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
+	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
 	{0,},
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/parport/ChangeLog linux-2.4.27-rc4/drivers/parport/ChangeLog
--- linux-2.4.26/drivers/parport/ChangeLog	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/parport/ChangeLog	2004-07-30 16:29:59.000000000 +0000
@@ -1,7 +1,16 @@
+2004-06-13  Marek Michalkiewicz  <marekm@amelek.gda.pl>
+
+       * parport_serial.c: Move from here to ../char/, must be initialised
+       after serial.c for register_serial to work.
+
 2002-11-29  Tim Waugh  <twaugh@redhat.com>
 
 	* parport_pc.c: Fix ECP hang on Aladdin card.
 
+	2001-10-11  Tim Waugh  <twaugh@redhat.com>
+	* parport_pc.c, parport_serial.c: Support for NetMos cards.
+	Patch originally from Michael Reinelt <reinelt@eunet.at>.
+
 2002-04-25  Tim Waugh  <twaugh@redhat.com>
 
 	* parport_serial.c, parport_pc.c: Move some SIIG cards around.
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/parport/Makefile linux-2.4.27-rc4/drivers/parport/Makefile
--- linux-2.4.26/drivers/parport/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/parport/Makefile	2004-07-30 16:25:00.000000000 +0000
@@ -22,7 +22,6 @@ endif
 
 obj-$(CONFIG_PARPORT)		+= parport.o
 obj-$(CONFIG_PARPORT_PC)	+= parport_pc.o
-obj-$(CONFIG_PARPORT_SERIAL)	+= parport_serial.o
 obj-$(CONFIG_PARPORT_PC_PCMCIA)	+= parport_cs.o
 obj-$(CONFIG_PARPORT_AMIGA)	+= parport_amiga.o
 obj-$(CONFIG_PARPORT_MFC3)	+= parport_mfc3.o
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/parport/parport_pc.c linux-2.4.27-rc4/drivers/parport/parport_pc.c
--- linux-2.4.26/drivers/parport/parport_pc.c	2003-06-13 14:51:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/parport/parport_pc.c	2004-07-30 16:27:54.000000000 +0000
@@ -2699,6 +2699,10 @@ enum parport_pc_pci_cards {
 	oxsemi_840,
 	aks_0100,
 	mobility_pp,
+	netmos_9705,
+	netmos_9805,
+	netmos_9815,
+	netmos_9855,
 };
 
 
@@ -2768,6 +2772,10 @@ static struct parport_pc_pci {
 	/* oxsemi_840 */		{ 1, { { 0, -1 }, } },
 	/* aks_0100 */			{ 1, { { 0, -1 }, } },
 	/* mobility_pp */		{ 1, { { 0, 1 }, } },
+	/* netmos_9705 */               { 1, { { 0, -1 }, } }, /* untested */
+	/* netmos_9805 */               { 1, { { 0, -1 }, } }, /* untested */
+	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
+	/* netmos_9855 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
@@ -2836,6 +2844,15 @@ static struct pci_device_id parport_pc_p
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_840 },
 	{ PCI_VENDOR_ID_AKS, PCI_DEVICE_ID_AKS_ALADDINCARD,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, aks_0100 },
+	/* NetMos communication controllers */
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9705,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9705 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9805,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
+	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/parport/parport_serial.c linux-2.4.27-rc4/drivers/parport/parport_serial.c
--- linux-2.4.26/drivers/parport/parport_serial.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.27-rc4/drivers/parport/parport_serial.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,426 +0,0 @@
-/*
- * Support for common PCI multi-I/O cards (which is most of them)
- *
- * Copyright (C) 2001  Tim Waugh <twaugh@redhat.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.
- *
- *
- * Multi-function PCI cards are supposed to present separate logical
- * devices on the bus.  A common thing to do seems to be to just use
- * one logical device with lots of base address registers for both
- * parallel ports and serial ports.  This driver is for dealing with
- * that.
- *
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/parport.h>
-#include <linux/parport_pc.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/list.h>
-
-#include <asm/serial.h>
-
-enum parport_pc_pci_cards {
-	titan_110l = 0,
-	titan_210l,
-	avlab_1s1p,
-	avlab_1s1p_650,
-	avlab_1s1p_850,
-	avlab_1s2p,
-	avlab_1s2p_650,
-	avlab_1s2p_850,
-	avlab_2s1p,
-	avlab_2s1p_650,
-	avlab_2s1p_850,
-	siig_1s1p_10x,
-	siig_2s1p_10x,
-	siig_2p1s_20x,
-	siig_1s1p_20x,
-	siig_2s1p_20x,
-};
-
-
-/* each element directly indexed from enum list, above */
-static struct parport_pc_pci {
-	int numports;
-	struct { /* BAR (base address registers) numbers in the config
-                    space header */
-		int lo;
-		int hi; /* -1 if not there, >6 for offset-method (max
-                           BAR is 6) */
-	} addr[4];
-
-	/* If set, this is called immediately after pci_enable_device.
-	 * If it returns non-zero, no probing will take place and the
-	 * ports will not be used. */
-	int (*preinit_hook) (struct pci_dev *pdev, int autoirq, int autodma);
-
-	/* If set, this is called after probing for ports.  If 'failed'
-	 * is non-zero we couldn't use any of the ports. */
-	void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
-	/* titan_110l */		{ 1, { { 3, -1 }, } },
-	/* titan_210l */		{ 1, { { 3, -1 }, } },
-	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
-	/* avlab_1s1p_650 */		{ 1, { { 1, 2}, } },
-	/* avlab_1s1p_850 */		{ 1, { { 1, 2}, } },
-	/* avlab_1s2p     */		{ 2, { { 1, 2}, { 3, 4 },} },
-	/* avlab_1s2p_650 */		{ 2, { { 1, 2}, { 3, 4 },} },
-	/* avlab_1s2p_850 */		{ 2, { { 1, 2}, { 3, 4 },} },
-	/* avlab_2s1p     */		{ 1, { { 2, 3}, } },
-	/* avlab_2s1p_650 */		{ 1, { { 2, 3}, } },
-	/* avlab_2s1p_850 */		{ 1, { { 2, 3}, } },
-	/* siig_1s1p_10x */		{ 1, { { 3, 4 }, } },
-	/* siig_2s1p_10x */		{ 1, { { 4, 5 }, } },
-	/* siig_2p1s_20x */		{ 2, { { 1, 2 }, { 3, 4 }, } },
-	/* siig_1s1p_20x */		{ 1, { { 1, 2 }, } },
-	/* siig_2s1p_20x */		{ 1, { { 2, 3 }, } },
-};
-
-static struct pci_device_id parport_serial_pci_tbl[] __devinitdata = {
-	/* PCI cards */
-	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_110L,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_110l },
-	{ PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_210L,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, titan_210l },
-	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
-	{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
-	{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
-	{ 0x14db, 0x2112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_850},
-	{ 0x14db, 0x2140, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p},
-	{ 0x14db, 0x2141, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_650},
-	{ 0x14db, 0x2142, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s2p_850},
-	{ 0x14db, 0x2160, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p},
-	{ 0x14db, 0x2161, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_650},
-	{ 0x14db, 0x2162, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2s1p_850},
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
-
-	{ 0, } /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
-
-struct pci_board_no_ids {
-	int flags;
-	int num_ports;
-	int base_baud;
-	int uart_offset;
-	int reg_shift;
-	int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,
-			int enable);
-	int first_uart_offset;
-};
-
-static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-	return pci_siig10x_fn(dev, NULL, enable);
-}
-
-static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)
-{
-	return pci_siig20x_fn(dev, NULL, enable);
-}
-
-static struct pci_board_no_ids pci_boards[] __devinitdata = {
-	/*
-	 * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
-	 * Offset to get to next UART's registers,
-	 * Register shift to use for memory-mapped I/O,
-	 * Initialization function, first UART offset
-	 */
-
-// Cards not tested are marked n/t
-// If you have one of these cards and it works for you, please tell me..
-
-/* titan_110l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
-/* titan_210l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
-/* avlab_1s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
-/* avlab_2s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },
-/* siig_1s1p_10x */	{ SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },
-/* siig_2s1p_10x */	{ SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },
-/* siig_2p1s_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_1s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-/* siig_2s1p_20x */	{ SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },
-};
-
-struct parport_serial_private {
-	int num_ser;
-	int line[20];
-	struct pci_board_no_ids ser;
-	int num_par;
-	struct parport *port[PARPORT_MAX];
-};
-
-static int __devinit get_pci_port (struct pci_dev *dev,
-				   struct pci_board_no_ids *board,
-				   struct serial_struct *req,
-				   int idx)
-{
-	unsigned long port;
-	int base_idx;
-	int max_port;
-	int offset;
-
-	base_idx = SPCI_FL_GET_BASE(board->flags);
-	if (board->flags & SPCI_FL_BASE_TABLE)
-		base_idx += idx;
-
-	if (board->flags & SPCI_FL_REGION_SZ_CAP) {
-		max_port = pci_resource_len(dev, base_idx) / 8;
-		if (idx >= max_port)
-			return 1;
-	}
-			
-	offset = board->first_uart_offset;
-
-	/* Timedia/SUNIX uses a mixture of BARs and offsets */
-	/* Ugh, this is ugly as all hell --- TYT */
-	if(dev->vendor == PCI_VENDOR_ID_TIMEDIA )  /* 0x1409 */
-		switch(idx) {
-			case 0: base_idx=0;
-				break;
-			case 1: base_idx=0; offset=8;
-				break;
-			case 2: base_idx=1; 
-				break;
-			case 3: base_idx=1; offset=8;
-				break;
-			case 4: /* BAR 2*/
-			case 5: /* BAR 3 */
-			case 6: /* BAR 4*/
-			case 7: base_idx=idx-2; /* BAR 5*/
-		}
-  
-	port =  pci_resource_start(dev, base_idx) + offset;
-
-	if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
-		port += idx * (board->uart_offset ? board->uart_offset : 8);
-
-	if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {
-		int high_bits_offset = ((sizeof(long)-sizeof(int))*8);
-		req->port = port;
-		if (high_bits_offset)
-			req->port_high = port >> high_bits_offset;
-		else
-			req->port_high = 0;
-		return 0;
-	}
-	req->io_type = SERIAL_IO_MEM;
-	req->iomem_base = ioremap(port, board->uart_offset);
-	req->iomem_reg_shift = board->reg_shift;
-	req->port = 0;
-	return req->iomem_base ? 0 : 1;
-}
-
-/* Register the serial port(s) of a PCI card. */
-static int __devinit serial_register (struct pci_dev *dev,
-				      const struct pci_device_id *id)
-{
-	struct pci_board_no_ids *board = &pci_boards[id->driver_data];
-	struct parport_serial_private *priv = pci_get_drvdata (dev);
-	struct serial_struct serial_req;
-	int base_baud;
-	int k;
-	int success = 0;
-
-	priv->ser = *board;
-	if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))
-		return 1;
-
-	base_baud = board->base_baud;
-	if (!base_baud)
-		base_baud = BASE_BAUD;
-	memset (&serial_req, 0, sizeof (serial_req));
-
-	for (k = 0; k < board->num_ports; k++) {
-		int line;
-		serial_req.irq = dev->irq;
-		if (get_pci_port (dev, board, &serial_req, k))
-			break;
-		serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
-		serial_req.baud_base = base_baud;
-		line = register_serial (&serial_req);
-		if (line < 0) {
-			printk (KERN_DEBUG
-				"parport_serial: register_serial failed\n");
-			continue;
-		}
-		priv->line[priv->num_ser++] = line;
-		success = 1;
-	}
-
-	return success ? 0 : 1;
-}
-
-/* Register the parallel port(s) of a PCI card. */
-static int __devinit parport_register (struct pci_dev *dev,
-				       const struct pci_device_id *id)
-{
-	struct parport_serial_private *priv = pci_get_drvdata (dev);
-	int i = id->driver_data, n;
-	int success = 0;
-
-	if (cards[i].preinit_hook &&
-	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
-		return -ENODEV;
-
-	for (n = 0; n < cards[i].numports; n++) {
-		struct parport *port;
-		int lo = cards[i].addr[n].lo;
-		int hi = cards[i].addr[n].hi;
-		unsigned long io_lo, io_hi;
-		io_lo = pci_resource_start (dev, lo);
-		io_hi = 0;
-		if ((hi >= 0) && (hi <= 6))
-			io_hi = pci_resource_start (dev, hi);
-		else if (hi > 6)
-			io_lo += hi; /* Reinterpret the meaning of
-                                        "hi" as an offset (see SYBA
-                                        def.) */
-		/* TODO: test if sharing interrupts works */
-		printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
-			"I/O at %#lx(%#lx)\n",
-			parport_serial_pci_tbl[i].vendor,
-			parport_serial_pci_tbl[i].device, io_lo, io_hi);
-		port = parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
-					      PARPORT_DMA_NONE, dev);
-		if (port) {
-			priv->port[priv->num_par++] = port;
-			success = 1;
-		}
-	}
-
-	if (cards[i].postinit_hook)
-		cards[i].postinit_hook (dev, !success);
-
-	return success ? 0 : 1;
-}
-
-static int __devinit parport_serial_pci_probe (struct pci_dev *dev,
-					       const struct pci_device_id *id)
-{
-	struct parport_serial_private *priv;
-	int err;
-
-	priv = kmalloc (sizeof *priv, GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-	priv->num_ser = priv->num_par = 0;
-	pci_set_drvdata (dev, priv);
-
-	err = pci_enable_device (dev);
-	if (err) {
-		pci_set_drvdata (dev, NULL);
-		kfree (priv);
-		return err;
-	}
-
-	if (parport_register (dev, id)) {
-		pci_set_drvdata (dev, NULL);
-		kfree (priv);
-		return -ENODEV;
-	}
-
-	if (serial_register (dev, id)) {
-		int i;
-		for (i = 0; i < priv->num_par; i++)
-			parport_pc_unregister_port (priv->port[i]);
-		pci_set_drvdata (dev, NULL);
-		kfree (priv);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void __devexit parport_serial_pci_remove (struct pci_dev *dev)
-{
-	struct parport_serial_private *priv = pci_get_drvdata (dev);
-	int i;
-
-	// Serial ports
-	for (i = 0; i < priv->num_ser; i++) {
-		unregister_serial (priv->line[i]);
-
-		if (priv->ser.init_fn)
-			(priv->ser.init_fn) (dev, &priv->ser, 0);
-	}
-	pci_set_drvdata (dev, NULL);
-	
-	// Parallel ports
-	for (i = 0; i < priv->num_par; i++)
-		parport_pc_unregister_port (priv->port[i]);
-
-	kfree (priv);
-	return;
-}
-
-static struct pci_driver parport_serial_pci_driver = {
-	name:		"parport_serial",
-	id_table:	parport_serial_pci_tbl,
-	probe:		parport_serial_pci_probe,
-	remove:		__devexit_p(parport_serial_pci_remove),
-};
-
-
-static int __init parport_serial_init (void)
-{
-	return pci_module_init (&parport_serial_pci_driver);
-}
-
-static void __exit parport_serial_exit (void)
-{
-	pci_unregister_driver (&parport_serial_pci_driver);
-	return;
-}
-
-MODULE_AUTHOR("Tim Waugh <twaugh@redhat.com>");
-MODULE_DESCRIPTION("Driver for common parallel+serial multi-I/O PCI cards");
-MODULE_LICENSE("GPL");
-
-module_init(parport_serial_init);
-module_exit(parport_serial_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/pci/pci.c linux-2.4.27-rc4/drivers/pci/pci.c
--- linux-2.4.26/drivers/pci/pci.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/pci/pci.c	2004-07-30 16:26:57.000000000 +0000
@@ -943,7 +943,7 @@ pci_generic_prep_mwi(struct pci_dev *dev
 	if (cacheline_size == pci_cache_line_size)
 		return 0;
 
-	printk(KERN_WARNING "PCI: cache line size of %d is not supported "
+	printk(KERN_DEBUG "PCI: cache line size of %d is not supported "
 	       "by device %s\n", pci_cache_line_size << 2, dev->slot_name);
 
 	return -EINVAL;
@@ -2214,6 +2214,7 @@ EXPORT_SYMBOL(pcibios_find_device);
 
 EXPORT_SYMBOL(isa_dma_bridge_buggy);
 EXPORT_SYMBOL(pci_pci_problems);
+EXPORT_SYMBOL(pciehp_msi_quirk);
 
 /* Pool allocator */
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/pci/pci.ids linux-2.4.27-rc4/drivers/pci/pci.ids
--- linux-2.4.26/drivers/pci/pci.ids	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/pci/pci.ids	2004-07-30 16:28:56.000000000 +0000
@@ -476,6 +476,7 @@
 	700f  PCI Bridge [IGP 320M]
 	7010  PCI Bridge [IGP 340M]
 	cab2  RS200/RS200M AGP Bridge [IGP 340M]
+	cbb2  RS200/RS200M AGP Bridge [IGP 345M]
 1003  ULSI Systems
 	0201  US201
 1004  VLSI Technology Inc
@@ -5542,13 +5543,21 @@
 	1649  NetXtreme BCM5704S Gigabit Ethernet
 	164d  NetXtreme BCM5702FE Gigabit Ethernet
 	1653  NetXtreme BCM5705 Gigabit Ethernet
-	1654  NetXtreme BCM5705 Gigabit Ethernet
+	1654  NetXtreme BCM5705_2 Gigabit Ethernet
+	1658  NetXtreme BCM5720 Gigabit Ethernet
+	1659  NetXtreme BCM5721 Gigabit Ethernet
 	165d  NetXtreme BCM5705M Gigabit Ethernet
-	165e  NetXtreme BCM5705M Gigabit Ethernet
+	165e  NetXtreme BCM5705M_2 Gigabit Ethernet
 	166e  NetXtreme BCM5705F Gigabit Ethernet
+	1676  NetXtreme BCM5750 Gigabit Ethernet
+	1677  NetXtreme BCM5751 Gigabit Ethernet
+	167c  NetXtreme BCM5750M Gigabit Ethernet
+	167d  NetXtreme BCM5751M Gigabit Ethernet
+	167e  NetXtreme BCM5751F Gigabit Ethernet
 	1696  NetXtreme BCM5782 Gigabit Ethernet
 		14e4 000d  NetXtreme BCM5782 1000Base-T
 	169c  NetXtreme BCM5788 Gigabit Ethernet
+	169d  NetXtreme BCM5789 Gigabit Ethernet
 	16a6  NetXtreme BCM5702 Gigabit Ethernet
 		0e11 00bb  NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
 		1028 0126  BCM5702 1000Base-T
@@ -5571,7 +5580,7 @@
 		14e4 0009  NetXtreme BCM5703 1000Base-T
 		14e4 000a  NetXtreme BCM5703 1000Base-SX
 	170d  NetXtreme BCM5901 Gigabit Ethernet
-	170e  NetXtreme BCM5901 Gigabit Ethernet
+	170e  NetXtreme BCM5901_2 Gigabit Ethernet
 	4210  BCM4210 iLine10 HomePNA 2.0
 	4211  BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
 	4212  BCM4212 v.90 56k modem
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/pci/quirks.c linux-2.4.27-rc4/drivers/pci/quirks.c
--- linux-2.4.26/drivers/pci/quirks.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/pci/quirks.c	2004-07-30 16:24:55.000000000 +0000
@@ -719,6 +719,13 @@ static void __init asus_hides_smbus_lpc(
 	}
 }
 
+int pciehp_msi_quirk;
+
+static void __devinit quirk_pciehp_msi(struct pci_dev *pdev)
+{
+	pciehp_msi_quirk = 1;
+}
+
 /*
  *  The main table of quirks.
  */
@@ -808,6 +815,8 @@ static struct pci_fixup pci_fixups[] __i
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801DB_0,	asus_hides_smbus_lpc },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82801BA_0,	asus_hides_smbus_lpc },
 
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_SMCH,  quirk_pciehp_msi },
+	
 	{ 0 }
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/pcmcia/yenta.c linux-2.4.27-rc4/drivers/pcmcia/yenta.c
--- linux-2.4.26/drivers/pcmcia/yenta.c	2004-04-14 13:05:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/pcmcia/yenta.c	2004-07-30 16:29:22.000000000 +0000
@@ -35,6 +35,8 @@
 #define to_cycles(ns)	((ns)/120)
 #define to_ns(cycles)	((cycles)*120)
 
+static int override_bios;
+
 /*
  * Generate easy-to-use ways of reading a cardbus sockets
  * regular memory space ("cb_xxx"), configuration space
@@ -753,7 +755,7 @@ static void yenta_allocate_res(pci_socke
 
 	start = config_readl(socket, offset) & mask;
 	end = config_readl(socket, offset+4) | ~mask;
-	if (start && end > start) {
+	if (start && end > start && !override_bios) {
 		res->start = start;
 		res->end = end;
 		if (request_resource(root, res) == 0)
@@ -950,6 +952,9 @@ static int yenta_open(pci_socket_t *sock
 
 	return 0;
 }
+  
+MODULE_PARM (override_bios, "i");
+MODULE_PARM_DESC (override_bios, "yenta ignore bios resource allocation");
 
 /*
  * Standard plain cardbus - no frills, no extensions
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/ChangeLog.ips linux-2.4.27-rc4/drivers/scsi/ChangeLog.ips
--- linux-2.4.26/drivers/scsi/ChangeLog.ips	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/ChangeLog.ips	2004-07-30 16:31:30.000000000 +0000
@@ -1,6 +1,13 @@
 IBM ServeRAID driver Change Log
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+        7.00.xx  - Linux 2.6 Kernel Changes
+             
+        6.11.07  - Make Logical Drive Info structure safe for DMA     
+                 - Get VersionInfo buffer off the stack !             
+        
+        6.10.24  - Remove 1G Addressing Limitations                   
+        
         6.00.00  - Add 6x Adapters and Battery Flash 
         
         5.30.00  - use __devexit_p()
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/Config.in linux-2.4.27-rc4/drivers/scsi/Config.in
--- linux-2.4.26/drivers/scsi/Config.in	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/Config.in	2004-07-30 16:27:53.000000000 +0000
@@ -68,6 +68,14 @@ dep_tristate 'Always IN2000 SCSI support
 dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI $CONFIG_PCI
 dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI
 dep_tristate 'AMI MegaRAID2 support' CONFIG_SCSI_MEGARAID2 $CONFIG_SCSI
+dep_mbool 'Serial ATA (SATA) support' CONFIG_SCSI_SATA $CONFIG_SCSI
+dep_tristate '  ServerWorks Frodo / Apple K2 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SVW $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  Promise SATA TX2/TX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_PROMISE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  SiS 964/180 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIS $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  VIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_VIA $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  Vitesse VSC-7174 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_VITESSE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
 
 dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
 if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/Makefile linux-2.4.27-rc4/drivers/scsi/Makefile
--- linux-2.4.26/drivers/scsi/Makefile	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/Makefile	2004-07-30 16:30:32.000000000 +0000
@@ -21,7 +21,7 @@ CFLAGS_seagate.o =   -DARBITRATE -DPARIT
 
 O_TARGET := scsidrv.o
 
-export-objs	:= scsi_syms.o 53c700.o
+export-objs	:= scsi_syms.o 53c700.o libata-core.o
 mod-subdirs	:= pcmcia ../acorn/scsi
 
 
@@ -130,6 +130,13 @@ obj-$(CONFIG_SCSI_FCAL)		+= fcal.o
 obj-$(CONFIG_SCSI_CPQFCTS)	+= cpqfc.o
 obj-$(CONFIG_SCSI_LASI700)	+= lasi700.o 53c700.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
+obj-$(CONFIG_SCSI_SATA_SVW)	+= libata.o sata_svw.o
+obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
+obj-$(CONFIG_SCSI_SATA_SIL)	+= libata.o sata_sil.o
+obj-$(CONFIG_SCSI_SATA_VIA)	+= libata.o sata_via.o
+obj-$(CONFIG_SCSI_SATA_VITESSE)	+= libata.o sata_vsc.o
+obj-$(CONFIG_SCSI_SATA_SIS)	+= libata.o sata_sis.o
+obj-$(CONFIG_SCSI_SATA_SX4)	+= libata.o sata_sx4.o
 
 subdir-$(CONFIG_ARCH_ACORN)	+= ../acorn/scsi
 obj-$(CONFIG_ARCH_ACORN)	+= ../acorn/scsi/acorn-scsi.o
@@ -141,7 +148,7 @@ obj-$(CONFIG_BLK_DEV_SR)	+= sr_mod.o
 obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 
 list-multi	:= scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o \
-			zalon7xx_mod.o
+			zalon7xx_mod.o libata.o
 scsi_mod-objs	:= scsi.o hosts.o scsi_ioctl.o constants.o \
 			scsicam.o scsi_proc.o scsi_error.o \
 			scsi_obsolete.o scsi_queue.o scsi_lib.o \
@@ -154,6 +161,7 @@ a100u2w-objs	:= inia100.o i60uscsi.o
 zalon7xx_mod-objs := zalon7xx.o ncr53c8xx.o
 cpqfc-objs	:= cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \
 		   cpqfcTSworker.o cpqfcTStrigger.o
+libata-objs	:= libata-core.o libata-scsi.o
 
 include $(TOPDIR)/Rules.make
 
@@ -179,6 +187,9 @@ zalon7xx_mod.o: $(zalon7xx_mod-objs)
 cpqfc.o: $(cpqfc-objs)
 	$(LD) -r -o $@ $(cpqfc-objs)
 
+libata.o: $(libata-objs)
+	$(LD) -r -o $@ $(libata-objs)
+
 53c8xx_d.h: 53c7,8xx.scr script_asm.pl
 	ln -sf 53c7,8xx.scr fake8.c
 	$(CPP) $(CPPFLAGS) -traditional -DCHIP=810 fake8.c | grep -v '^#' | $(PERL) script_asm.pl 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/NCR53C9x.c linux-2.4.27-rc4/drivers/scsi/NCR53C9x.c
--- linux-2.4.26/drivers/scsi/NCR53C9x.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/NCR53C9x.c	2004-07-30 16:26:35.000000000 +0000
@@ -917,7 +917,7 @@ static void esp_get_dmabufs(struct NCR_E
 		if (esp->dma_mmu_get_scsi_one)
 			esp->dma_mmu_get_scsi_one(esp, sp);
 		else
-			sp->SCp.have_data_in = (int) sp->SCp.ptr =
+			sp->SCp.ptr =
 				(char *) virt_to_phys(sp->request_buffer);
 	} else {
 		sp->SCp.buffer = (struct scatterlist *) sp->buffer;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/ips.c linux-2.4.27-rc4/drivers/scsi/ips.c
--- linux-2.4.26/drivers/scsi/ips.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/ips.c	2004-07-30 16:24:32.000000000 +0000
@@ -170,12 +170,11 @@
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
 
-#include <linux/blk.h>
+#include <linux/blkdev.h>
 #include <linux/types.h>
 
 #include <scsi/sg.h>
 
-#include "sd.h"
 #include "scsi.h"
 #include "hosts.h"
 #include "ips.h"
@@ -198,17 +197,22 @@ MODULE_PARM(ips, "s");
 /*
  * DRIVER_VER
  */
-#define IPS_VERSION_HIGH        "6.11"
-#define IPS_VERSION_LOW         ".07 "
+#define IPS_VERSION_HIGH        "7.00"
+#define IPS_VERSION_LOW         ".15 "
 
 #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)
 #warning "This driver has only been tested on the x86/ia64/x86_64 platforms"
 #endif
 
-#if LINUX_VERSION_CODE <= LinuxVersionCode(2,5,0)
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+#include <linux/blk.h>
+#include "sd.h"
 #define IPS_SG_ADDRESS(sg)       ((sg)->address)
 #define IPS_LOCK_SAVE(lock,flags) spin_lock_irqsave(&io_request_lock,flags)
 #define IPS_UNLOCK_RESTORE(lock,flags) spin_unlock_irqrestore(&io_request_lock,flags)
+#ifndef __devexit_p
+#define __devexit_p(x) x
+#endif
 #else
 #define IPS_SG_ADDRESS(sg)      (page_address((sg)->page) ? \
                                      page_address((sg)->page)+(sg)->offset : 0)
@@ -240,42 +244,70 @@ static ips_ha_t *ips_ha[IPS_MAX_ADAPTERS
 static unsigned int ips_next_controller;
 static unsigned int ips_num_controllers;
 static unsigned int ips_released_controllers;
+static int ips_hotplug;
 static int ips_cmd_timeout = 60;
 static int ips_reset_timeout = 60 * 5;
-static int ips_force_memio = 1;	/* Always use Memory Mapped I/O    */
+static int ips_force_memio = 1;		/* Always use Memory Mapped I/O    */
 static int ips_force_i2o = 1;	/* Always use I2O command delivery */
 static int ips_ioctlsize = IPS_IOCTL_SIZE;	/* Size of the ioctl buffer        */
-static int ips_cd_boot;		/* Booting from Manager CD         */
+static int ips_cd_boot;			/* Booting from Manager CD         */
 static char *ips_FlashData = NULL;	/* CD Boot - Flash Data Buffer      */
 static dma_addr_t ips_flashbusaddr;
-static long ips_FlashDataInUse;	/* CD Boot - Flash Data In Use Flag */
+static long ips_FlashDataInUse;		/* CD Boot - Flash Data In Use Flag */
 static uint32_t MaxLiteCmds = 32;	/* Max Active Cmds for a Lite Adapter */
-static Scsi_Host_Template ips_driver_template = IPS;
+static Scsi_Host_Template ips_driver_template = {
+	.detect			= ips_detect,
+	.release		= ips_release,
+	.info			= ips_info,
+	.queuecommand		= ips_queue,
+	.eh_abort_handler	= ips_eh_abort,
+	.eh_host_reset_handler	= ips_eh_reset,
+	.proc_name		= "ips",
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+	.proc_info		= ips_proc_info,
+	.slave_configure	= ips_slave_configure,
+#else
+	.proc_info		= ips_proc24_info,
+	.select_queue_depths	= ips_select_queue_depth,
+#endif
+	.bios_param		= ips_biosparam,
+	.this_id		= -1,
+	.sg_tablesize		= IPS_MAX_SG,
+	.cmd_per_lun		= 3,
+	.use_clustering		= ENABLE_CLUSTERING,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	.use_new_eh_code	= 1,
+#ifdef RHEL3
+    .vary_io            = 1,
+#endif
+#endif
+};
+
+IPS_DEFINE_COMPAT_TABLE( Compatable );	/* Version Compatability Table      */
 
-IPS_DEFINE_COMPAT_TABLE(Compatable);	/* Version Compatability Table      */
 
-   /* This table describes all ServeRAID Adapters */
-static struct pci_device_id ips_pci_table[] __devinitdata = {
-	{0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{0,}
+/* This table describes all ServeRAID Adapters */
+static struct  pci_device_id  ips_pci_table[] = {
+	{ 0x1014, 0x002E, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0x1014, 0x01BD, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0x9005, 0x0250, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
+	{ 0, }
 };
 
-MODULE_DEVICE_TABLE(pci, ips_pci_table);
+MODULE_DEVICE_TABLE( pci, ips_pci_table );
 
 static char ips_hot_plug_name[] = "ips";
-
-static int __devinit ips_insert_device(struct pci_dev *pci_dev,
-				       const struct pci_device_id *ent);
-static void ips_remove_device(struct pci_dev *pci_dev);
-
+   
+static int __devinit  ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent);
+static void __devexit ips_remove_device(struct pci_dev *pci_dev);
+   
 struct pci_driver ips_pci_driver = {
-	.name = ips_hot_plug_name,
-	.id_table = ips_pci_table,
-	.probe = ips_insert_device,
-	.remove = ips_remove_device,
+	.name		= ips_hot_plug_name,
+	.id_table	= ips_pci_table,
+	.probe		= ips_insert_device,
+	.remove		= __devexit_p(ips_remove_device),
 };
+           
 
 /*
  * Necessary forward function protoypes
@@ -299,7 +331,10 @@ static char ips_adapter_name[][30] = {
 	"ServeRAID 5i",
 	"ServeRAID 5i",
 	"ServeRAID 6M",
-	"ServeRAID 6i"
+	"ServeRAID 6i",
+	"ServeRAID 7t",
+	"ServeRAID 7k",
+	"ServeRAID 7M"
 };
 
 static struct notifier_block ips_notifier = {
@@ -371,9 +406,8 @@ int ips_release(struct Scsi_Host *);
 int ips_eh_abort(Scsi_Cmnd *);
 int ips_eh_reset(Scsi_Cmnd *);
 int ips_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-int ips_biosparam(Disk *, kdev_t, int *);
 const char *ips_info(struct Scsi_Host *);
-void do_ipsintr(int, void *, struct pt_regs *);
+irqreturn_t do_ipsintr(int, void *, struct pt_regs *);
 static int ips_hainit(ips_ha_t *);
 static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);
 static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);
@@ -424,8 +458,8 @@ static void ips_chkstatus(ips_ha_t *, IP
 static void ips_enable_int_copperhead(ips_ha_t *);
 static void ips_enable_int_copperhead_memio(ips_ha_t *);
 static void ips_enable_int_morpheus(ips_ha_t *);
-static void ips_intr_copperhead(ips_ha_t *);
-static void ips_intr_morpheus(ips_ha_t *);
+static int ips_intr_copperhead(ips_ha_t *);
+static int ips_intr_morpheus(ips_ha_t *);
 static void ips_next(ips_ha_t *, int);
 static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);
 static void ipsintr_done(ips_ha_t *, struct ips_scb *);
@@ -467,7 +501,7 @@ static void ips_scmd_buf_write(Scsi_Cmnd
 			       unsigned int count);
 static void ips_scmd_buf_read(Scsi_Cmnd * scmd, void *data, unsigned int count);
 
-int ips_proc_info(char *, char **, off_t, int, int, int);
+int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
 static int ips_host_info(ips_ha_t *, char *, off_t, int);
 static void copy_mem_info(IPS_INFOSTR *, char *, int);
 static int copy_info(IPS_INFOSTR *, char *, ...);
@@ -561,15 +595,12 @@ ips_detect(Scsi_Host_Template * SHT)
 		ips_setup(ips);
 #endif
 
-	SHT->proc_info = ips_proc_info;
-	SHT->proc_name = "ips";
-
 	for (i = 0; i < ips_num_controllers; i++) {
 		if (ips_register_scsi(i))
 			ips_free(ips_ha[i]);
 		ips_released_controllers++;
 	}
-
+	ips_hotplug = 1;
 	return (ips_num_controllers);
 }
 
@@ -680,15 +711,13 @@ ips_release(struct Scsi_Host *sh)
 	scb->cmd.flush_cache.reserved3 = 0;
 	scb->cmd.flush_cache.reserved4 = 0;
 
-	printk(KERN_NOTICE "(%s%d) Flushing Cache.\n", ips_name, ha->host_num);
+	IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n");
 
 	/* send command */
 	if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE)
-		printk(KERN_NOTICE "(%s%d) Incomplete Flush.\n", ips_name,
-		       ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev, "Incomplete Flush.\n");
 
-	printk(KERN_NOTICE "(%s%d) Flushing Complete.\n", ips_name,
-	       ha->host_num);
+	IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Complete.\n");
 
 	ips_sh[i] = NULL;
 	ips_ha[i] = NULL;
@@ -703,7 +732,8 @@ ips_release(struct Scsi_Host *sh)
 	/* free IRQ */
 	free_irq(ha->irq, ha);
 
-	scsi_unregister(sh);
+	IPS_REMOVE_HOST(sh);
+	scsi_host_put(sh);
 
 	ips_released_controllers++;
 
@@ -727,7 +757,8 @@ ips_halt(struct notifier_block *nb, ulon
 	int i;
 
 	if ((event != SYS_RESTART) && (event != SYS_HALT) &&
-	    (event != SYS_POWER_OFF)) return (NOTIFY_DONE);
+	    (event != SYS_POWER_OFF))
+		return (NOTIFY_DONE);
 
 	for (i = 0; i < ips_next_controller; i++) {
 		ha = (ips_ha_t *) ips_ha[i];
@@ -754,17 +785,16 @@ ips_halt(struct notifier_block *nb, ulon
 		scb->cmd.flush_cache.reserved3 = 0;
 		scb->cmd.flush_cache.reserved4 = 0;
 
-		printk(KERN_NOTICE "(%s%d) Flushing Cache.\n", ips_name,
-		       ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n");
 
 		/* send command */
 		if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) ==
-		    IPS_FAILURE) printk(KERN_NOTICE
-					"(%s%d) Incomplete Flush.\n", ips_name,
-					ha->host_num);
+		    IPS_FAILURE)
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "Incomplete Flush.\n");
 		else
-			printk(KERN_NOTICE "(%s%d) Flushing Complete.\n",
-			       ips_name, ha->host_num);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "Flushing Complete.\n");
 	}
 
 	return (NOTIFY_OK);
@@ -791,7 +821,7 @@ ips_eh_abort(Scsi_Cmnd * SC)
 	if (!SC)
 		return (FAILED);
 
-	ha = (ips_ha_t *) SC->host->hostdata;
+	ha = (ips_ha_t *) SC->device->host->hostdata;
 
 	if (!ha)
 		return (FAILED);
@@ -859,7 +889,7 @@ ips_eh_reset(Scsi_Cmnd * SC)
 		return (FAILED);
 	}
 
-	ha = (ips_ha_t *) SC->host->hostdata;
+	ha = (ips_ha_t *) SC->device->host->hostdata;
 
 	if (!ha) {
 		DEBUG(1, "Reset called with NULL ha struct");
@@ -916,9 +946,8 @@ ips_eh_reset(Scsi_Cmnd * SC)
 		/* Attempt the flush command */
 		ret = ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_IORL);
 		if (ret == IPS_SUCCESS) {
-			printk(KERN_NOTICE
-			       "(%s%d) Reset Request - Flushed Cache\n",
-			       ips_name, ha->host_num);
+			IPS_PRINTK(KERN_NOTICE, ha->pcidev,
+				   "Reset Request - Flushed Cache\n");
 			return (SUCCESS);
 		}
 	}
@@ -932,16 +961,14 @@ ips_eh_reset(Scsi_Cmnd * SC)
 	 * command must have already been sent
 	 * reset the controller
 	 */
-	printk(KERN_NOTICE "(%s%d) Resetting controller.\n",
-	       ips_name, ha->host_num);
+	IPS_PRINTK(KERN_NOTICE, ha->pcidev, "Resetting controller.\n");
 	ret = (*ha->func.reset) (ha);
 
 	if (!ret) {
 		Scsi_Cmnd *scsi_cmd;
 
-		printk(KERN_NOTICE
-		       "(%s%d) Controller reset failed - controller now offline.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_NOTICE, ha->pcidev,
+			   "Controller reset failed - controller now offline.\n");
 
 		/* Now fail all of the active commands */
 		DEBUG_VAR(1, "(%s%d) Failing active commands",
@@ -969,9 +996,8 @@ ips_eh_reset(Scsi_Cmnd * SC)
 	if (!ips_clear_adapter(ha, IPS_INTR_IORL)) {
 		Scsi_Cmnd *scsi_cmd;
 
-		printk(KERN_NOTICE
-		       "(%s%d) Controller reset failed - controller now offline.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_NOTICE, ha->pcidev,
+			   "Controller reset failed - controller now offline.\n");
 
 		/* Now fail all of the active commands */
 		DEBUG_VAR(1, "(%s%d) Failing active commands",
@@ -1050,7 +1076,7 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (
 
 	METHOD_TRACE("ips_queue", 1);
 
-	ha = (ips_ha_t *) SC->host->hostdata;
+	ha = (ips_ha_t *) SC->device->host->hostdata;
 
 	if (!ha)
 		return (1);
@@ -1076,10 +1102,13 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (
 
 	DEBUG_VAR(2, "(%s%d): ips_queue: cmd 0x%X (%d %d %d)",
 		  ips_name,
-		  ha->host_num, SC->cmnd[0], SC->channel, SC->target, SC->lun);
+		  ha->host_num,
+		  SC->cmnd[0],
+		  SC->device->channel, SC->device->id, SC->device->lun);
 
 	/* Check for command to initiator IDs */
-	if ((SC->channel > 0) && (SC->target == ha->ha_id[SC->channel])) {
+	if ((SC->device->channel > 0)
+	    && (SC->device->id == ha->ha_id[SC->device->channel])) {
 		SC->result = DID_NO_CONNECT << 16;
 		done(SC);
 
@@ -1140,18 +1169,24 @@ ips_queue(Scsi_Cmnd * SC, void (*done) (
 /*   Set bios geometry for the controller                                   */
 /*                                                                          */
 /****************************************************************************/
-int
+static int
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 ips_biosparam(Disk * disk, kdev_t dev, int geom[])
 {
-	ips_ha_t *ha;
+	ips_ha_t *ha = (ips_ha_t *) disk->device->host->hostdata;
+	unsigned long capacity = disk->capacity;
+#else
+ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+	      sector_t capacity, int geom[])
+{
+	ips_ha_t *ha = (ips_ha_t *) sdev->host->hostdata;
+#endif
 	int heads;
 	int sectors;
 	int cylinders;
 
 	METHOD_TRACE("ips_biosparam", 1);
 
-	ha = (ips_ha_t *) disk->device->host->hostdata;
-
 	if (!ha)
 		/* ?!?! host adater info invalid */
 		return (0);
@@ -1163,7 +1198,7 @@ ips_biosparam(Disk * disk, kdev_t dev, i
 		/* ?!?! Enquiry command failed */
 		return (0);
 
-	if ((disk->capacity > 0x400000) && ((ha->enq->ucMiscFlag & 0x8) == 0)) {
+	if ((capacity > 0x400000) && ((ha->enq->ucMiscFlag & 0x8) == 0)) {
 		heads = IPS_NORM_HEADS;
 		sectors = IPS_NORM_SECTORS;
 	} else {
@@ -1171,7 +1206,7 @@ ips_biosparam(Disk * disk, kdev_t dev, i
 		sectors = IPS_COMP_SECTORS;
 	}
 
-	cylinders = disk->capacity / (heads * sectors);
+	cylinders = (unsigned long) capacity / (heads * sectors);
 
 	DEBUG_VAR(2, "Geometry: heads: %d, sectors: %d, cylinders: %d",
 		  heads, sectors, cylinders);
@@ -1183,7 +1218,25 @@ ips_biosparam(Disk * disk, kdev_t dev, i
 	return (0);
 }
 
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+
+/* ips_proc24_info is a wrapper around ips_proc_info *
+ * for compatibility with the 2.4 scsi parameters    */
+static int
+ips_proc24_info(char *buffer, char **start, off_t offset, int length,
+		              int hostno, int func)
+{
+	int i;
+
+	for (i = 0; i < ips_next_controller; i++) {
+		if (ips_sh[i] && ips_sh[i]->host_no == hostno) {
+			return ips_proc_info(ips_sh[i], buffer, start,
+					     offset, length, func);
+		}
+	}
+	return -EINVAL;	
+}
+
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_select_queue_depth                                     */
@@ -1264,38 +1317,40 @@ ips_slave_configure(Scsi_Device * SDptr)
 /*   Wrapper for the interrupt handler                                      */
 /*                                                                          */
 /****************************************************************************/
-void
-do_ipsintr(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t
+do_ipsintr(int irq, void *dev_id, struct pt_regs * regs)
 {
 	ips_ha_t *ha;
 	unsigned long cpu_flags;
 	struct Scsi_Host *host;
+	int irqstatus;
 
 	METHOD_TRACE("do_ipsintr", 2);
 
 	ha = (ips_ha_t *) dev_id;
 	if (!ha)
-		return;
+		return IRQ_NONE;
 	host = ips_sh[ha->host_num];
 	/* interrupt during initialization */
 	if (!host) {
 		(*ha->func.intr) (ha);
-		return;
+		return IRQ_HANDLED;
 	}
 
 	IPS_LOCK_SAVE(host->host_lock, cpu_flags);
 
 	if (!ha->active) {
 		IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
-		return;
+		return IRQ_HANDLED;
 	}
 
-	(*ha->func.intr) (ha);
+	irqstatus = (*ha->func.intr) (ha);
 
 	IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
 
 	/* start the next command */
 	ips_next(ha, IPS_INTR_ON);
+	return IRQ_RETVAL(irqstatus);
 }
 
 /****************************************************************************/
@@ -1309,7 +1364,7 @@ do_ipsintr(int irq, void *dev_id, struct
 /*   ASSUMES interrupts are disabled                                        */
 /*                                                                          */
 /****************************************************************************/
-void
+int
 ips_intr_copperhead(ips_ha_t * ha)
 {
 	ips_stat_t *sp;
@@ -1320,10 +1375,10 @@ ips_intr_copperhead(ips_ha_t * ha)
 	METHOD_TRACE("ips_intr", 2);
 
 	if (!ha)
-		return;
+		return 0;
 
 	if (!ha->active)
-		return;
+		return 0;
 
 	intrstatus = (*ha->func.isintr) (ha);
 
@@ -1332,7 +1387,7 @@ ips_intr_copperhead(ips_ha_t * ha)
 		 * Unexpected/Shared interrupt
 		 */
 
-		return;
+		return 0;
 	}
 
 	while (TRUE) {
@@ -1359,6 +1414,7 @@ ips_intr_copperhead(ips_ha_t * ha)
 		 */
 		(*scb->callback) (ha, scb);
 	}			/* end while */
+	return 1;
 }
 
 /****************************************************************************/
@@ -1372,7 +1428,7 @@ ips_intr_copperhead(ips_ha_t * ha)
 /*   ASSUMES interrupts are disabled                                        */
 /*                                                                          */
 /****************************************************************************/
-void
+int
 ips_intr_morpheus(ips_ha_t * ha)
 {
 	ips_stat_t *sp;
@@ -1383,10 +1439,10 @@ ips_intr_morpheus(ips_ha_t * ha)
 	METHOD_TRACE("ips_intr_morpheus", 2);
 
 	if (!ha)
-		return;
+		return 0;
 
 	if (!ha->active)
-		return;
+		return 0;
 
 	intrstatus = (*ha->func.isintr) (ha);
 
@@ -1395,7 +1451,7 @@ ips_intr_morpheus(ips_ha_t * ha)
 		 * Unexpected/Shared interrupt
 		 */
 
-		return;
+		return 0;
 	}
 
 	while (TRUE) {
@@ -1413,9 +1469,8 @@ ips_intr_morpheus(ips_ha_t * ha)
 			break;
 
 		if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
-			printk(KERN_WARNING
-			       "(%s%d) Spurious interrupt; no ccb.\n", ips_name,
-			       ha->host_num);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "Spurious interrupt; no ccb.\n");
 
 			continue;
 		}
@@ -1429,6 +1484,7 @@ ips_intr_morpheus(ips_ha_t * ha)
 		 */
 		(*scb->callback) (ha, scb);
 	}			/* end while */
+	return 1;
 }
 
 /****************************************************************************/
@@ -1479,8 +1535,8 @@ ips_info(struct Scsi_Host *SH)
 /*                                                                          */
 /****************************************************************************/
 int
-ips_proc_info(char *buffer, char **start, off_t offset,
-	      int length, int hostno, int func)
+ips_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
+	      int length, int func)
 {
 	int i;
 	int ret;
@@ -1491,7 +1547,7 @@ ips_proc_info(char *buffer, char **start
 	/* Find our host structure */
 	for (i = 0; i < ips_next_controller; i++) {
 		if (ips_sh[i]) {
-			if (ips_sh[i]->host_no == hostno) {
+			if (ips_sh[i] == host) {
 				ha = (ips_ha_t *) ips_sh[i]->hostdata;
 				break;
 			}
@@ -1537,9 +1593,9 @@ ips_is_passthru(Scsi_Cmnd * SC)
 		return (0);
 
 	if ((SC->cmnd[0] == IPS_IOCTL_COMMAND) &&
-	    (SC->channel == 0) &&
-	    (SC->target == IPS_ADAPTER_ID) &&
-	    (SC->lun == 0) && SC->request_buffer) {
+	    (SC->device->channel == 0) &&
+	    (SC->device->id == IPS_ADAPTER_ID) &&
+	    (SC->device->lun == 0) && SC->request_buffer) {
 		if ((!SC->use_sg) && SC->request_bufflen &&
 		    (((char *) SC->request_buffer)[0] == 'C') &&
 		    (((char *) SC->request_buffer)[1] == 'O') &&
@@ -1671,7 +1727,8 @@ ips_make_passthru(ips_ha_t * ha, Scsi_Cm
 			}
 
 			if (ha->device_id == IPS_DEVICEID_COPPERHEAD &&
-			    pt->CoppCP.cmd.flashfw.op_code == IPS_CMD_RW_BIOSFW) {
+			    pt->CoppCP.cmd.flashfw.op_code ==
+			    IPS_CMD_RW_BIOSFW) {
 				ret = ips_flash_copperhead(ha, pt, scb);
 				ips_scmd_buf_write(SC, ha->ioctl_data,
 						   sizeof (ips_passthru_t));
@@ -1741,7 +1798,8 @@ ips_flash_copperhead(ips_ha_t * ha, ips_
 		if (pt->CoppCP.cmd.flashfw.count + ha->flash_datasize >
 		    ha->flash_len) {
 			ips_free_flash_copperhead(ha);
-			printk(KERN_WARNING "failed size sanity check\n");
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "failed size sanity check\n");
 			return IPS_FAILURE;
 		}
 	}
@@ -1773,24 +1831,29 @@ ips_flash_bios(ips_ha_t * ha, ips_passth
 	if (pt->CoppCP.cmd.flashfw.type == IPS_BIOS_IMAGE &&
 	    pt->CoppCP.cmd.flashfw.direction == IPS_WRITE_BIOS) {
 		if ((!ha->func.programbios) || (!ha->func.erasebios) ||
-		    (!ha->func.verifybios)) goto error;
+		    (!ha->func.verifybios))
+			goto error;
 		if ((*ha->func.erasebios) (ha)) {
 			DEBUG_VAR(1,
 				  "(%s%d) flash bios failed - unable to erase flash",
 				  ips_name, ha->host_num);
 			goto error;
 		} else
-		    if ((*ha->func.programbios)
-			(ha, ha->flash_data + IPS_BIOS_HEADER,
-			 ha->flash_datasize - IPS_BIOS_HEADER, 0)) {
+		    if ((*ha->func.programbios) (ha,
+						 ha->flash_data +
+						 IPS_BIOS_HEADER,
+						 ha->flash_datasize -
+						 IPS_BIOS_HEADER, 0)) {
 			DEBUG_VAR(1,
 				  "(%s%d) flash bios failed - unable to flash",
 				  ips_name, ha->host_num);
 			goto error;
 		} else
-		    if ((*ha->func.verifybios)
-			(ha, ha->flash_data + IPS_BIOS_HEADER,
-			 ha->flash_datasize - IPS_BIOS_HEADER, 0)) {
+		    if ((*ha->func.verifybios) (ha,
+						ha->flash_data +
+						IPS_BIOS_HEADER,
+						ha->flash_datasize -
+						IPS_BIOS_HEADER, 0)) {
 			DEBUG_VAR(1,
 				  "(%s%d) flash bios failed - unable to verify flash",
 				  ips_name, ha->host_num);
@@ -1823,7 +1886,7 @@ ips_flash_bios(ips_ha_t * ha, ips_passth
 /*                                                                          */
 /* Routine Description:                                                     */
 /*   Fill in a single scb sg_list element from an address                   */
-/*   return a -1 if a breakup occured                                       */
+/*   return a -1 if a breakup occurred                                      */
 /****************************************************************************/
 static inline int
 ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
@@ -1888,9 +1951,9 @@ ips_flash_firmware(ips_ha_t * ha, ips_pa
 	/* FIX stuff that might be wrong */
 	scb->sg_list.list = sg_list.list;
 	scb->scb_busaddr = cmd_busaddr;
-	scb->bus = scb->scsi_cmd->channel;
-	scb->target_id = scb->scsi_cmd->target;
-	scb->lun = scb->scsi_cmd->lun;
+	scb->bus = scb->scsi_cmd->device->channel;
+	scb->target_id = scb->scsi_cmd->device->id;
+	scb->lun = scb->scsi_cmd->device->lun;
 	scb->sg_len = 0;
 	scb->data_len = 0;
 	scb->flags = 0;
@@ -1957,9 +2020,9 @@ ips_usrcmd(ips_ha_t * ha, ips_passthru_t
 	/* FIX stuff that might be wrong */
 	scb->sg_list.list = sg_list.list;
 	scb->scb_busaddr = cmd_busaddr;
-	scb->bus = scb->scsi_cmd->channel;
-	scb->target_id = scb->scsi_cmd->target;
-	scb->lun = scb->scsi_cmd->lun;
+	scb->bus = scb->scsi_cmd->device->channel;
+	scb->target_id = scb->scsi_cmd->device->id;
+	scb->lun = scb->scsi_cmd->device->lun;
 	scb->sg_len = 0;
 	scb->data_len = 0;
 	scb->flags = 0;
@@ -2103,27 +2166,60 @@ ips_host_info(ips_ha_t * ha, char *ptr, 
 
 	copy_info(&info, "\tIRQ number                        : %d\n", ha->irq);
 
-	if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG)
-		copy_info(&info,
-			  "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
-			  ha->nvram->bios_high[0], ha->nvram->bios_high[1],
-			  ha->nvram->bios_high[2], ha->nvram->bios_high[3],
-			  ha->nvram->bios_low[0], ha->nvram->bios_low[1],
-			  ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
-
-	copy_info(&info,
-		  "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
-		  ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
-		  ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
-		  ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
-		  ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
-
-	copy_info(&info,
-		  "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
-		  ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
-		  ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
-		  ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
-		  ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
+    /* For the Next 3 lines Check for Binary 0 at the end and don't include it if it's there. */
+    /* That keeps everything happy for "text" operations on the proc file.                    */
+
+	if (le32_to_cpu(ha->nvram->signature) == IPS_NVRAM_P5_SIG) {
+        if (ha->nvram->bios_low[3] == 0) { 
+            copy_info(&info,
+			          "\tBIOS Version                      : %c%c%c%c%c%c%c\n",
+			          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+			          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+			          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+			          ha->nvram->bios_low[2]);
+
+        } else {
+		    copy_info(&info,
+			          "\tBIOS Version                      : %c%c%c%c%c%c%c%c\n",
+			          ha->nvram->bios_high[0], ha->nvram->bios_high[1],
+			          ha->nvram->bios_high[2], ha->nvram->bios_high[3],
+			          ha->nvram->bios_low[0], ha->nvram->bios_low[1],
+			          ha->nvram->bios_low[2], ha->nvram->bios_low[3]);
+        }
+
+    }
+
+    if (ha->enq->CodeBlkVersion[7] == 0) {
+        copy_info(&info,
+		          "\tFirmware Version                  : %c%c%c%c%c%c%c\n",
+		          ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+		          ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+		          ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+		          ha->enq->CodeBlkVersion[6]);
+    } else {
+        copy_info(&info,
+		          "\tFirmware Version                  : %c%c%c%c%c%c%c%c\n",
+		          ha->enq->CodeBlkVersion[0], ha->enq->CodeBlkVersion[1],
+		          ha->enq->CodeBlkVersion[2], ha->enq->CodeBlkVersion[3],
+		          ha->enq->CodeBlkVersion[4], ha->enq->CodeBlkVersion[5],
+		          ha->enq->CodeBlkVersion[6], ha->enq->CodeBlkVersion[7]);
+    }
+
+    if (ha->enq->BootBlkVersion[7] == 0) {
+        copy_info(&info,
+		          "\tBoot Block Version                : %c%c%c%c%c%c%c\n",
+		          ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+		          ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+		          ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+		          ha->enq->BootBlkVersion[6]);
+    } else {
+        copy_info(&info,
+		          "\tBoot Block Version                : %c%c%c%c%c%c%c%c\n",
+		          ha->enq->BootBlkVersion[0], ha->enq->BootBlkVersion[1],
+		          ha->enq->BootBlkVersion[2], ha->enq->BootBlkVersion[3],
+		          ha->enq->BootBlkVersion[4], ha->enq->BootBlkVersion[5],
+		          ha->enq->BootBlkVersion[6], ha->enq->BootBlkVersion[7]);
+    }
 
 	copy_info(&info, "\tDriver Version                    : %s%s\n",
 		  IPS_VERSION_HIGH, IPS_VERSION_LOW);
@@ -2285,6 +2381,12 @@ ips_identify_controller(ips_ha_t * ha)
 		case IPS_SUBDEVICEID_6I:
 			ha->ad_type = IPS_ADTYPE_SERVERAID6I;
 			break;
+		case IPS_SUBDEVICEID_7k:
+			ha->ad_type = IPS_ADTYPE_SERVERAID7k;
+			break;
+		case IPS_SUBDEVICEID_7M:
+			ha->ad_type = IPS_ADTYPE_SERVERAID7M;
+			break;
 		}
 		break;
 	}
@@ -2310,7 +2412,7 @@ ips_get_bios_version(ips_ha_t * ha, int 
 	uint8_t *buffer;
 	char hexDigits[] =
 	    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
-		    'D', 'E', 'F' };
+     'D', 'E', 'F' };
 
 	METHOD_TRACE("ips_get_bios_version", 1);
 
@@ -2422,9 +2524,10 @@ ips_get_bios_version(ips_ha_t * ha, int 
 		scb->cmd.flashfw.buffer_addr = ha->ioctl_busaddr;
 
 		/* issue the command */
-		if (
-		    ((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) ==
-		     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+		if (((ret =
+		      ips_send_wait(ha, scb, ips_cmd_timeout,
+				    intr)) == IPS_FAILURE)
+		    || (ret == IPS_SUCCESS_IMM)
 		    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
 			/* Error occurred */
 
@@ -2485,17 +2588,15 @@ ips_hainit(ips_ha_t * ha)
 	ips_ffdc_reset(ha, IPS_INTR_IORL);
 
 	if (!ips_read_config(ha, IPS_INTR_IORL)) {
-		printk(KERN_WARNING
-		       "(%s%d) unable to read config from controller.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "unable to read config from controller.\n");
 
 		return (0);
 	}
 	/* end if */
 	if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) {
-		printk(KERN_WARNING
-		       "(%s%d) unable to read controller status.\n", ips_name,
-		       ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "unable to read controller status.\n");
 
 		return (0);
 	}
@@ -2504,18 +2605,16 @@ ips_hainit(ips_ha_t * ha)
 	ips_identify_controller(ha);
 
 	if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) {
-		printk(KERN_WARNING
-		       "(%s%d) unable to read subsystem parameters.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "unable to read subsystem parameters.\n");
 
 		return (0);
 	}
 
 	/* write nvram user page 5 */
 	if (!ips_write_driver_status(ha, IPS_INTR_IORL)) {
-		printk(KERN_WARNING
-		       "(%s%d) unable to write driver info to controller.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "unable to write driver info to controller.\n");
 
 		return (0);
 	}
@@ -2713,8 +2812,10 @@ ips_next(ips_ha_t * ha, int intr)
 
 	p = ha->scb_waitlist.head;
 	while ((p) && (scb = ips_getscb(ha))) {
-		if ((p->channel > 0)
-		    && (ha->dcdb_active[p->channel - 1] & (1 << p->target))) {
+		if ((p->device->channel > 0)
+		    && (ha->
+			dcdb_active[p->device->channel -
+				    1] & (1 << p->device->id))) {
 			ips_freescb(ha, scb);
 			p = (Scsi_Cmnd *) p->host_scribble;
 			continue;
@@ -2731,9 +2832,9 @@ ips_next(ips_ha_t * ha, int intr)
 
 		memset(SC->sense_buffer, 0, sizeof (SC->sense_buffer));
 
-		scb->target_id = SC->target;
-		scb->lun = SC->lun;
-		scb->bus = SC->channel;
+		scb->target_id = SC->device->id;
+		scb->lun = SC->device->lun;
+		scb->bus = SC->device->channel;
 		scb->scsi_cmd = SC;
 		scb->breakup = 0;
 		scb->data_len = 0;
@@ -3301,17 +3402,16 @@ ipsintr_done(ips_ha_t * ha, ips_scb_t * 
 	METHOD_TRACE("ipsintr_done", 2);
 
 	if (!scb) {
-		printk(KERN_WARNING "(%s%d) Spurious interrupt; scb NULL.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Spurious interrupt; scb NULL.\n");
 
 		return;
 	}
 
 	if (scb->scsi_cmd == NULL) {
 		/* unexpected interrupt */
-		printk(KERN_WARNING
-		       "(%s%d) Spurious interrupt; scsi_cmd not set.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Spurious interrupt; scsi_cmd not set.\n");
 
 		return;
 	}
@@ -3465,8 +3565,9 @@ ips_map_status(ips_ha_t * ha, ips_scb_t 
 	if (scb->bus) {
 		DEBUG_VAR(2,
 			  "(%s%d) Physical device error (%d %d %d): %x %x, Sense Key: %x, ASC: %x, ASCQ: %x",
-			  ips_name, ha->host_num, scb->scsi_cmd->channel,
-			  scb->scsi_cmd->target, scb->scsi_cmd->lun,
+			  ips_name, ha->host_num,
+			  scb->scsi_cmd->device->channel,
+			  scb->scsi_cmd->device->id, scb->scsi_cmd->device->lun,
 			  scb->basic_status, scb->extended_status,
 			  scb->extended_status ==
 			  IPS_ERR_CKCOND ? scb->dcdb.sense_info[2] & 0xf : 0,
@@ -3502,7 +3603,8 @@ ips_map_status(ips_ha_t * ha, ips_scb_t 
 
 		case IPS_ERR_OU_RUN:
 			if ((scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB) ||
-			    (scb->cmd.dcdb.op_code == IPS_CMD_EXTENDED_DCDB_SG)) {
+			    (scb->cmd.dcdb.op_code ==
+			     IPS_CMD_EXTENDED_DCDB_SG)) {
 				tapeDCDB = (IPS_DCDB_TABLE_TAPE *) & scb->dcdb;
 				transfer_len = tapeDCDB->transfer_length;
 			} else {
@@ -3516,9 +3618,8 @@ ips_map_status(ips_ha_t * ha, ips_scb_t 
 
 				/* Restrict access to physical DASD */
 				if ((scb->scsi_cmd->cmnd[0] == INQUIRY) &&
-				    ((((char
-					*) scb->scsi_cmd->buffer)[0] & 0x1f) ==
-				     TYPE_DISK)) {
+				    ((((char *) scb->scsi_cmd->
+				       buffer)[0] & 0x1f) == TYPE_DISK)) {
 					/* underflow -- no error               */
 					/* restrict access to physical DASD    */
 					errcode = DID_TIME_OUT;
@@ -3543,8 +3644,7 @@ ips_map_status(ips_ha_t * ha, ips_scb_t 
 
 		case IPS_ERR_CKCOND:
 			if (scb->bus) {
-				if (
-				    (scb->cmd.dcdb.op_code ==
+				if ((scb->cmd.dcdb.op_code ==
 				     IPS_CMD_EXTENDED_DCDB)
 				    || (scb->cmd.dcdb.op_code ==
 					IPS_CMD_EXTENDED_DCDB_SG)) {
@@ -3822,13 +3922,10 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * 
 							    sector_count));
 			else
 				scb->cmd.basic_io.lba =
-				    (((scb->
-				       scsi_cmd->cmnd[1] & 0x1f) << 16) | (scb->
-									   scsi_cmd->
-									   cmnd
-									   [2]
-									   << 8)
-				     | (scb->scsi_cmd->cmnd[3]));
+				    (((scb->scsi_cmd->
+				       cmnd[1] & 0x1f) << 16) | (scb->scsi_cmd->
+								 cmnd[2] << 8) |
+				     (scb->scsi_cmd->cmnd[3]));
 
 			scb->cmd.basic_io.sector_count =
 			    cpu_to_le16(scb->data_len / IPS_BLKSIZE);
@@ -3873,11 +3970,11 @@ ips_send_cmd(ips_ha_t * ha, ips_scb_t * 
 							    sector_count));
 			else
 				scb->cmd.basic_io.lba =
-				    ((scb->
-				      scsi_cmd->cmnd[2] << 24) | (scb->
-								  scsi_cmd->
-								  cmnd[3] << 16)
-				     | (scb->scsi_cmd->cmnd[4] << 8) | scb->
+				    ((scb->scsi_cmd->cmnd[2] << 24) | (scb->
+								       scsi_cmd->
+								       cmnd[3]
+								       << 16) |
+				     (scb->scsi_cmd->cmnd[4] << 8) | scb->
 				     scsi_cmd->cmnd[5]);
 
 			scb->cmd.basic_io.sector_count =
@@ -4253,7 +4350,8 @@ ips_online(ips_ha_t * ha, ips_scb_t * sc
 	    && ha->logical_drive_info->drive_info[scb->target_id].state !=
 	    IPS_LD_CRS
 	    && ha->logical_drive_info->drive_info[scb->target_id].state !=
-	    IPS_LD_SYS) return (1);
+	    IPS_LD_SYS)
+		return (1);
 	else
 		return (0);
 }
@@ -4397,6 +4495,13 @@ ips_msense(ips_ha_t * ha, ips_scb_t * sc
 		mdata.pdata.pg4.RotationalOffset = 0;
 		mdata.pdata.pg4.MediumRotationRate = 0;
 		break;
+	case 0x8:
+		mdata.pdata.pg8.PageCode = 8;
+		mdata.pdata.pg8.PageLength = sizeof (IPS_SCSI_MODE_PAGE8);
+		mdata.hdr.DataLength =
+		    3 + mdata.hdr.BlockDescLength + mdata.pdata.pg8.PageLength;
+		/* everything else is left set to 0 */
+		break;
 
 	default:
 		return (0);
@@ -4469,9 +4574,9 @@ ips_free(ips_ha_t * ha)
 					    sizeof (IPS_IO_CMD), ha->adapt,
 					    ha->adapt->hw_status_start);
 			ha->adapt = NULL;
-		}  	
-        	
-        if (ha->logical_drive_info) {
+		}
+
+		if (ha->logical_drive_info) {
 			pci_free_consistent(ha->pcidev,
 					    sizeof (IPS_LD_INFO),
                         ha->logical_drive_info,
@@ -4800,7 +4905,7 @@ ips_enable_int_copperhead(ips_ha_t * ha)
 	METHOD_TRACE("ips_enable_int_copperhead", 1);
 
 	outb(ha->io_addr + IPS_REG_HISR, IPS_BIT_EI);
-	inb(ha->io_addr + IPS_REG_HISR);	// Ensure PCI Posting Completes
+	inb(ha->io_addr + IPS_REG_HISR);	/*Ensure PCI Posting Completes*/
 }
 
 /****************************************************************************/
@@ -4817,7 +4922,7 @@ ips_enable_int_copperhead_memio(ips_ha_t
 	METHOD_TRACE("ips_enable_int_copperhead_memio", 1);
 
 	writeb(IPS_BIT_EI, ha->mem_ptr + IPS_REG_HISR);
-	readb(ha->mem_ptr + IPS_REG_HISR);	// Ensure PCI Posting Completes
+	readb(ha->mem_ptr + IPS_REG_HISR);	/*Ensure PCI Posting Completes*/
 }
 
 /****************************************************************************/
@@ -4838,7 +4943,7 @@ ips_enable_int_morpheus(ips_ha_t * ha)
 	Oimr = readl(ha->mem_ptr + IPS_REG_I960_OIMR);
 	Oimr &= ~0x08;
 	writel(Oimr, ha->mem_ptr + IPS_REG_I960_OIMR);
-	readl(ha->mem_ptr + IPS_REG_I960_OIMR);	// Ensure PCI Posting Completes
+	readl(ha->mem_ptr + IPS_REG_I960_OIMR);	/*Ensure PCI Posting Completes*/
 }
 
 /****************************************************************************/
@@ -4880,9 +4985,9 @@ ips_init_copperhead(ips_ha_t * ha)
 	}
 
 	if (PostByte[0] < IPS_GOOD_POST_STATUS) {
-		printk(KERN_WARNING
-		       "(%s%d) reset controller fails (post status %x %x).\n",
-		       ips_name, ha->host_num, PostByte[0], PostByte[1]);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "reset controller fails (post status %x %x).\n",
+			   PostByte[0], PostByte[1]);
 
 		return (0);
 	}
@@ -4974,9 +5079,9 @@ ips_init_copperhead_memio(ips_ha_t * ha)
 	}
 
 	if (PostByte[0] < IPS_GOOD_POST_STATUS) {
-		printk(KERN_WARNING
-		       "(%s%d) reset controller fails (post status %x %x).\n",
-		       ips_name, ha->host_num, PostByte[0], PostByte[1]);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "reset controller fails (post status %x %x).\n",
+			   PostByte[0], PostByte[1]);
 
 		return (0);
 	}
@@ -5063,8 +5168,8 @@ ips_init_morpheus(ips_ha_t * ha)
 
 	if (i >= 45) {
 		/* error occurred */
-		printk(KERN_WARNING "(%s%d) timeout waiting for post.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "timeout waiting for post.\n");
 
 		return (0);
 	}
@@ -5072,7 +5177,8 @@ ips_init_morpheus(ips_ha_t * ha)
 	Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0);
 
 	if (Post == 0x4F00) {	/* If Flashing the Battery PIC         */
-		printk(KERN_WARNING "Flashing Battery PIC, Please wait ...\n");
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Flashing Battery PIC, Please wait ...\n");
 
 		/* Clear the interrupt bit */
 		Isr = (uint32_t) IPS_BIT_I960_MSG0I;
@@ -5087,9 +5193,8 @@ ips_init_morpheus(ips_ha_t * ha)
 		}
 
 		if (i >= 120) {
-			printk(KERN_WARNING
-			       "(%s%d) timeout waiting for Battery PIC Flash\n",
-			       ips_name, ha->host_num);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "timeout waiting for Battery PIC Flash\n");
 			return (0);
 		}
 
@@ -5100,9 +5205,8 @@ ips_init_morpheus(ips_ha_t * ha)
 	writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR);
 
 	if (Post < (IPS_GOOD_POST_STATUS << 8)) {
-		printk(KERN_WARNING
-		       "(%s%d) reset controller fails (post status %x).\n",
-		       ips_name, ha->host_num, Post);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "reset controller fails (post status %x).\n", Post);
 
 		return (0);
 	}
@@ -5120,8 +5224,8 @@ ips_init_morpheus(ips_ha_t * ha)
 
 	if (i >= 240) {
 		/* error occurred */
-		printk(KERN_WARNING "(%s%d) timeout waiting for config.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "timeout waiting for config.\n");
 
 		return (0);
 	}
@@ -5450,19 +5554,18 @@ ips_issue_copperhead(ips_ha_t * ha, ips_
 
 	TimeOut = 0;
 
-	while ((val = le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) &
-	       IPS_BIT_SEM) {
+	while ((val =
+		le32_to_cpu(inl(ha->io_addr + IPS_REG_CCCR))) & IPS_BIT_SEM) {
 		udelay(1000);
 
 		if (++TimeOut >= IPS_SEM_TIMEOUT) {
 			if (!(val & IPS_BIT_START_STOP))
 				break;
 
-			printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
-			       ips_name, ha->host_num, val);
-			printk(KERN_WARNING
-			       "(%s%d) ips_issue semaphore chk timeout.\n",
-			       ips_name, ha->host_num);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "ips_issue val [0x%x].\n", val);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "ips_issue semaphore chk timeout.\n");
 
 			return (IPS_FAILURE);
 		}		/* end if */
@@ -5512,11 +5615,10 @@ ips_issue_copperhead_memio(ips_ha_t * ha
 			if (!(val & IPS_BIT_START_STOP))
 				break;
 
-			printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n",
-			       ips_name, ha->host_num, val);
-			printk(KERN_WARNING
-			       "(%s%d) ips_issue semaphore chk timeout.\n",
-			       ips_name, ha->host_num);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "ips_issue val [0x%x].\n", val);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "ips_issue semaphore chk timeout.\n");
 
 			return (IPS_FAILURE);
 		}		/* end if */
@@ -5755,8 +5857,8 @@ ips_write_driver_status(ips_ha_t * ha, i
 	METHOD_TRACE("ips_write_driver_status", 1);
 
 	if (!ips_readwrite_page5(ha, FALSE, intr)) {
-		printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "unable to read NVRAM page 5.\n");
 
 		return (0);
 	}
@@ -5793,8 +5895,8 @@ ips_write_driver_status(ips_ha_t * ha, i
 
 	/* now update the page */
 	if (!ips_readwrite_page5(ha, TRUE, intr)) {
-		printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n",
-		       ips_name, ha->host_num);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "unable to write NVRAM page 5.\n");
 
 		return (0);
 	}
@@ -5839,9 +5941,9 @@ ips_read_adapter_status(ips_ha_t * ha, i
 	scb->cmd.basic_io.sg_addr = ha->enq_busaddr;
 
 	/* send command */
-	if (
-	    ((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) ==
-	     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+	if (((ret =
+	      ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
+	    || (ret == IPS_SUCCESS_IMM)
 	    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
 		return (0);
 
@@ -5882,9 +5984,9 @@ ips_read_subsystem_parameters(ips_ha_t *
 	scb->cmd.basic_io.sg_addr = ha->ioctl_busaddr;
 
 	/* send command */
-	if (
-	    ((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) ==
-	     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+	if (((ret =
+	      ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
+	    || (ret == IPS_SUCCESS_IMM)
 	    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
 		return (0);
 
@@ -5927,9 +6029,9 @@ ips_read_config(ips_ha_t * ha, int intr)
 	scb->cmd.basic_io.sg_addr = ha->ioctl_busaddr;
 
 	/* send command */
-	if (
-	    ((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) ==
-	     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+	if (((ret =
+	      ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
+	    || (ret == IPS_SUCCESS_IMM)
 	    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
 
 		memset(ha->conf, 0, sizeof (IPS_CONF));
@@ -5940,7 +6042,8 @@ ips_read_config(ips_ha_t * ha, int intr)
 
 		/* Allow Completed with Errors, so JCRM can access the Adapter to fix the problems */
 		if ((scb->basic_status & IPS_GSC_STATUS_MASK) ==
-		    IPS_CMD_CMPLT_WERROR) return (1);
+		    IPS_CMD_CMPLT_WERROR)
+			return (1);
 
 		return (0);
 	}
@@ -5985,9 +6088,9 @@ ips_readwrite_page5(ips_ha_t * ha, int w
 		memcpy(ha->ioctl_data, ha->nvram, sizeof(*ha->nvram));
 	
 	/* issue the command */
-	if (
-	    ((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) ==
-	     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+	if (((ret =
+	      ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
+	    || (ret == IPS_SUCCESS_IMM)
 	    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1)) {
 
 		memset(ha->nvram, 0, sizeof (IPS_NVRAM_P5));
@@ -6032,9 +6135,9 @@ ips_clear_adapter(ips_ha_t * ha, int int
 	scb->cmd.config_sync.reserved3 = 0;
 
 	/* issue command */
-	if (
-	    ((ret = ips_send_wait(ha, scb, ips_reset_timeout, intr)) ==
-	     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+	if (((ret =
+	      ips_send_wait(ha, scb, ips_reset_timeout, intr)) == IPS_FAILURE)
+	    || (ret == IPS_SUCCESS_IMM)
 	    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
 		return (0);
 
@@ -6053,9 +6156,9 @@ ips_clear_adapter(ips_ha_t * ha, int int
 	scb->cmd.unlock_stripe.reserved3 = 0;
 
 	/* issue command */
-	if (
-	    ((ret = ips_send_wait(ha, scb, ips_cmd_timeout, intr)) ==
-	     IPS_FAILURE) || (ret == IPS_SUCCESS_IMM)
+	if (((ret =
+	      ips_send_wait(ha, scb, ips_cmd_timeout, intr)) == IPS_FAILURE)
+	    || (ret == IPS_SUCCESS_IMM)
 	    || ((scb->basic_status & IPS_GSC_STATUS_MASK) > 1))
 		return (0);
 
@@ -6722,7 +6825,7 @@ ips_version_check(ips_ha_t * ha, int int
 	uint8_t FirmwareVersion[IPS_COMPAT_ID_LENGTH + 1];
 	uint8_t BiosVersion[IPS_COMPAT_ID_LENGTH + 1];
 	int MatchError;
-	int  rc;
+	int rc;
 	char BiosString[10];
 	char FirmwareString[10];
 
@@ -6739,8 +6842,8 @@ ips_version_check(ips_ha_t * ha, int int
 
 	rc = IPS_FAILURE;
 	if (ha->subsys->param[4] & IPS_GET_VERSION_SUPPORT) {	/* If Versioning is Supported */
-        memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
 		/* Get the Version Info with a Get Version Command */
+        memset( VersionInfo, 0, sizeof (IPS_VERSION_DATA));
 		rc = ips_get_version_info(ha, ha->ioctl_busaddr, intr);
 		if (rc == IPS_SUCCESS)
 			memcpy(FirmwareVersion, VersionInfo->compatibilityId,
@@ -6780,14 +6883,14 @@ ips_version_check(ips_ha_t * ha, int int
 			strncpy(&FirmwareString[0], ha->enq->CodeBlkVersion, 8);
 			FirmwareString[8] = 0;
 
-			printk(KERN_WARNING
-			       "Warning ! ! ! ServeRAID Version Mismatch\n");
-			printk(KERN_WARNING
-			       "Bios = %s, Firmware = %s, Device Driver = %s%s\n",
-			       BiosString, FirmwareString, IPS_VERSION_HIGH,
-			       IPS_VERSION_LOW);
-			printk(KERN_WARNING
-			       "These levels should match to avoid possible compatibility problems.\n");
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "Warning ! ! ! ServeRAID Version Mismatch\n");
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "Bios = %s, Firmware = %s, Device Driver = %s%s\n",
+				   BiosString, FirmwareString, IPS_VERSION_HIGH,
+				   IPS_VERSION_LOW);
+			IPS_PRINTK(KERN_WARNING, ha->pcidev,
+				   "These levels should match to avoid possible compatibility problems.\n");
 		}
 	} else {
 		ha->nvram->version_mismatch = 0;
@@ -6825,7 +6928,7 @@ ips_get_version_info(ips_ha_t * ha, dma_
 	scb->cmd.version_info.count = sizeof (IPS_VERSION_DATA);
 	scb->cmd.version_info.reserved2 = 0;
 	scb->data_len = sizeof (IPS_VERSION_DATA);
-    scb->data_busaddr = Buffer;
+	scb->data_busaddr = Buffer;
 	scb->cmd.version_info.buffer_addr = Buffer;
 	scb->flags = 0;
 
@@ -6896,6 +6999,8 @@ ips_order_controllers(void)
 			for (j = position; j < ips_num_controllers; j++) {
 				switch (ips_ha[j]->ad_type) {
 				case IPS_ADTYPE_SERVERAID6M:
+				case IPS_ADTYPE_SERVERAID7k:
+				case IPS_ADTYPE_SERVERAID7M:
 					if (nvram->adapter_order[i] == 'M') {
 						ips_shift_controllers(position,
 								      j);
@@ -6979,28 +7084,28 @@ static int
 ips_register_scsi(int index)
 {
 	struct Scsi_Host *sh;
-	ips_ha_t *ha, *oldha;
-	sh = scsi_register(&ips_driver_template, sizeof (ips_ha_t));
+	ips_ha_t *ha, *oldha = ips_ha[index];
+	sh = scsi_host_alloc(&ips_driver_template, sizeof (ips_ha_t));
 	if (!sh) {
-		printk(KERN_WARNING
-		       "Unable to register controller with SCSI subsystem\n");
+		IPS_PRINTK(KERN_WARNING, oldha->pcidev,
+			   "Unable to register controller with SCSI subsystem\n");
 		return -1;
 	}
-	oldha = ips_ha[index];
 	ha = IPS_HA(sh);
 	memcpy(ha, oldha, sizeof (ips_ha_t));
 	free_irq(oldha->irq, oldha);
 	/* Install the interrupt handler with the new ha */
 	if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
-		printk(KERN_WARNING "Unable to install interrupt handler\n");
-		scsi_unregister(sh);
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Unable to install interrupt handler\n");
+		scsi_host_put(sh);
 		return -1;
 	}
 
 	kfree(oldha);
 	ips_sh[index] = sh;
 	ips_ha[index] = ha;
-	scsi_set_pci_device(sh, ha->pcidev);
+	IPS_SCSI_SET_DEVICE(sh, ha);
 
 	/* Store away needed values for later use */
 	sh->io_port = ha->io_addr;
@@ -7013,7 +7118,7 @@ ips_register_scsi(int index)
 	sh->unchecked_isa_dma = sh->hostt->unchecked_isa_dma;
 	sh->use_clustering = sh->hostt->use_clustering;
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
 	sh->max_sectors = 128;
 #endif
 
@@ -7022,6 +7127,7 @@ ips_register_scsi(int index)
 	sh->max_channel = ha->nbus - 1;
 	sh->can_queue = ha->max_cmds - 1;
 
+	IPS_ADD_HOST(sh, NULL);
 	return 0;
 }
 
@@ -7031,7 +7137,7 @@ ips_register_scsi(int index)
 /*   Routine Description:                                                    */
 /*     Remove one Adapter ( Hot Plugging )                                   */
 /*---------------------------------------------------------------------------*/
-static void
+static void __devexit
 ips_remove_device(struct pci_dev *pci_dev)
 {
 	int i;
@@ -7064,7 +7170,7 @@ ips_module_init(void)
 		return -ENODEV;
 	ips_driver_template.module = THIS_MODULE;
 	ips_order_controllers();
-	if (scsi_register_module(MODULE_SCSI_HA, &ips_driver_template)) {
+	if (IPS_REGISTER_HOSTS(&ips_driver_template)) {
 		pci_unregister_driver(&ips_pci_driver);
 		return -ENODEV;
 	}
@@ -7082,7 +7188,7 @@ ips_module_init(void)
 static void __exit
 ips_module_exit(void)
 {
-	scsi_unregister_module(MODULE_SCSI_HA, &ips_driver_template);
+	IPS_UNREGISTER_HOSTS(&ips_driver_template);
 	pci_unregister_driver(&ips_pci_driver);
 	unregister_reboot_notifier(&ips_notifier);
 }
@@ -7106,7 +7212,6 @@ ips_insert_device(struct pci_dev *pci_de
 	int rc;
 
 	METHOD_TRACE("ips_insert_device", 1);
-
 	if (pci_enable_device(pci_dev))
 		return -1;
 
@@ -7114,6 +7219,12 @@ ips_insert_device(struct pci_dev *pci_de
 	if (rc == SUCCESS)
 		rc = ips_init_phase2(index);
 
+	if (ips_hotplug)
+		if (ips_register_scsi(index)) {
+			ips_free(ips_ha[index]);
+			rc = -1;
+		}
+
 	if (rc == SUCCESS)
 		ips_num_controllers++;
 
@@ -7192,9 +7303,9 @@ ips_init_phase1(struct pci_dev *pci_dev,
 		uint32_t offs;
 
 		if (!request_mem_region(mem_addr, mem_len, "ips")) {
-			printk(KERN_WARNING
-			       "Couldn't allocate IO Memory space %x len %d.\n",
-			       mem_addr, mem_len);
+			IPS_PRINTK(KERN_WARNING, pci_dev,
+				   "Couldn't allocate IO Memory space %x len %d.\n",
+				   mem_addr, mem_len);
 			return -1;
 		}
 
@@ -7210,16 +7321,16 @@ ips_init_phase1(struct pci_dev *pci_dev,
 	/* setup I/O mapped area (if applicable) */
 	if (io_addr) {
 		if (!request_region(io_addr, io_len, "ips")) {
-			printk(KERN_WARNING
-			       "Couldn't allocate IO space %x len %d.\n",
-			       io_addr, io_len);
+			IPS_PRINTK(KERN_WARNING, pci_dev,
+				   "Couldn't allocate IO space %x len %d.\n",
+				   io_addr, io_len);
 			return -1;
 		}
 	}
 
 	/* get the revision ID */
 	if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) {
-		printk(KERN_WARNING "Can't get revision id.\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n");
 		return -1;
 	}
 
@@ -7228,7 +7339,8 @@ ips_init_phase1(struct pci_dev *pci_dev,
 	/* found a controller */
 	ha = kmalloc(sizeof (ips_ha_t), GFP_KERNEL);
 	if (ha == NULL) {
-		printk(KERN_WARNING "Unable to allocate temporary ha struct\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate temporary ha struct\n");
 		return -1;
 	}
 
@@ -7272,54 +7384,57 @@ ips_init_phase1(struct pci_dev *pci_dev,
 		ips_FlashData = pci_alloc_consistent(pci_dev, PAGE_SIZE << 7,
 						     &ips_flashbusaddr);
 	}
-	
+
 	ha->enq = pci_alloc_consistent(pci_dev, sizeof (IPS_ENQ),
 				       &ha->enq_busaddr);
 	if (!ha->enq) {
-		printk(KERN_WARNING
-		       "Unable to allocate host inquiry structure\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate host inquiry structure\n");
 		return ips_abort_init(ha, index);
 	}
 
 	ha->adapt = pci_alloc_consistent(pci_dev, sizeof (IPS_ADAPTER) +
 					 sizeof (IPS_IO_CMD), &dma_address);
 	if (!ha->adapt) {
-		printk(KERN_WARNING
-		       "Unable to allocate host adapt & dummy structures\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate host adapt & dummy structures\n");
 		return ips_abort_init(ha, index);
 	}
 	ha->adapt->hw_status_start = dma_address;
 	ha->dummy = (void *) (ha->adapt + 1);
-    
-	ha->logical_drive_info = pci_alloc_consistent(pci_dev, sizeof (IPS_LD_INFO),
-                                                  &dma_address);
+
+
+
+	ha->logical_drive_info = pci_alloc_consistent(pci_dev, sizeof (IPS_LD_INFO), &dma_address);
 	if (!ha->logical_drive_info) {
-		printk(KERN_WARNING
-		       "Unable to allocate host logical drive info structure\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate logical drive info structure\n");
 		return ips_abort_init(ha, index);
 	}
 	ha->logical_drive_info_dma_addr = dma_address;
-    
+
+
 	ha->conf = kmalloc(sizeof (IPS_CONF), GFP_KERNEL);
 
 	if (!ha->conf) {
-		printk(KERN_WARNING "Unable to allocate host conf structure\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate host conf structure\n");
 		return ips_abort_init(ha, index);
 	}
 
 	ha->nvram = kmalloc(sizeof (IPS_NVRAM_P5), GFP_KERNEL);
 
 	if (!ha->nvram) {
-		printk(KERN_WARNING
-		       "Unable to allocate host NVRAM structure\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate host NVRAM structure\n");
 		return ips_abort_init(ha, index);
 	}
 
 	ha->subsys = kmalloc(sizeof (IPS_SUBSYS), GFP_KERNEL);
 
 	if (!ha->subsys) {
-		printk(KERN_WARNING
-		       "Unable to allocate host subsystem structure\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate host subsystem structure\n");
 		return ips_abort_init(ha, index);
 	}
 
@@ -7327,13 +7442,13 @@ ips_init_phase1(struct pci_dev *pci_dev,
 	 * successful allocation is now required */
 	if (ips_ioctlsize < PAGE_SIZE)
 		ips_ioctlsize = PAGE_SIZE;
-	
+
 	ha->ioctl_data = pci_alloc_consistent(pci_dev, ips_ioctlsize,
 					      &ha->ioctl_busaddr);
 	ha->ioctl_len = ips_ioctlsize;
-
 	if (!ha->ioctl_data) {
-		printk(KERN_WARNING "Unable to allocate IOCTL data\n");
+		IPS_PRINTK(KERN_WARNING, pci_dev,
+			   "Unable to allocate IOCTL data\n");
 		return ips_abort_init(ha, index);
 	}
 
@@ -7359,8 +7474,8 @@ ips_init_phase1(struct pci_dev *pci_dev,
 			/*
 			 * Initialization failed
 			 */
-			printk(KERN_WARNING
-			       "Unable to initialize controller\n");
+			IPS_PRINTK(KERN_WARNING, pci_dev,
+				   "Unable to initialize controller\n");
 			return ips_abort_init(ha, index);
 		}
 	}
@@ -7393,7 +7508,8 @@ ips_init_phase2(int index)
 
 	/* Install the interrupt handler */
 	if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) {
-		printk(KERN_WARNING "Unable to install interrupt handler\n");
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Unable to install interrupt handler\n");
 		return ips_abort_init(ha, index);
 	}
 
@@ -7402,13 +7518,15 @@ ips_init_phase2(int index)
 	 */
 	ha->max_cmds = 1;
 	if (!ips_allocatescbs(ha)) {
-		printk(KERN_WARNING "Unable to allocate a CCB\n");
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Unable to allocate a CCB\n");
 		free_irq(ha->irq, ha);
 		return ips_abort_init(ha, index);
 	}
 
 	if (!ips_hainit(ha)) {
-		printk(KERN_WARNING "Unable to initialize controller\n");
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Unable to initialize controller\n");
 		free_irq(ha->irq, ha);
 		return ips_abort_init(ha, index);
 	}
@@ -7417,7 +7535,8 @@ ips_init_phase2(int index)
 
 	/* allocate CCBs */
 	if (!ips_allocatescbs(ha)) {
-		printk(KERN_WARNING "Unable to allocate CCBs\n");
+		IPS_PRINTK(KERN_WARNING, ha->pcidev,
+			   "Unable to allocate CCBs\n");
 		free_irq(ha->irq, ha);
 		return ips_abort_init(ha, index);
 	}
@@ -7425,7 +7544,7 @@ ips_init_phase2(int index)
 	return SUCCESS;
 }
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,9)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
 MODULE_LICENSE("GPL");
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/ips.h linux-2.4.27-rc4/drivers/scsi/ips.h
--- linux-2.4.26/drivers/scsi/ips.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/ips.h	2004-07-30 16:26:38.000000000 +0000
@@ -59,21 +59,13 @@
    extern int ips_eh_abort(Scsi_Cmnd *);
    extern int ips_eh_reset(Scsi_Cmnd *);
    extern int ips_queue(Scsi_Cmnd *, void (*) (Scsi_Cmnd *));
-   extern int ips_biosparam(Disk *, kdev_t, int *);
    extern const char * ips_info(struct Scsi_Host *);
 
    /*
     * Some handy macros
     */
-   #ifndef LinuxVersionCode
-      #define LinuxVersionCode(x,y,z)  (((x)<<16)+((y)<<8)+(z))
-   #endif
-
-   #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,20) || defined CONFIG_HIGHIO
+   #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO
       #define IPS_HIGHIO
-      #define IPS_HIGHMEM_IO     .highmem_io = 1,
-   #else
-      #define IPS_HIGHMEM_IO
    #endif
 
    #define IPS_HA(x)                   ((ips_ha_t *) x->hostdata)
@@ -98,11 +90,39 @@
     #define IPS_SGLIST_SIZE(ha)       (IPS_USE_ENH_SGLIST(ha) ? \
                                          sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST))
 
-   #if LINUX_VERSION_CODE < LinuxVersionCode(2,4,4)
+   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
       #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 )
       #define scsi_set_pci_device(sh,dev) (0)
    #endif
 
+   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
+      typedef void irqreturn_t;
+      #define IRQ_NONE
+      #define IRQ_HANDLED
+      #define IRQ_RETVAL(x)
+   #endif
+
+   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+      #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
+      #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
+      #define IPS_ADD_HOST(shost,device)
+      #define IPS_REMOVE_HOST(shost)
+      #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_pci_device(sh, (ha)->pcidev)
+      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
+            printk(level "%s %s:" format , "ips" ,     \
+            (pcidev)->slot_name , ## arg)
+      #define scsi_host_alloc(sh,size)         scsi_register(sh,size)
+      #define scsi_host_put(sh)             scsi_unregister(sh)
+   #else
+      #define IPS_REGISTER_HOSTS(SHT)      (!ips_detect(SHT))
+      #define IPS_UNREGISTER_HOSTS(SHT)
+      #define IPS_ADD_HOST(shost,device)   do { scsi_add_host(shost,device); scsi_scan_host(shost); } while (0)
+      #define IPS_REMOVE_HOST(shost)       scsi_remove_host(shost)
+      #define IPS_SCSI_SET_DEVICE(sh,ha)   scsi_set_device(sh, &(ha)->pcidev->dev)
+      #define IPS_PRINTK(level, pcidev, format, arg...)                 \
+            dev_printk(level , &((pcidev)->dev) , format , ## arg)
+   #endif
+
    #ifndef MDELAY
       #define MDELAY mdelay
    #endif
@@ -229,6 +249,8 @@
    #define IPS_SUBDEVICEID_5I1          0x0258
    #define IPS_SUBDEVICEID_6M           0x0279
    #define IPS_SUBDEVICEID_6I           0x028C
+   #define IPS_SUBDEVICEID_7k           0x028E
+   #define IPS_SUBDEVICEID_7M           0x028F
    #define IPS_IOCTL_SIZE               8192
    #define IPS_STATUS_SIZE              4
    #define IPS_STATUS_Q_SIZE            (IPS_MAX_CMDS+1) * IPS_STATUS_SIZE
@@ -313,6 +335,9 @@
    #define IPS_ADTYPE_SERVERAID5I1      0x0D
    #define IPS_ADTYPE_SERVERAID6M       0x0E
    #define IPS_ADTYPE_SERVERAID6I       0x0F
+   #define IPS_ADTYPE_SERVERAID7t       0x10
+   #define IPS_ADTYPE_SERVERAID7k       0x11
+   #define IPS_ADTYPE_SERVERAID7M       0x12
 
    /*
     * Adapter Command/Status Packet Definitions
@@ -426,46 +451,15 @@
    /*
     * Scsi_Host Template
     */
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+   static int ips_proc24_info(char *, char **, off_t, int, int, int);
    static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *);
-#define IPS {	\
-	.detect				= ips_detect,	\
-	.release			= ips_release,	\
-	.info				= ips_info,	\
-	.queuecommand			= ips_queue,	\
-	.eh_abort_handler		= ips_eh_abort,	\
-	.eh_host_reset_handler		= ips_eh_reset,	\
-	.bios_param			= ips_biosparam,\
-	.select_queue_depths		= ips_select_queue_depth, \
-	.can_queue			= 0,		\
-	.this_id			= -1,		\
-	.sg_tablesize			= IPS_MAX_SG,	\
-	.cmd_per_lun			= 16,		\
-	.present			= 0,		\
-	.unchecked_isa_dma		= 0,		\
-	.use_clustering			= ENABLE_CLUSTERING,\
-	.use_new_eh_code		= 1, \
-	IPS_HIGHMEM_IO \
-}
+   static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]);
 #else
-#define IPS {	\
-	.detect			= ips_detect,		\
-	.release		= ips_release,		\
-	.info			= ips_info,		\
-	.queuecommand		= ips_queue,		\
-	.eh_abort_handler	= ips_eh_abort,		\
-	.eh_host_reset_handler	= ips_eh_reset,		\
-	.slave_configure	= ips_slave_configure,	\
-	.bios_param		= ips_biosparam,	\
-	.can_queue		= 0,			\
-	.this_id		= -1,			\
-	.sg_tablesize		= IPS_MAX_SG,		\
-	.cmd_per_lun		= 3,			\
-	.present		= 0,			\
-	.unchecked_isa_dma	= 0,			\
-	.use_clustering		= ENABLE_CLUSTERING,	\
-	.highmem_io		= 1 \
-}
+   int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);
+   static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev,
+		sector_t capacity, int geom[]);
+   int ips_slave_configure(Scsi_Device *SDptr);
 #endif
 
 /*
@@ -941,6 +935,20 @@ typedef struct {
 } IPS_SCSI_MODE_PAGE4;
 
 /*
+ * Sense Data Format - Page 8
+ */
+typedef struct {
+   uint8_t  PageCode;
+   uint8_t  PageLength;
+   uint8_t  flags;
+   uint8_t  RetentPrio;
+   uint16_t DisPrefetchLen;
+   uint16_t MinPrefetchLen;
+   uint16_t MaxPrefetchLen;
+   uint16_t MaxPrefetchCeiling;
+} IPS_SCSI_MODE_PAGE8;
+
+/*
  * Sense Data Format - Block Descriptor (DASD)
  */
 typedef struct {
@@ -967,6 +975,7 @@ typedef struct {
    union {
       IPS_SCSI_MODE_PAGE3 pg3;
       IPS_SCSI_MODE_PAGE4 pg4;
+      IPS_SCSI_MODE_PAGE8 pg8;
    } pdata;
 } IPS_SCSI_MODE_PAGE_DATA;
 
@@ -1056,7 +1065,7 @@ typedef struct {
    int       (*programbios)(struct ips_ha *, char *, uint32_t, uint32_t);
    int       (*verifybios)(struct ips_ha *, char *, uint32_t, uint32_t);
    void      (*statinit)(struct ips_ha *);
-   void      (*intr)(struct ips_ha *);
+   int       (*intr)(struct ips_ha *);
    void      (*enableint)(struct ips_ha *);
    uint32_t (*statupd)(struct ips_ha *);
 } ips_hw_func_t;
@@ -1082,7 +1091,7 @@ typedef struct ips_ha {
    ips_scb_queue_t    scb_activelist;     /* Active SCB list            */
    IPS_IO_CMD        *dummy;              /* dummy command              */
    IPS_ADAPTER       *adapt;              /* Adapter status area        */
-   IPS_LD_INFO       *logical_drive_info; /* Logical Drive Info         */
+   IPS_LD_INFO       *logical_drive_info; /* Adapter Logical Drive Info */
    dma_addr_t         logical_drive_info_dma_addr; /* Logical Drive Info DMA Address */
    IPS_ENQ           *enq;                /* Adapter Enquiry data       */
    IPS_CONF          *conf;               /* Adapter config data        */
@@ -1131,8 +1140,8 @@ typedef struct ips_scb {
    uint8_t           bus;
    uint8_t           lun;
    uint8_t           cdb[12];
-   uint32_t          scb_busaddr;      
-   uint32_t          old_data_busaddr;         // Obsolete field left in to not break utilities
+   uint32_t          scb_busaddr;
+   uint32_t          old_data_busaddr;  // Obsolete, but kept for old utility compatibility
    uint32_t          timeout;
    uint8_t           basic_status;
    uint8_t           extended_status;
@@ -1202,29 +1211,30 @@ typedef struct {
 *
 *************************************************************************/
 
-#define IPS_VER_MAJOR 6
-#define IPS_VER_MAJOR_STRING "6"
-#define IPS_VER_MINOR 11
-#define IPS_VER_MINOR_STRING "11"
-#define IPS_VER_BUILD 07
-#define IPS_VER_BUILD_STRING "07"
-#define IPS_VER_STRING "6.11.07"
-#define IPS_RELEASE_ID 0x00010001
-#define IPS_BUILD_IDENT 2224
-#define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2003. All Rights Reserved."
-#define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to present. All Rights Reserved."
-#define IPS_NT_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2003."
+#define IPS_VER_MAJOR 7
+#define IPS_VER_MAJOR_STRING "7"
+#define IPS_VER_MINOR 00
+#define IPS_VER_MINOR_STRING "00"
+#define IPS_VER_BUILD 15
+#define IPS_VER_BUILD_STRING "15"
+#define IPS_VER_STRING "7.00.15"
+#define IPS_RELEASE_ID 0x00020000
+#define IPS_BUILD_IDENT 625
+#define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved."
+#define IPS_ADAPTECCOPYRIGHT_STRING "(c) Copyright Adaptec, Inc. 2002 to 2004. All Rights Reserved."
+#define IPS_DELLCOPYRIGHT_STRING "(c) Copyright Dell 2004. All Rights Reserved."
+#define IPS_NT_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002."
 
 /* Version numbers for various adapters */
 #define IPS_VER_SERVERAID1 "2.25.01"
 #define IPS_VER_SERVERAID2 "2.88.13"
 #define IPS_VER_NAVAJO "2.88.13"
 #define IPS_VER_SERVERAID3 "6.10.24"
-#define IPS_VER_SERVERAID4H "6.11.07"
-#define IPS_VER_SERVERAID4MLx "6.11.07"
-#define IPS_VER_SARASOTA "6.11.07"
-#define IPS_VER_MARCO "6.11.07"
-#define IPS_VER_SEBRING "6.11.07"
+#define IPS_VER_SERVERAID4H "7.00.15"
+#define IPS_VER_SERVERAID4MLx "7.00.15"
+#define IPS_VER_SARASOTA "7.00.15"
+#define IPS_VER_MARCO "7.00.15"
+#define IPS_VER_SEBRING "7.00.15"
 
 /* Compatability IDs for various adapters */
 #define IPS_COMPAT_UNKNOWN ""
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/libata-core.c linux-2.4.27-rc4/drivers/scsi/libata-core.c
--- linux-2.4.26/drivers/scsi/libata-core.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/libata-core.c	2004-07-30 16:29:11.000000000 +0000
@@ -0,0 +1,3527 @@
+/*
+   libata-core.c - helper library for ATA
+
+   Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+   Copyright 2003-2004 Jeff Garzik
+
+   The contents of this file are subject to the Open
+   Software License version 1.1 that can be found at
+   http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+   by reference.
+
+   Alternatively, the contents of this file may be used under the terms
+   of the GNU General Public License version 2 (the "GPL") as distributed
+   in the kernel source COPYING file, in which case the provisions of
+   the GPL are applicable instead of the above.  If you wish to allow
+   the use of your version of this file only under the terms of the
+   GPL and not to allow others to use your version of this file under
+   the OSL, indicate your decision by deleting the provisions above and
+   replace them with the notice and other provisions required by the GPL.
+   If you do not delete the provisions above, a recipient may use your
+   version of this file under either the OSL or the GPL.
+
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/highmem.h>
+#include <linux/spinlock.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/tqueue.h>
+#include <scsi/scsi.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include <asm/semaphore.h>
+
+#include "libata.h"
+
+static unsigned int ata_busy_sleep (struct ata_port *ap,
+				    unsigned long tmout_pat,
+			    	    unsigned long tmout);
+static void __ata_dev_select (struct ata_port *ap, unsigned int device);
+static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat);
+static void ata_host_set_pio(struct ata_port *ap);
+static void ata_host_set_udma(struct ata_port *ap);
+static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
+static void ata_dev_set_udma(struct ata_port *ap, unsigned int device);
+static void ata_set_mode(struct ata_port *ap);
+static int ata_qc_issue_prot(struct ata_queued_cmd *qc);
+
+static unsigned int ata_unique_id = 1;
+static LIST_HEAD(ata_probe_list);
+static spinlock_t ata_module_lock = SPIN_LOCK_UNLOCKED;
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("Library module for ATA devices");
+MODULE_LICENSE("GPL");
+
+static const char * thr_state_name[] = {
+	"THR_UNKNOWN",
+	"THR_PORT_RESET",
+	"THR_AWAIT_DEATH",
+	"THR_PROBE_FAILED",
+	"THR_IDLE",
+	"THR_PROBE_SUCCESS",
+	"THR_PROBE_START",
+};
+
+/**
+ *	ata_thr_state_name - convert thread state enum to string
+ *	@thr_state: thread state to be converted to string
+ *
+ *	Converts the specified thread state id to a constant C string.
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	The THR_xxx-prefixed string naming the specified thread
+ *	state id, or the string "<invalid THR_xxx state>".
+ */
+
+static const char *ata_thr_state_name(unsigned int thr_state)
+{
+	if (thr_state < ARRAY_SIZE(thr_state_name))
+		return thr_state_name[thr_state];
+	return "<invalid THR_xxx state>";
+}
+
+/**
+ *	msleep - sleep for a number of milliseconds
+ *	@msecs: number of milliseconds to sleep
+ *
+ *	Issues schedule_timeout call for the specified number
+ *	of milliseconds.
+ *
+ *	LOCKING:
+ *	None.
+ */
+
+static void msleep(unsigned long msecs)
+{
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(msecs) + 1);
+}
+
+/**
+ *	ata_tf_load_pio - send taskfile registers to host controller
+ *	@ap: Port to which output is sent
+ *	@tf: ATA taskfile register set
+ *
+ *	Outputs ATA taskfile to standard ATA host controller using PIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		outb(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		outb(tf->hob_feature, ioaddr->feature_addr);
+		outb(tf->hob_nsect, ioaddr->nsect_addr);
+		outb(tf->hob_lbal, ioaddr->lbal_addr);
+		outb(tf->hob_lbam, ioaddr->lbam_addr);
+		outb(tf->hob_lbah, ioaddr->lbah_addr);
+		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+			tf->hob_feature,
+			tf->hob_nsect,
+			tf->hob_lbal,
+			tf->hob_lbam,
+			tf->hob_lbah);
+	}
+
+	if (is_addr) {
+		outb(tf->feature, ioaddr->feature_addr);
+		outb(tf->nsect, ioaddr->nsect_addr);
+		outb(tf->lbal, ioaddr->lbal_addr);
+		outb(tf->lbam, ioaddr->lbam_addr);
+		outb(tf->lbah, ioaddr->lbah_addr);
+		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+			tf->feature,
+			tf->nsect,
+			tf->lbal,
+			tf->lbam,
+			tf->lbah);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE) {
+		outb(tf->device, ioaddr->device_addr);
+		VPRINTK("device 0x%X\n", tf->device);
+	}
+
+	ata_wait_idle(ap);
+}
+
+/**
+ *	ata_tf_load_mmio - send taskfile registers to host controller
+ *	@ap: Port to which output is sent
+ *	@tf: ATA taskfile register set
+ *
+ *	Outputs ATA taskfile to standard ATA host controller using MMIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		writeb(tf->ctl, ap->ioaddr.ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writeb(tf->hob_feature, (void *) ioaddr->feature_addr);
+		writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, (void *) ioaddr->lbah_addr);
+		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
+			tf->hob_feature,
+			tf->hob_nsect,
+			tf->hob_lbal,
+			tf->hob_lbam,
+			tf->hob_lbah);
+	}
+
+	if (is_addr) {
+		writeb(tf->feature, (void *) ioaddr->feature_addr);
+		writeb(tf->nsect, (void *) ioaddr->nsect_addr);
+		writeb(tf->lbal, (void *) ioaddr->lbal_addr);
+		writeb(tf->lbam, (void *) ioaddr->lbam_addr);
+		writeb(tf->lbah, (void *) ioaddr->lbah_addr);
+		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+			tf->feature,
+			tf->nsect,
+			tf->lbal,
+			tf->lbam,
+			tf->lbah);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE) {
+		writeb(tf->device, (void *) ioaddr->device_addr);
+		VPRINTK("device 0x%X\n", tf->device);
+	}
+
+	ata_wait_idle(ap);
+}
+
+/**
+ *	ata_exec_command_pio - issue ATA command to host controller
+ *	@ap: port to which command is being issued
+ *	@tf: ATA taskfile register set
+ *
+ *	Issues PIO write to ATA command register, with proper
+ *	synchronization with interrupt handler / other threads.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+
+       	outb(tf->command, ap->ioaddr.command_addr);
+	ata_pause(ap);
+}
+
+
+/**
+ *	ata_exec_command_mmio - issue ATA command to host controller
+ *	@ap: port to which command is being issued
+ *	@tf: ATA taskfile register set
+ *
+ *	Issues MMIO write to ATA command register, with proper
+ *	synchronization with interrupt handler / other threads.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+
+       	writeb(tf->command, (void *) ap->ioaddr.command_addr);
+	ata_pause(ap);
+}
+
+/**
+ *	ata_exec - issue ATA command to host controller
+ *	@ap: port to which command is being issued
+ *	@tf: ATA taskfile register set
+ *
+ *	Issues PIO write to ATA command register, with proper
+ *	synchronization with interrupt handler / other threads.
+ *
+ *	LOCKING:
+ *	Obtains host_set lock.
+ */
+
+static inline void ata_exec(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	unsigned long flags;
+
+	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	ap->ops->exec_command(ap, tf);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+}
+
+/**
+ *	ata_tf_to_host - issue ATA taskfile to host controller
+ *	@ap: port to which command is being issued
+ *	@tf: ATA taskfile register set
+ *
+ *	Issues ATA taskfile register set to ATA host controller,
+ *	via PIO, with proper synchronization with interrupt handler and
+ *	other threads.
+ *
+ *	LOCKING:
+ *	Obtains host_set lock.
+ */
+
+static void ata_tf_to_host(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	ap->ops->tf_load(ap, tf);
+
+	ata_exec(ap, tf);
+}
+
+/**
+ *	ata_tf_to_host_nolock - issue ATA taskfile to host controller
+ *	@ap: port to which command is being issued
+ *	@tf: ATA taskfile register set
+ *
+ *	Issues ATA taskfile register set to ATA host controller,
+ *	via PIO, with proper synchronization with interrupt handler and
+ *	other threads.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	ap->ops->tf_load(ap, tf);
+	ap->ops->exec_command(ap, tf);
+}
+
+/**
+ *	ata_tf_read_pio - input device's ATA taskfile shadow registers
+ *	@ap: Port from which input is read
+ *	@tf: ATA taskfile register set for storing input
+ *
+ *	Reads ATA taskfile registers for currently-selected device
+ *	into @tf via PIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->nsect = inb(ioaddr->nsect_addr);
+	tf->lbal = inb(ioaddr->lbal_addr);
+	tf->lbam = inb(ioaddr->lbam_addr);
+	tf->lbah = inb(ioaddr->lbah_addr);
+	tf->device = inb(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		outb(tf->ctl | ATA_HOB, ioaddr->ctl_addr);
+		tf->hob_feature = inb(ioaddr->error_addr);
+		tf->hob_nsect = inb(ioaddr->nsect_addr);
+		tf->hob_lbal = inb(ioaddr->lbal_addr);
+		tf->hob_lbam = inb(ioaddr->lbam_addr);
+		tf->hob_lbah = inb(ioaddr->lbah_addr);
+	}
+}
+
+/**
+ *	ata_tf_read_mmio - input device's ATA taskfile shadow registers
+ *	@ap: Port from which input is read
+ *	@tf: ATA taskfile register set for storing input
+ *
+ *	Reads ATA taskfile registers for currently-selected device
+ *	into @tf via MMIO.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	tf->nsect = readb((void *)ioaddr->nsect_addr);
+	tf->lbal = readb((void *)ioaddr->lbal_addr);
+	tf->lbam = readb((void *)ioaddr->lbam_addr);
+	tf->lbah = readb((void *)ioaddr->lbah_addr);
+	tf->device = readb((void *)ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		writeb(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr);
+		tf->hob_feature = readb((void *)ioaddr->error_addr);
+		tf->hob_nsect = readb((void *)ioaddr->nsect_addr);
+		tf->hob_lbal = readb((void *)ioaddr->lbal_addr);
+		tf->hob_lbam = readb((void *)ioaddr->lbam_addr);
+		tf->hob_lbah = readb((void *)ioaddr->lbah_addr);
+	}
+}
+
+/**
+ *	ata_check_status_pio - Read device status reg & clear interrupt
+ *	@ap: port where the device is
+ *
+ *	Reads ATA taskfile status register for currently-selected device
+ *	via PIO and return it's value. This also clears pending interrupts
+ *      from this device
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+u8 ata_check_status_pio(struct ata_port *ap)
+{
+	return inb(ap->ioaddr.status_addr);
+}
+
+/**
+ *	ata_check_status_mmio - Read device status reg & clear interrupt
+ *	@ap: port where the device is
+ *
+ *	Reads ATA taskfile status register for currently-selected device
+ *	via MMIO and return it's value. This also clears pending interrupts
+ *      from this device
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+u8 ata_check_status_mmio(struct ata_port *ap)
+{
+       	return readb((void *) ap->ioaddr.status_addr);
+}
+
+/**
+ *	ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
+ *	@tf: Taskfile to convert
+ *	@fis: Buffer into which data will output
+ *	@pmp: Port multiplier port
+ *
+ *	Converts a standard ATA taskfile to a Serial ATA
+ *	FIS structure (Register - Host to Device).
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp)
+{
+	fis[0] = 0x27;	/* Register - Host to Device FIS */
+	fis[1] = (pmp & 0xf) | (1 << 7); /* Port multiplier number,
+					    bit 7 indicates Command FIS */
+	fis[2] = tf->command;
+	fis[3] = tf->feature;
+
+	fis[4] = tf->lbal;
+	fis[5] = tf->lbam;
+	fis[6] = tf->lbah;
+	fis[7] = tf->device;
+
+	fis[8] = tf->hob_lbal;
+	fis[9] = tf->hob_lbam;
+	fis[10] = tf->hob_lbah;
+	fis[11] = tf->hob_feature;
+
+	fis[12] = tf->nsect;
+	fis[13] = tf->hob_nsect;
+	fis[14] = 0;
+	fis[15] = tf->ctl;
+
+	fis[16] = 0;
+	fis[17] = 0;
+	fis[18] = 0;
+	fis[19] = 0;
+}
+
+/**
+ *	ata_tf_from_fis - Convert SATA FIS to ATA taskfile
+ *	@fis: Buffer from which data will be input
+ *	@tf: Taskfile to output
+ *
+ *	Converts a standard ATA taskfile to a Serial ATA
+ *	FIS structure (Register - Host to Device).
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+
+void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
+{
+	tf->command	= fis[2];	/* status */
+	tf->feature	= fis[3];	/* error */
+
+	tf->lbal	= fis[4];
+	tf->lbam	= fis[5];
+	tf->lbah	= fis[6];
+	tf->device	= fis[7];
+
+	tf->hob_lbal	= fis[8];
+	tf->hob_lbam	= fis[9];
+	tf->hob_lbah	= fis[10];
+
+	tf->nsect	= fis[12];
+	tf->hob_nsect	= fis[13];
+}
+
+/**
+ *	ata_prot_to_cmd - determine which read/write opcodes to use
+ *	@protocol: ATA_PROT_xxx taskfile protocol
+ *	@lba48: true is lba48 is present
+ *
+ *	Given necessary input, determine which read/write commands
+ *	to use to transfer data.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static int ata_prot_to_cmd(int protocol, int lba48)
+{
+	int rcmd = 0, wcmd = 0;
+
+	switch (protocol) {
+	case ATA_PROT_PIO:
+		if (lba48) {
+			rcmd = ATA_CMD_PIO_READ_EXT;
+			wcmd = ATA_CMD_PIO_WRITE_EXT;
+		} else {
+			rcmd = ATA_CMD_PIO_READ;
+			wcmd = ATA_CMD_PIO_WRITE;
+		}
+		break;
+
+	case ATA_PROT_DMA:
+		if (lba48) {
+			rcmd = ATA_CMD_READ_EXT;
+			wcmd = ATA_CMD_WRITE_EXT;
+		} else {
+			rcmd = ATA_CMD_READ;
+			wcmd = ATA_CMD_WRITE;
+		}
+		break;
+
+	default:
+		return -1;
+	}
+
+	return rcmd | (wcmd << 8);
+}
+
+/**
+ *	ata_dev_set_protocol - set taskfile protocol and r/w commands
+ *	@dev: device to examine and configure
+ *
+ *	Examine the device configuration, after we have
+ *	read the identify-device page and configured the
+ *	data transfer mode.  Set internal state related to
+ *	the ATA taskfile protocol (pio, pio mult, dma, etc.)
+ *	and calculate the proper read/write commands to use.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+static void ata_dev_set_protocol(struct ata_device *dev)
+{
+	int pio = (dev->flags & ATA_DFLAG_PIO);
+	int lba48 = (dev->flags & ATA_DFLAG_LBA48);
+	int proto, cmd;
+
+	if (pio)
+		proto = dev->xfer_protocol = ATA_PROT_PIO;
+	else
+		proto = dev->xfer_protocol = ATA_PROT_DMA;
+
+	cmd = ata_prot_to_cmd(proto, lba48);
+	if (cmd < 0)
+		BUG();
+
+	dev->read_cmd = cmd & 0xff;
+	dev->write_cmd = (cmd >> 8) & 0xff;
+}
+
+static const char * udma_str[] = {
+	"UDMA/16",
+	"UDMA/25",
+	"UDMA/33",
+	"UDMA/44",
+	"UDMA/66",
+	"UDMA/100",
+	"UDMA/133",
+	"UDMA7",
+};
+
+/**
+ *	ata_udma_string - convert UDMA bit offset to string
+ *	@udma_mask: mask of bits supported; only highest bit counts.
+ *
+ *	Determine string which represents the highest speed
+ *	(highest bit in @udma_mask).
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	Constant C string representing highest speed listed in
+ *	@udma_mask, or the constant C string "<n/a>".
+ */
+
+static const char *ata_udma_string(unsigned int udma_mask)
+{
+	int i;
+
+	for (i = 7; i >= 0; i--) {
+		if (udma_mask & (1 << i))
+			return udma_str[i];
+	}
+
+	return "<n/a>";
+}
+
+/**
+ *	ata_pio_devchk - PATA device presence detection
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
+ *
+ *	This technique was originally described in
+ *	Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *	later found its way into the ATA/ATAPI spec.
+ *
+ *	Write a pattern to the ATA shadow registers,
+ *	and if a device is present, it will respond by
+ *	correctly storing and echoing back the
+ *	ATA shadow register contents.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static unsigned int ata_pio_devchk(struct ata_port *ap,
+				   unsigned int device)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 nsect, lbal;
+
+	__ata_dev_select(ap, device);
+
+	outb(0x55, ioaddr->nsect_addr);
+	outb(0xaa, ioaddr->lbal_addr);
+
+	outb(0xaa, ioaddr->nsect_addr);
+	outb(0x55, ioaddr->lbal_addr);
+
+	outb(0x55, ioaddr->nsect_addr);
+	outb(0xaa, ioaddr->lbal_addr);
+
+	nsect = inb(ioaddr->nsect_addr);
+	lbal = inb(ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa))
+		return 1;	/* we found a device */
+
+	return 0;		/* nothing found */
+}
+
+/**
+ *	ata_mmio_devchk - PATA device presence detection
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
+ *
+ *	This technique was originally described in
+ *	Hale Landis's ATADRVR (www.ata-atapi.com), and
+ *	later found its way into the ATA/ATAPI spec.
+ *
+ *	Write a pattern to the ATA shadow registers,
+ *	and if a device is present, it will respond by
+ *	correctly storing and echoing back the
+ *	ATA shadow register contents.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static unsigned int ata_mmio_devchk(struct ata_port *ap,
+				    unsigned int device)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u8 nsect, lbal;
+
+	__ata_dev_select(ap, device);
+
+	writeb(0x55, (void *) ioaddr->nsect_addr);
+	writeb(0xaa, (void *) ioaddr->lbal_addr);
+
+	writeb(0xaa, (void *) ioaddr->nsect_addr);
+	writeb(0x55, (void *) ioaddr->lbal_addr);
+
+	writeb(0x55, (void *) ioaddr->nsect_addr);
+	writeb(0xaa, (void *) ioaddr->lbal_addr);
+
+	nsect = readb((void *) ioaddr->nsect_addr);
+	lbal = readb((void *) ioaddr->lbal_addr);
+
+	if ((nsect == 0x55) && (lbal == 0xaa))
+		return 1;	/* we found a device */
+
+	return 0;		/* nothing found */
+}
+
+/**
+ *	ata_dev_devchk - PATA device presence detection
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
+ *
+ *	Dispatch ATA device presence detection, depending
+ *	on whether we are using PIO or MMIO to talk to the
+ *	ATA shadow registers.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static unsigned int ata_dev_devchk(struct ata_port *ap,
+				    unsigned int device)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		return ata_mmio_devchk(ap, device);
+	return ata_pio_devchk(ap, device);
+}
+
+/**
+ *	ata_dev_classify - determine device type based on ATA-spec signature
+ *	@tf: ATA taskfile register set for device to be identified
+ *
+ *	Determine from taskfile register contents whether a device is
+ *	ATA or ATAPI, as per "Signature and persistence" section
+ *	of ATA/PI spec (volume 1, sect 5.14).
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, or %ATA_DEV_UNKNOWN
+ *	the event of failure.
+ */
+
+static unsigned int ata_dev_classify(struct ata_taskfile *tf)
+{
+	/* Apple's open source Darwin code hints that some devices only
+	 * put a proper signature into the LBA mid/high registers,
+	 * So, we only check those.  It's sufficient for uniqueness.
+	 */
+
+	if (((tf->lbam == 0) && (tf->lbah == 0)) ||
+	    ((tf->lbam == 0x3c) && (tf->lbah == 0xc3))) {
+		DPRINTK("found ATA device by sig\n");
+		return ATA_DEV_ATA;
+	}
+
+	if (((tf->lbam == 0x14) && (tf->lbah == 0xeb)) ||
+	    ((tf->lbam == 0x69) && (tf->lbah == 0x96))) {
+		DPRINTK("found ATAPI device by sig\n");
+		return ATA_DEV_ATAPI;
+	}
+
+	DPRINTK("unknown device\n");
+	return ATA_DEV_UNKNOWN;
+}
+
+/**
+ *	ata_dev_try_classify - Parse returned ATA device signature
+ *	@ap: ATA channel to examine
+ *	@device: Device to examine (starting at zero)
+ *
+ *	After an event -- SRST, E.D.D., or SATA COMRESET -- occurs,
+ *	an ATA/ATAPI-defined set of values is placed in the ATA
+ *	shadow registers, indicating the results of device detection
+ *	and diagnostics.
+ *
+ *	Select the ATA device, and read the values from the ATA shadow
+ *	registers.  Then parse according to the Error register value,
+ *	and the spec-defined values examined by ata_dev_classify().
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
+{
+	struct ata_device *dev = &ap->device[device];
+	struct ata_taskfile tf;
+	unsigned int class;
+	u8 err;
+
+	__ata_dev_select(ap, device);
+
+	memset(&tf, 0, sizeof(tf));
+
+	err = ata_chk_err(ap);
+	ap->ops->tf_read(ap, &tf);
+
+	dev->class = ATA_DEV_NONE;
+
+	/* see if device passed diags */
+	if (err == 1)
+		/* do nothing */ ;
+	else if ((device == 0) && (err == 0x81))
+		/* do nothing */ ;
+	else
+		return err;
+
+	/* determine if device if ATA or ATAPI */
+	class = ata_dev_classify(&tf);
+	if (class == ATA_DEV_UNKNOWN)
+		return err;
+	if ((class == ATA_DEV_ATA) && (ata_chk_status(ap) == 0))
+		return err;
+
+	dev->class = class;
+
+	return err;
+}
+
+/**
+ *	ata_dev_id_string - Convert IDENTIFY DEVICE page into string
+ *	@dev: Device whose IDENTIFY DEVICE results we will examine
+ *	@s: string into which data is output
+ *	@ofs: offset into identify device page
+ *	@len: length of string to return. must be an even number.
+ *
+ *	The strings in the IDENTIFY DEVICE page are broken up into
+ *	16-bit chunks.  Run through the string, and output each
+ *	8-bit chunk linearly, regardless of platform.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
+		       unsigned int ofs, unsigned int len)
+{
+	unsigned int c;
+
+	while (len > 0) {
+		c = dev->id[ofs] >> 8;
+		*s = c;
+		s++;
+
+		c = dev->id[ofs] & 0xff;
+		*s = c;
+		s++;
+
+		ofs++;
+		len -= 2;
+	}
+}
+
+/**
+ *	__ata_dev_select - Select device 0/1 on ATA bus
+ *	@ap: ATA channel to manipulate
+ *	@device: ATA device (numbered from zero) to select
+ *
+ *	Use the method defined in the ATA specification to
+ *	make either device 0, or device 1, active on the
+ *	ATA channel.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static void __ata_dev_select (struct ata_port *ap, unsigned int device)
+{
+	u8 tmp;
+
+	if (device == 0)
+		tmp = ATA_DEVICE_OBS;
+	else
+		tmp = ATA_DEVICE_OBS | ATA_DEV1;
+
+	if (ap->flags & ATA_FLAG_MMIO) {
+		writeb(tmp, (void *) ap->ioaddr.device_addr);
+	} else {
+		outb(tmp, ap->ioaddr.device_addr);
+	}
+	ata_pause(ap);		/* needed; also flushes, for mmio */
+}
+
+/**
+ *	ata_dev_select - Select device 0/1 on ATA bus
+ *	@ap: ATA channel to manipulate
+ *	@device: ATA device (numbered from zero) to select
+ *	@wait: non-zero to wait for Status register BSY bit to clear
+ *	@can_sleep: non-zero if context allows sleeping
+ *
+ *	Use the method defined in the ATA specification to
+ *	make either device 0, or device 1, active on the
+ *	ATA channel.
+ *
+ *	This is a high-level version of __ata_dev_select(),
+ *	which additionally provides the services of inserting
+ *	the proper pauses and status polling, where needed.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+void ata_dev_select(struct ata_port *ap, unsigned int device,
+			   unsigned int wait, unsigned int can_sleep)
+{
+	VPRINTK("ENTER, ata%u: device %u, wait %u\n",
+		ap->id, device, wait);
+
+	if (wait)
+		ata_wait_idle(ap);
+
+	__ata_dev_select(ap, device);
+
+	if (wait) {
+		if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
+			msleep(150);
+		ata_wait_idle(ap);
+	}
+}
+
+/**
+ *	ata_dump_id - IDENTIFY DEVICE info debugging output
+ *	@dev: Device whose IDENTIFY DEVICE page we will dump
+ *
+ *	Dump selected 16-bit words from a detected device's
+ *	IDENTIFY PAGE page.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static inline void ata_dump_id(struct ata_device *dev)
+{
+	DPRINTK("49==0x%04x  "
+		"53==0x%04x  "
+		"63==0x%04x  "
+		"64==0x%04x  "
+		"75==0x%04x  \n",
+		dev->id[49],
+		dev->id[53],
+		dev->id[63],
+		dev->id[64],
+		dev->id[75]);
+	DPRINTK("80==0x%04x  "
+		"81==0x%04x  "
+		"82==0x%04x  "
+		"83==0x%04x  "
+		"84==0x%04x  \n",
+		dev->id[80],
+		dev->id[81],
+		dev->id[82],
+		dev->id[83],
+		dev->id[84]);
+	DPRINTK("88==0x%04x  "
+		"93==0x%04x\n",
+		dev->id[88],
+		dev->id[93]);
+}
+
+/**
+ *	ata_dev_identify - obtain IDENTIFY x DEVICE page
+ *	@ap: port on which device we wish to probe resides
+ *	@device: device bus address, starting at zero
+ *
+ *	Following bus reset, we issue the IDENTIFY [PACKET] DEVICE
+ *	command, and read back the 512-byte device information page.
+ *	The device information page is fed to us via the standard
+ *	PIO-IN protocol, but we hand-code it here. (TODO: investigate
+ *	using standard PIO-IN paths)
+ *
+ *	After reading the device information page, we use several
+ *	bits of information from it to initialize data structures
+ *	that will be used during the lifetime of the ata_device.
+ *	Other data from the info page is used to disqualify certain
+ *	older ATA devices we do not wish to support.
+ *
+ *	LOCKING:
+ *	Inherited from caller.  Some functions called by this function
+ *	obtain the host_set lock.
+ */
+
+static void ata_dev_identify(struct ata_port *ap, unsigned int device)
+{
+	struct ata_device *dev = &ap->device[device];
+	unsigned int i;
+	u16 tmp, udma_modes;
+	u8 status;
+	struct ata_taskfile tf;
+	unsigned int using_edd;
+
+	if (!ata_dev_present(dev)) {
+		DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
+			ap->id, device);
+		return;
+	}
+
+	if (ap->flags & (ATA_FLAG_SRST | ATA_FLAG_SATA_RESET))
+		using_edd = 0;
+	else
+		using_edd = 1;
+
+	DPRINTK("ENTER, host %u, dev %u\n", ap->id, device);
+
+	assert (dev->class == ATA_DEV_ATA || dev->class == ATA_DEV_ATAPI ||
+		dev->class == ATA_DEV_NONE);
+
+	ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
+
+retry:
+	ata_tf_init(ap, &tf, device);
+	tf.ctl |= ATA_NIEN;
+	tf.protocol = ATA_PROT_PIO;
+
+	if (dev->class == ATA_DEV_ATA) {
+		tf.command = ATA_CMD_ID_ATA;
+		DPRINTK("do ATA identify\n");
+	} else {
+		tf.command = ATA_CMD_ID_ATAPI;
+		DPRINTK("do ATAPI identify\n");
+	}
+
+	ata_tf_to_host(ap, &tf);
+
+	/* crazy ATAPI devices... */
+	if (dev->class == ATA_DEV_ATAPI)
+		msleep(150);
+
+	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT))
+		goto err_out;
+
+	status = ata_chk_status(ap);
+	if (status & ATA_ERR) {
+		/*
+		 * arg!  EDD works for all test cases, but seems to return
+		 * the ATA signature for some ATAPI devices.  Until the
+		 * reason for this is found and fixed, we fix up the mess
+		 * here.  If IDENTIFY DEVICE returns command aborted
+		 * (as ATAPI devices do), then we issue an
+		 * IDENTIFY PACKET DEVICE.
+		 *
+		 * ATA software reset (SRST, the default) does not appear
+		 * to have this problem.
+		 */
+		if ((using_edd) && (tf.command == ATA_CMD_ID_ATA)) {
+			u8 err = ata_chk_err(ap);
+			if (err & ATA_ABORTED) {
+				dev->class = ATA_DEV_ATAPI;
+				goto retry;
+			}
+		}
+		goto err_out;
+	}
+
+	/* make sure we have BSY=0, DRQ=1 */
+	if ((status & ATA_DRQ) == 0) {
+		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) not returning id page (0x%x)\n",
+		       ap->id, device,
+		       dev->class == ATA_DEV_ATA ? "" : "PI",
+		       status);
+		goto err_out;
+	}
+
+	/* read IDENTIFY [X] DEVICE page */
+	if (ap->flags & ATA_FLAG_MMIO) {
+		for (i = 0; i < ATA_ID_WORDS; i++)
+			dev->id[i] = readw((void *)ap->ioaddr.data_addr);
+	} else
+		for (i = 0; i < ATA_ID_WORDS; i++)
+			dev->id[i] = inw(ap->ioaddr.data_addr);
+
+	/* wait for host_idle */
+	status = ata_wait_idle(ap);
+	if (status & (ATA_BUSY | ATA_DRQ)) {
+		printk(KERN_WARNING "ata%u: dev %u (ATA%s?) error after id page (0x%x)\n",
+		       ap->id, device,
+		       dev->class == ATA_DEV_ATA ? "" : "PI",
+		       status);
+		goto err_out;
+	}
+
+	ata_irq_on(ap);	/* re-enable interrupts */
+
+	/* print device capabilities */
+	printk(KERN_DEBUG "ata%u: dev %u cfg "
+	       "49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
+	       ap->id, device, dev->id[49],
+	       dev->id[82], dev->id[83], dev->id[84],
+	       dev->id[85], dev->id[86], dev->id[87],
+	       dev->id[88]);
+
+	/*
+	 * common ATA, ATAPI feature tests
+	 */
+
+	/* we require LBA and DMA support (bits 8 & 9 of word 49) */
+	if (!ata_id_has_dma(dev) || !ata_id_has_lba(dev)) {
+		printk(KERN_DEBUG "ata%u: no dma/lba\n", ap->id);
+		goto err_out_nosup;
+	}
+
+	/* we require UDMA support */
+	udma_modes =
+	tmp = dev->id[ATA_ID_UDMA_MODES];
+	if ((tmp & 0xff) == 0) {
+		printk(KERN_DEBUG "ata%u: no udma\n", ap->id);
+		goto err_out_nosup;
+	}
+
+	ata_dump_id(dev);
+
+	/* ATA-specific feature tests */
+	if (dev->class == ATA_DEV_ATA) {
+		if (!ata_id_is_ata(dev))	/* sanity check */
+			goto err_out_nosup;
+
+		tmp = dev->id[ATA_ID_MAJOR_VER];
+		for (i = 14; i >= 1; i--)
+			if (tmp & (1 << i))
+				break;
+
+		/* we require at least ATA-3 */
+		if (i < 3) {
+			printk(KERN_DEBUG "ata%u: no ATA-3\n", ap->id);
+			goto err_out_nosup;
+		}
+
+		if (ata_id_has_lba48(dev)) {
+			dev->flags |= ATA_DFLAG_LBA48;
+			dev->n_sectors = ata_id_u64(dev, 100);
+		} else {
+			dev->n_sectors = ata_id_u32(dev, 60);
+		}
+
+		ap->host->max_cmd_len = 16;
+
+		/* print device info to dmesg */
+		printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
+		       ap->id, device,
+		       ata_udma_string(udma_modes),
+		       (unsigned long long)dev->n_sectors,
+		       dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
+	}
+
+	/* ATAPI-specific feature tests */
+	else {
+		if (ata_id_is_ata(dev))		/* sanity check */
+			goto err_out_nosup;
+
+		/* see if 16-byte commands supported */
+		tmp = dev->id[0] & 0x3;
+		if (tmp == 1)
+			ap->host->max_cmd_len = 16;
+
+		/* print device info to dmesg */
+		printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
+		       ap->id, device,
+		       ata_udma_string(udma_modes));
+	}
+
+	DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
+	return;
+
+err_out_nosup:
+	printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
+	       ap->id, device);
+err_out:
+	ata_irq_on(ap);	/* re-enable interrupts */
+	dev->class++;	/* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
+	DPRINTK("EXIT, err\n");
+}
+
+/**
+ *	ata_port_reset -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+static void ata_port_reset(struct ata_port *ap)
+{
+	unsigned int i, found = 0;
+
+	ap->ops->phy_reset(ap);
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		goto err_out;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		ata_dev_identify(ap, i);
+		if (ata_dev_present(&ap->device[i])) {
+			found = 1;
+			if (ap->ops->dev_config)
+				ap->ops->dev_config(ap, &ap->device[i]);
+		}
+	}
+
+	if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		goto err_out_disable;
+
+	ata_set_mode(ap);
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		goto err_out_disable;
+
+	ap->thr_state = THR_PROBE_SUCCESS;
+
+	return;
+
+err_out_disable:
+	ap->ops->port_disable(ap);
+err_out:
+	ap->thr_state = THR_PROBE_FAILED;
+}
+
+/**
+ *	ata_port_probe -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+void ata_port_probe(struct ata_port *ap)
+{
+	ap->flags &= ~ATA_FLAG_PORT_DISABLED;
+}
+
+/**
+ *	sata_phy_reset -
+ *	@ap:
+ *
+ *	LOCKING:
+ *
+ */
+void sata_phy_reset(struct ata_port *ap)
+{
+	u32 sstatus;
+	unsigned long timeout = jiffies + (HZ * 5);
+
+	if (ap->flags & ATA_FLAG_SATA_RESET) {
+		scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */
+		scr_read(ap, SCR_STATUS);	/* dummy read; flush */
+		udelay(400);			/* FIXME: a guess */
+	}
+	scr_write(ap, SCR_CONTROL, 0x300);	/* issue phy wake/clear reset */
+
+	/* wait for phy to become ready, if necessary */
+	do {
+		msleep(200);
+		sstatus = scr_read(ap, SCR_STATUS);
+		if ((sstatus & 0xf) != 1)
+			break;
+	} while (time_before(jiffies, timeout));
+
+	/* TODO: phy layer with polling, timeouts, etc. */
+	if (sata_dev_present(ap))
+		ata_port_probe(ap);
+	else {
+		sstatus = scr_read(ap, SCR_STATUS);
+		printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+		       ap->id, sstatus);
+		ata_port_disable(ap);
+	}
+
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
+
+	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
+		ata_port_disable(ap);
+		return;
+	}
+
+	ata_bus_reset(ap);
+}
+
+/**
+ *	ata_port_disable -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+void ata_port_disable(struct ata_port *ap)
+{
+	ap->device[0].class = ATA_DEV_NONE;
+	ap->device[1].class = ATA_DEV_NONE;
+	ap->flags |= ATA_FLAG_PORT_DISABLED;
+}
+
+/**
+ *	ata_set_mode - Program timings and issue SET FEATURES - XFER
+ *	@ap: port on which timings will be programmed
+ *
+ *	LOCKING:
+ *
+ */
+static void ata_set_mode(struct ata_port *ap)
+{
+	unsigned int force_pio, i;
+
+	ata_host_set_pio(ap);
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
+
+	ata_host_set_udma(ap);
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
+
+#ifdef ATA_FORCE_PIO
+	force_pio = 1;
+#else
+	force_pio = 0;
+#endif
+
+	if (force_pio) {
+		ata_dev_set_pio(ap, 0);
+		ata_dev_set_pio(ap, 1);
+	} else {
+		ata_dev_set_udma(ap, 0);
+		ata_dev_set_udma(ap, 1);
+	}
+
+	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+		return;
+
+	if (ap->ops->post_set_mode)
+		ap->ops->post_set_mode(ap);
+
+	for (i = 0; i < 2; i++) {
+		struct ata_device *dev = &ap->device[i];
+		ata_dev_set_protocol(dev);
+	}
+}
+
+/**
+ *	ata_busy_sleep - sleep until BSY clears, or timeout
+ *	@ap: port containing status register to be polled
+ *	@tmout_pat: impatience timeout
+ *	@tmout: overall timeout
+ *
+ *	LOCKING:
+ *
+ */
+
+static unsigned int ata_busy_sleep (struct ata_port *ap,
+				    unsigned long tmout_pat,
+			    	    unsigned long tmout)
+{
+	unsigned long timer_start, timeout;
+	u8 status;
+
+	status = ata_busy_wait(ap, ATA_BUSY, 300);
+	timer_start = jiffies;
+	timeout = timer_start + tmout_pat;
+	while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+		msleep(50);
+		status = ata_busy_wait(ap, ATA_BUSY, 3);
+	}
+
+	if (status & ATA_BUSY)
+		printk(KERN_WARNING "ata%u is slow to respond, "
+		       "please be patient\n", ap->id);
+
+	timeout = timer_start + tmout;
+	while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+		msleep(50);
+		status = ata_chk_status(ap);
+	}
+
+	if (status & ATA_BUSY) {
+		printk(KERN_ERR "ata%u failed to respond (%lu secs)\n",
+		       ap->id, tmout / HZ);
+		return 1;
+	}
+
+	return 0;
+}
+
+static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int dev0 = devmask & (1 << 0);
+	unsigned int dev1 = devmask & (1 << 1);
+	unsigned long timeout;
+
+	/* if device 0 was found in ata_dev_devchk, wait for its
+	 * BSY bit to clear
+	 */
+	if (dev0)
+		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+	/* if device 1 was found in ata_dev_devchk, wait for
+	 * register access, then wait for BSY to clear
+	 */
+	timeout = jiffies + ATA_TMOUT_BOOT;
+	while (dev1) {
+		u8 nsect, lbal;
+
+		__ata_dev_select(ap, 1);
+		if (ap->flags & ATA_FLAG_MMIO) {
+			nsect = readb((void *) ioaddr->nsect_addr);
+			lbal = readb((void *) ioaddr->lbal_addr);
+		} else {
+			nsect = inb(ioaddr->nsect_addr);
+			lbal = inb(ioaddr->lbal_addr);
+		}
+		if ((nsect == 1) && (lbal == 1))
+			break;
+		if (time_after(jiffies, timeout)) {
+			dev1 = 0;
+			break;
+		}
+		msleep(50);	/* give drive a breather */
+	}
+	if (dev1)
+		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+	/* is all this really necessary? */
+	__ata_dev_select(ap, 0);
+	if (dev1)
+		__ata_dev_select(ap, 1);
+	if (dev0)
+		__ata_dev_select(ap, 0);
+}
+
+/**
+ *	ata_bus_edd -
+ *	@ap:
+ *
+ *	LOCKING:
+ *
+ */
+
+static unsigned int ata_bus_edd(struct ata_port *ap)
+{
+	struct ata_taskfile tf;
+
+	/* set up execute-device-diag (bus reset) taskfile */
+	/* also, take interrupts to a known state (disabled) */
+	DPRINTK("execute-device-diag\n");
+	ata_tf_init(ap, &tf, 0);
+	tf.ctl |= ATA_NIEN;
+	tf.command = ATA_CMD_EDD;
+	tf.protocol = ATA_PROT_NODATA;
+
+	/* do bus reset */
+	ata_tf_to_host(ap, &tf);
+
+	/* spec says at least 2ms.  but who knows with those
+	 * crazy ATAPI devices...
+	 */
+	msleep(150);
+
+	return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+}
+
+static unsigned int ata_bus_softreset(struct ata_port *ap,
+				      unsigned int devmask)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	DPRINTK("ata%u: bus reset via SRST\n", ap->id);
+
+	/* software reset.  causes dev0 to be selected */
+	if (ap->flags & ATA_FLAG_MMIO) {
+		writeb(ap->ctl, ioaddr->ctl_addr);
+		udelay(20);	/* FIXME: flush */
+		writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+		udelay(20);	/* FIXME: flush */
+		writeb(ap->ctl, ioaddr->ctl_addr);
+	} else {
+		outb(ap->ctl, ioaddr->ctl_addr);
+		udelay(10);
+		outb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+		udelay(10);
+		outb(ap->ctl, ioaddr->ctl_addr);
+	}
+
+	/* spec mandates ">= 2ms" before checking status.
+	 * We wait 150ms, because that was the magic delay used for
+	 * ATAPI devices in Hale Landis's ATADRVR, for the period of time
+	 * between when the ATA command register is written, and then
+	 * status is checked.  Because waiting for "a while" before
+	 * checking status is fine, post SRST, we perform this magic
+	 * delay here as well.
+	 */
+	msleep(150);
+
+	ata_bus_post_reset(ap, devmask);
+
+	return 0;
+}
+
+/**
+ *	ata_bus_reset - reset host port and associated ATA channel
+ *	@ap: port to reset
+ *
+ *	This is typically the first time we actually start issuing
+ *	commands to the ATA channel.  We wait for BSY to clear, then
+ *	issue EXECUTE DEVICE DIAGNOSTIC command, polling for its
+ *	result.  Determine what devices, if any, are on the channel
+ *	by looking at the device 0/1 error register.  Look at the signature
+ *	stored in each device's taskfile registers, to determine if
+ *	the device is ATA or ATAPI.
+ *
+ *	LOCKING:
+ *	Inherited from caller.  Some functions called by this function
+ *	obtain the host_set lock.
+ *
+ *	SIDE EFFECTS:
+ *	Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
+ */
+
+void ata_bus_reset(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
+	u8 err;
+	unsigned int dev0, dev1 = 0, rc = 0, devmask = 0;
+
+	DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no);
+
+	/* determine if device 0/1 are present */
+	if (ap->flags & ATA_FLAG_SATA_RESET)
+		dev0 = 1;
+	else {
+		dev0 = ata_dev_devchk(ap, 0);
+		if (slave_possible)
+			dev1 = ata_dev_devchk(ap, 1);
+	}
+
+	if (dev0)
+		devmask |= (1 << 0);
+	if (dev1)
+		devmask |= (1 << 1);
+
+	/* select device 0 again */
+	__ata_dev_select(ap, 0);
+
+	/* issue bus reset */
+	if (ap->flags & ATA_FLAG_SRST)
+		rc = ata_bus_softreset(ap, devmask);
+	else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
+		/* set up device control */
+		if (ap->flags & ATA_FLAG_MMIO)
+			writeb(ap->ctl, ioaddr->ctl_addr);
+		else
+			outb(ap->ctl, ioaddr->ctl_addr);
+		rc = ata_bus_edd(ap);
+	}
+
+	if (rc)
+		goto err_out;
+
+	/*
+	 * determine by signature whether we have ATA or ATAPI devices
+	 */
+	err = ata_dev_try_classify(ap, 0);
+	if ((slave_possible) && (err != 0x81))
+		ata_dev_try_classify(ap, 1);
+
+	/* re-enable interrupts */
+	ata_irq_on(ap);
+
+	/* is double-select really necessary? */
+	if (ap->device[1].class != ATA_DEV_NONE)
+		__ata_dev_select(ap, 1);
+	if (ap->device[0].class != ATA_DEV_NONE)
+		__ata_dev_select(ap, 0);
+
+	/* if no devices were detected, disable this port */
+	if ((ap->device[0].class == ATA_DEV_NONE) &&
+	    (ap->device[1].class == ATA_DEV_NONE))
+		goto err_out;
+
+	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
+		/* set up device control for ATA_FLAG_SATA_RESET */
+		if (ap->flags & ATA_FLAG_MMIO)
+			writeb(ap->ctl, ioaddr->ctl_addr);
+		else
+			outb(ap->ctl, ioaddr->ctl_addr);
+	}
+
+	DPRINTK("EXIT\n");
+	return;
+
+err_out:
+	printk(KERN_ERR "ata%u: disabling port\n", ap->id);
+	ap->ops->port_disable(ap);
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_host_set_pio -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+static void ata_host_set_pio(struct ata_port *ap)
+{
+	struct ata_device *master, *slave;
+	unsigned int pio, i;
+	u16 mask;
+
+	master = &ap->device[0];
+	slave = &ap->device[1];
+
+	assert (ata_dev_present(master) || ata_dev_present(slave));
+
+	mask = ap->pio_mask;
+	if (ata_dev_present(master))
+		mask &= (master->id[ATA_ID_PIO_MODES] & 0x03);
+	if (ata_dev_present(slave))
+		mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03);
+
+	/* require pio mode 3 or 4 support for host and all devices */
+	if (mask == 0) {
+		printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n",
+		       ap->id);
+		goto err_out;
+	}
+
+	pio = (mask & ATA_ID_PIO4) ? 4 : 3;
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		if (ata_dev_present(&ap->device[i])) {
+			ap->device[i].pio_mode = (pio == 3) ?
+				XFER_PIO_3 : XFER_PIO_4;
+			if (ap->ops->set_piomode)
+				ap->ops->set_piomode(ap, &ap->device[i], pio);
+		}
+
+	return;
+
+err_out:
+	ap->ops->port_disable(ap);
+}
+
+/**
+ *	ata_host_set_udma -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+static void ata_host_set_udma(struct ata_port *ap)
+{
+	struct ata_device *master, *slave;
+	u16 mask;
+	unsigned int i, j;
+	int udma_mode = -1;
+
+	master = &ap->device[0];
+	slave = &ap->device[1];
+
+	assert (ata_dev_present(master) || ata_dev_present(slave));
+	assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0);
+
+	DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n",
+		ap->udma_mask,
+		(!ata_dev_present(master)) ? 0xff :
+			(master->id[ATA_ID_UDMA_MODES] & 0xff),
+		(!ata_dev_present(slave)) ? 0xff :
+			(slave->id[ATA_ID_UDMA_MODES] & 0xff));
+
+	mask = ap->udma_mask;
+	if (ata_dev_present(master))
+		mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
+	if (ata_dev_present(slave))
+		mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
+
+	i = XFER_UDMA_7;
+	while (i >= XFER_UDMA_0) {
+		j = i - XFER_UDMA_0;
+		DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j);
+		if (mask & (1 << j)) {
+			udma_mode = i;
+			break;
+		}
+
+		i--;
+	}
+
+	/* require udma for host and all attached devices */
+	if (udma_mode < 0) {
+		printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n",
+		       ap->id);
+		goto err_out;
+	}
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		if (ata_dev_present(&ap->device[i])) {
+			ap->device[i].udma_mode = udma_mode;
+			if (ap->ops->set_udmamode)
+				ap->ops->set_udmamode(ap, &ap->device[i],
+						      udma_mode);
+		}
+
+	return;
+
+err_out:
+	ap->ops->port_disable(ap);
+}
+
+/**
+ *	ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command
+ *	@ap: Port associated with device @dev
+ *	@dev: Device to which command will be sent
+ *
+ *	LOCKING:
+ */
+
+static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
+{
+	struct ata_taskfile tf;
+
+	/* set up set-features taskfile */
+	DPRINTK("set features - xfer mode\n");
+	ata_tf_init(ap, &tf, dev->devno);
+	tf.ctl |= ATA_NIEN;
+	tf.command = ATA_CMD_SET_FEATURES;
+	tf.feature = SETFEATURES_XFER;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+	if (dev->flags & ATA_DFLAG_PIO)
+		tf.nsect = dev->pio_mode;
+	else
+		tf.nsect = dev->udma_mode;
+
+	/* do bus reset */
+	ata_tf_to_host(ap, &tf);
+
+	/* crazy ATAPI devices... */
+	if (dev->class == ATA_DEV_ATAPI)
+		msleep(150);
+
+	ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+	ata_irq_on(ap);	/* re-enable interrupts */
+
+	ata_wait_idle(ap);
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA
+ *	@ap: Port associated with device @dev
+ *	@device: Device whose mode will be set
+ *
+ *	LOCKING:
+ */
+
+static void ata_dev_set_udma(struct ata_port *ap, unsigned int device)
+{
+	struct ata_device *dev = &ap->device[device];
+
+	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		return;
+
+	ata_dev_set_xfermode(ap, dev);
+
+	assert((dev->udma_mode >= XFER_UDMA_0) &&
+	       (dev->udma_mode <= XFER_UDMA_7));
+	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
+	       ap->id, device,
+	       udma_str[dev->udma_mode - XFER_UDMA_0]);
+}
+
+/**
+ *	ata_dev_set_pio - Set ATA device's transfer mode to PIO
+ *	@ap: Port associated with device @dev
+ *	@device: Device whose mode will be set
+ *
+ *	LOCKING:
+ */
+
+static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
+{
+	struct ata_device *dev = &ap->device[device];
+
+	if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+		return;
+
+	/* force PIO mode */
+	dev->flags |= ATA_DFLAG_PIO;
+
+	ata_dev_set_xfermode(ap, dev);
+
+	assert((dev->pio_mode >= XFER_PIO_3) &&
+	       (dev->pio_mode <= XFER_PIO_4));
+	printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n",
+	       ap->id, device,
+	       dev->pio_mode == 3 ? '3' : '4');
+}
+
+/**
+ *	ata_sg_clean -
+ *	@qc:
+ *
+ *	LOCKING:
+ */
+
+static void ata_sg_clean(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct scatterlist *sg = qc->sg;
+	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+
+	assert(dir == SCSI_DATA_READ || dir == SCSI_DATA_WRITE);
+	assert(qc->flags & ATA_QCFLAG_SG);
+	assert(sg != NULL);
+
+	if (!cmd->use_sg)
+		assert(qc->n_elem == 1);
+
+	DPRINTK("unmapping %u sg elements\n", qc->n_elem);
+
+	if (cmd->use_sg)
+		pci_unmap_sg(ap->host_set->pdev, sg, qc->n_elem, dir);
+	else
+		pci_unmap_single(ap->host_set->pdev, sg_dma_address(&sg[0]),
+				 sg_dma_len(&sg[0]), dir);
+
+	qc->flags &= ~ATA_QCFLAG_SG;
+	qc->sg = NULL;
+}
+
+/**
+ *	ata_fill_sg -
+ *	@qc:
+ *
+ *	LOCKING:
+ *
+ */
+void ata_fill_sg(struct ata_queued_cmd *qc)
+{
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	unsigned int idx, nelem;
+
+	assert(sg != NULL);
+	assert(qc->n_elem > 0);
+
+	idx = 0;
+	for (nelem = qc->n_elem; nelem; nelem--,sg++) {
+		u32 addr, boundary;
+		u32 sg_len, len;
+
+		/* determine if physical DMA addr spans 64K boundary.
+		 * Note h/w doesn't support 64-bit, so we unconditionally
+		 * truncate dma_addr_t to u32.
+		 */
+		addr = (u32) sg_dma_address(sg);
+		sg_len = sg_dma_len(sg);
+
+		while (sg_len) {
+			boundary = (addr & ~0xffff) + (0xffff + 1);
+			len = sg_len;
+			if ((addr + sg_len) > boundary)
+				len = boundary - addr;
+
+			ap->prd[idx].addr = cpu_to_le32(addr);
+			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
+			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+
+			idx++;
+			sg_len -= len;
+			addr += len;
+		}
+	}
+
+	if (idx)
+		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+}
+
+/**
+ *	ata_sg_setup_one -
+ *	@qc:
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *
+ */
+
+static int ata_sg_setup_one(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+	struct scatterlist *sg = qc->sg;
+	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
+	dma_addr_t dma_address;
+
+	assert(sg == &qc->sgent);
+	assert(qc->n_elem == 1);
+
+	sg->address = cmd->request_buffer;
+	sg->page = virt_to_page(cmd->request_buffer);
+	sg->offset = (unsigned long) cmd->request_buffer & ~PAGE_MASK;
+	sg_dma_len(sg) = cmd->request_bufflen;
+
+	if (!have_sg)
+		return 0;
+
+	dma_address = pci_map_single(ap->host_set->pdev, cmd->request_buffer,
+				     cmd->request_bufflen, dir);
+
+	sg_dma_address(sg) = dma_address;
+
+	DPRINTK("mapped buffer of %d bytes for %s\n", cmd->request_bufflen,
+		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+	return 0;
+}
+
+/**
+ *	ata_sg_setup -
+ *	@qc:
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *
+ */
+
+static int ata_sg_setup(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct scatterlist *sg;
+	int n_elem;
+	unsigned int have_sg = (qc->flags & ATA_QCFLAG_SG);
+
+	VPRINTK("ENTER, ata%u, use_sg %d\n", ap->id, cmd->use_sg);
+	assert(cmd->use_sg > 0);
+
+	sg = (struct scatterlist *)cmd->request_buffer;
+	if (have_sg) {
+		int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
+		n_elem = pci_map_sg(ap->host_set->pdev, sg, cmd->use_sg, dir);
+		if (n_elem < 1)
+			return -1;
+		DPRINTK("%d sg elements mapped\n", n_elem);
+	} else {
+		n_elem = cmd->use_sg;
+	}
+	qc->n_elem = n_elem;
+
+	return 0;
+}
+
+/**
+ *	ata_pio_poll -
+ *	@ap:
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+static unsigned long ata_pio_poll(struct ata_port *ap)
+{
+	u8 status;
+	unsigned int poll_state = PIO_ST_UNKNOWN;
+	unsigned int reg_state = PIO_ST_UNKNOWN;
+	const unsigned int tmout_state = PIO_ST_TMOUT;
+
+	switch (ap->pio_task_state) {
+	case PIO_ST:
+	case PIO_ST_POLL:
+		poll_state = PIO_ST_POLL;
+		reg_state = PIO_ST;
+		break;
+	case PIO_ST_LAST:
+	case PIO_ST_LAST_POLL:
+		poll_state = PIO_ST_LAST_POLL;
+		reg_state = PIO_ST_LAST;
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	status = ata_chk_status(ap);
+	if (status & ATA_BUSY) {
+		if (time_after(jiffies, ap->pio_task_timeout)) {
+			ap->pio_task_state = tmout_state;
+			return 0;
+		}
+		ap->pio_task_state = poll_state;
+		return ATA_SHORT_PAUSE;
+	}
+
+	ap->pio_task_state = reg_state;
+	return 0;
+}
+
+/**
+ *	ata_pio_complete -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+static void ata_pio_complete (struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+	u8 drv_stat;
+
+	/*
+	 * This is purely hueristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, fall back to
+	 * PIO_ST_POLL state.
+	 */
+	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
+	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+		msleep(2);
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
+		if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+			ap->pio_task_state = PIO_ST_LAST_POLL;
+			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
+			return;
+		}
+	}
+
+	drv_stat = ata_wait_idle(ap);
+	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+		ap->pio_task_state = PIO_ST_ERR;
+		return;
+	}
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+
+	ap->pio_task_state = PIO_ST_IDLE;
+
+	ata_irq_on(ap);
+
+	ata_qc_complete(qc, drv_stat);
+}
+
+/**
+ *	ata_pio_sector -
+ *	@ap:
+ *
+ *	LOCKING:
+ */
+
+static void ata_pio_sector(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc;
+	struct scatterlist *sg;
+	struct scsi_cmnd *cmd;
+	unsigned char *buf;
+	u8 status;
+
+	/*
+	 * This is purely hueristic.  This is a fast path.
+	 * Sometimes when we enter, BSY will be cleared in
+	 * a chk-status or two.  If not, the drive is probably seeking
+	 * or something.  Snooze for a couple msecs, then
+	 * chk-status again.  If still busy, fall back to
+	 * PIO_ST_POLL state.
+	 */
+	status = ata_busy_wait(ap, ATA_BUSY, 5);
+	if (status & ATA_BUSY) {
+		msleep(2);
+		status = ata_busy_wait(ap, ATA_BUSY, 10);
+		if (status & ATA_BUSY) {
+			ap->pio_task_state = PIO_ST_POLL;
+			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
+			return;
+		}
+	}
+
+	/* handle BSY=0, DRQ=0 as error */
+	if ((status & ATA_DRQ) == 0) {
+		ap->pio_task_state = PIO_ST_ERR;
+		return;
+	}
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+
+	cmd = qc->scsicmd;
+	sg = qc->sg;
+
+	if (qc->cursect == (qc->nsect - 1))
+		ap->pio_task_state = PIO_ST_LAST;
+
+	buf = kmap(sg[qc->cursg].page) +
+	      sg[qc->cursg].offset + (qc->cursg_ofs * ATA_SECT_SIZE);
+
+	qc->cursect++;
+	qc->cursg_ofs++;
+
+	if (cmd->use_sg)
+		if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
+			qc->cursg++;
+			qc->cursg_ofs = 0;
+		}
+
+	DPRINTK("data %s, drv_stat 0x%X\n",
+		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
+		status);
+
+	/* do the actual data transfer */
+	/* FIXME: mmio-ize */
+	if (qc->tf.flags & ATA_TFLAG_WRITE)
+		outsl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
+	else
+		insl(ap->ioaddr.data_addr, buf, ATA_SECT_DWORDS);
+
+	kunmap(sg[qc->cursg].page);
+}
+
+static void ata_pio_task(void *_data)
+{
+	struct ata_port *ap = _data;
+	unsigned long timeout = 0;
+
+	switch (ap->pio_task_state) {
+	case PIO_ST:
+		ata_pio_sector(ap);
+		break;
+
+	case PIO_ST_LAST:
+		ata_pio_complete(ap);
+		break;
+
+	case PIO_ST_POLL:
+	case PIO_ST_LAST_POLL:
+		timeout = ata_pio_poll(ap);
+		break;
+
+	case PIO_ST_TMOUT:
+		printk(KERN_ERR "ata%d: FIXME: PIO_ST_TMOUT\n", /* FIXME */
+		       ap->id);
+		timeout = 11 * HZ;
+		break;
+
+	case PIO_ST_ERR:
+		printk(KERN_ERR "ata%d: FIXME: PIO_ST_ERR\n", /* FIXME */
+		       ap->id);
+		timeout = 11 * HZ;
+		break;
+	}
+
+	if (timeout) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(timeout);
+	}
+
+	if ((ap->pio_task_state != PIO_ST_IDLE) &&
+	    (ap->pio_task_state != PIO_ST_TMOUT) &&
+	    (ap->pio_task_state != PIO_ST_ERR))
+		schedule_task(&ap->pio_task);
+}
+
+/**
+ *	ata_eng_timeout - Handle timeout of queued command
+ *	@ap: Port on which timed-out command is active
+ *
+ *	Some part of the kernel (currently, only the SCSI layer)
+ *	has noticed that the active command on port @ap has not
+ *	completed after a specified length of time.  Handle this
+ *	condition by disabling DMA (if necessary) and completing
+ *	transactions, with error if necessary.
+ *
+ *	This also handles the case of the "lost interrupt", where
+ *	for some reason (possibly hardware bug, possibly driver bug)
+ *	an interrupt was not delivered to the driver, even though the
+ *	transaction completed successfully.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ */
+
+void ata_eng_timeout(struct ata_port *ap)
+{
+	u8 host_stat, drv_stat;
+	struct ata_queued_cmd *qc;
+
+	DPRINTK("ENTER\n");
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+		goto out;
+	}
+
+	/* hack alert!  We cannot use the supplied completion
+	 * function from inside the ->eh_strategy_handler() thread.
+	 * libata is the only user of ->eh_strategy_handler() in
+	 * any kernel, so the default scsi_done() assumes it is
+	 * not being called from the SCSI EH.
+	 */
+	qc->scsidone = scsi_finish_command;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		if (ap->flags & ATA_FLAG_MMIO) {
+			void *mmio = (void *) ap->ioaddr.bmdma_addr;
+			host_stat = readb(mmio + ATA_DMA_STATUS);
+		} else
+			host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+		printk(KERN_ERR "ata%u: DMA timeout, stat 0x%x\n",
+		       ap->id, host_stat);
+
+		ata_dma_complete(qc, host_stat);
+		break;
+
+	case ATA_PROT_NODATA:
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat);
+
+		ata_qc_complete(qc, drv_stat);
+		break;
+
+	default:
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat);
+
+		ata_qc_complete(qc, drv_stat);
+		break;
+	}
+
+out:
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_qc_new - Request an available ATA command, for queueing
+ *	@ap: Port associated with device @dev
+ *	@dev: Device from whom we request an available command structure
+ *
+ *	LOCKING:
+ */
+
+static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
+{
+	struct ata_queued_cmd *qc = NULL;
+	unsigned int i;
+
+	for (i = 0; i < ATA_MAX_QUEUE; i++)
+		if (!test_and_set_bit(i, &ap->qactive)) {
+			qc = ata_qc_from_tag(ap, i);
+			break;
+		}
+
+	if (qc)
+		qc->tag = i;
+
+	return qc;
+}
+
+/**
+ *	ata_qc_new_init - Request an available ATA command, and initialize it
+ *	@ap: Port associated with device @dev
+ *	@dev: Device from whom we request an available command structure
+ *
+ *	LOCKING:
+ */
+
+struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
+				      struct ata_device *dev)
+{
+	struct ata_queued_cmd *qc;
+
+	qc = ata_qc_new(ap);
+	if (qc) {
+		qc->sg = NULL;
+		qc->flags = 0;
+		qc->scsicmd = NULL;
+		qc->ap = ap;
+		qc->dev = dev;
+		qc->cursect = qc->cursg = qc->cursg_ofs = 0;
+		qc->nsect = 0;
+
+		ata_tf_init(ap, &qc->tf, dev->devno);
+
+		if (likely((dev->flags & ATA_DFLAG_PIO) == 0))
+			qc->flags |= ATA_QCFLAG_DMA;
+		if (dev->flags & ATA_DFLAG_LBA48)
+			qc->tf.flags |= ATA_TFLAG_LBA48;
+	}
+
+	return qc;
+}
+
+/**
+ *	ata_qc_complete - Complete an active ATA command
+ *	@qc: Command to complete
+ *	@drv_stat: ATA status register contents
+ *
+ *	LOCKING:
+ *
+ */
+
+void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+{
+	struct ata_port *ap = qc->ap;
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	unsigned int tag, do_clear = 0;
+
+	assert(qc != NULL);	/* ata_qc_from_tag _might_ return NULL */
+	assert(qc->flags & ATA_QCFLAG_ACTIVE);
+
+	if (likely(qc->flags & ATA_QCFLAG_SG))
+		ata_sg_clean(qc);
+
+	if (cmd) {
+		if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+			if (is_atapi_taskfile(&qc->tf))
+				cmd->result = SAM_STAT_CHECK_CONDITION;
+			else
+				ata_to_sense_error(qc);
+		} else {
+			cmd->result = SAM_STAT_GOOD;
+		}
+
+		qc->scsidone(cmd);
+	}
+
+	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	tag = qc->tag;
+	if (likely(ata_tag_valid(tag))) {
+		if (tag == ap->active_tag)
+			ap->active_tag = ATA_TAG_POISON;
+		qc->tag = ATA_TAG_POISON;
+		do_clear = 1;
+	}
+
+	if (qc->waiting)
+		complete(qc->waiting);
+
+	if (likely(do_clear))
+		clear_bit(tag, &ap->qactive);
+}
+
+/**
+ *	ata_qc_issue - issue taskfile to device
+ *	@qc: command to issue to device
+ *
+ *	Prepare an ATA command to submission to device.
+ *	This includes mapping the data into a DMA-able
+ *	area, filling in the S/G table, and finally
+ *	writing the taskfile to hardware, starting the command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, negative on error.
+ */
+
+int ata_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	if (qc->flags & ATA_QCFLAG_SG) {
+		/* set up SG table */
+		if (cmd->use_sg) {
+			if (ata_sg_setup(qc))
+				goto err_out;
+		} else {
+			if (ata_sg_setup_one(qc))
+				goto err_out;
+		}
+
+		ap->ops->fill_sg(qc);
+	}
+
+	qc->ap->active_tag = qc->tag;
+	qc->flags |= ATA_QCFLAG_ACTIVE;
+
+	return ata_qc_issue_prot(qc);
+
+err_out:
+	return -1;
+}
+
+/**
+ *	ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
+ *	@qc: command to issue to device
+ *
+ *	Using various libata functions and hooks, this function
+ *	starts an ATA command.  ATA commands are grouped into
+ *	classes called "protocols", and issuing each type of protocol
+ *	is slightly different.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, negative on error.
+ */
+
+static int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	ata_dev_select(ap, qc->dev->devno, 1, 0);
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_NODATA:
+		ata_tf_to_host_nolock(ap, &qc->tf);
+		break;
+
+	case ATA_PROT_DMA:
+		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
+		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
+		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
+		break;
+
+	case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
+		ata_qc_set_polling(qc);
+		ata_tf_to_host_nolock(ap, &qc->tf);
+		ap->pio_task_state = PIO_ST;
+		schedule_task(&ap->pio_task);
+		break;
+
+	case ATA_PROT_ATAPI:
+		ata_tf_to_host_nolock(ap, &qc->tf);
+		schedule_task(&ap->packet_task);
+		break;
+
+	case ATA_PROT_ATAPI_DMA:
+		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
+		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
+		schedule_task(&ap->packet_task);
+		break;
+
+	default:
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 host_stat, dmactl;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+
+	/* load PRD table addr. */
+	mb();	/* make sure PRD table writes are visible to controller */
+	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+	/* specify data direction, triple-check start bit is clear */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+	if (!rw)
+		dmactl |= ATA_DMA_WR;
+	writeb(dmactl, mmio + ATA_DMA_CMD);
+
+	/* clear interrupt, error bits */
+	host_stat = readb(mmio + ATA_DMA_STATUS);
+	writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, mmio + ATA_DMA_STATUS);
+
+	/* issue r/w command */
+	ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *	ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	u8 dmactl;
+
+	/* start host DMA transaction */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+
+	/* Strictly, one may wish to issue a readb() here, to
+	 * flush the mmio write.  However, control also passes
+	 * to the hardware at this point, and it will interrupt
+	 * us when we are to resume control.  So, in effect,
+	 * we don't care when the mmio write flushes.
+	 * Further, a read of the DMA status register _immediately_
+	 * following the write may not be what certain flaky hardware
+	 * is expected, so I think it is best to not add a readb()
+	 * without first all the MMIO ATA cards/mobos.
+	 * Or maybe I'm just being paranoid.
+	 */
+}
+
+/**
+ *	ata_bmdma_setup_pio - Set up PCI IDE BMDMA transaction (PIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 host_stat, dmactl;
+
+	/* load PRD table addr. */
+	outl(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
+
+	/* specify data direction, triple-check start bit is clear */
+	dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+	if (!rw)
+		dmactl |= ATA_DMA_WR;
+	outb(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+
+	/* clear interrupt, error bits */
+	host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+	     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+
+	/* issue r/w command */
+	ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *	ata_bmdma_start_pio - Start a PCI IDE BMDMA transaction (PIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	u8 dmactl;
+
+	/* start host DMA transaction */
+	dmactl = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+	outb(dmactl | ATA_DMA_START,
+	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+}
+
+/**
+ *	ata_dma_complete - Complete an active ATA BMDMA command
+ *	@qc: Command to complete
+ *	@host_stat: BMDMA status register contents
+ *
+ *	LOCKING:
+ */
+
+static void ata_dma_complete(struct ata_queued_cmd *qc, u8 host_stat)
+{
+	struct ata_port *ap = qc->ap;
+	VPRINTK("ENTER\n");
+
+	if (ap->flags & ATA_FLAG_MMIO) {
+		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+
+		/* clear start/stop bit */
+		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
+		       mmio + ATA_DMA_CMD);
+
+		/* ack intr, err bits */
+		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+		       mmio + ATA_DMA_STATUS);
+	} else {
+		/* clear start/stop bit */
+		outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
+		     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
+
+		/* ack intr, err bits */
+		outb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
+		     ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+	}
+
+
+	/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+	ata_altstatus(ap);		/* dummy read */
+
+	DPRINTK("host %u, host_stat==0x%X, drv_stat==0x%X\n",
+		ap->id, (u32) host_stat, (u32) ata_chk_status(ap));
+
+	/* get drive status; clear intr; complete txn */
+	ata_qc_complete(qc, ata_wait_idle(ap));
+}
+
+/**
+ *	ata_host_intr - Handle host interrupt for given (port, task)
+ *	@ap: Port on which interrupt arrived (possibly...)
+ *	@qc: Taskfile currently active in engine
+ *
+ *	Handle host interrupt for given queued command.  Currently,
+ *	only DMA interrupts are handled.  All other commands are
+ *	handled via polling with interrupts disabled (nIEN bit).
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	One if interrupt was handled, zero if not (shared irq).
+ */
+
+inline unsigned int ata_host_intr (struct ata_port *ap,
+				   struct ata_queued_cmd *qc)
+{
+	u8 status, host_stat;
+	unsigned int handled = 0;
+
+	switch (qc->tf.protocol) {
+
+	/* BMDMA completion */
+	case ATA_PROT_DMA:
+	case ATA_PROT_ATAPI_DMA:
+		if (ap->flags & ATA_FLAG_MMIO) {
+			void *mmio = (void *) ap->ioaddr.bmdma_addr;
+			host_stat = readb(mmio + ATA_DMA_STATUS);
+		} else
+			host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+		VPRINTK("BUS_DMA (host_stat 0x%X)\n", host_stat);
+
+		if (!(host_stat & ATA_DMA_INTR)) {
+			ap->stats.idle_irq++;
+			break;
+		}
+
+		ata_dma_complete(qc, host_stat);
+		handled = 1;
+		break;
+
+	/* command completion, but no data xfer */
+	/* FIXME: a shared interrupt _will_ cause a non-data command
+	 * to be completed prematurely, with an error.
+	 *
+	 * This doesn't matter right now, since we aren't sending
+	 * non-data commands down this pipe except in development
+	 * situations.
+	 */
+	case ATA_PROT_ATAPI:
+	case ATA_PROT_NODATA:
+		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+		ata_qc_complete(qc, status);
+		handled = 1;
+		break;
+
+	default:
+		ap->stats.idle_irq++;
+
+#ifdef ATA_IRQ_TRAP
+		if ((ap->stats.idle_irq % 1000) == 0) {
+			handled = 1;
+			ata_irq_ack(ap, 0); /* debug trap */
+			printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
+		}
+#endif
+		break;
+	}
+
+	return handled;
+}
+
+/**
+ *	ata_interrupt - Default ATA host interrupt handler
+ *	@irq: irq line
+ *	@dev_instance: pointer to our host information structure
+ *	@regs: unused
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	unsigned int i;
+	unsigned int handled = 0;
+	unsigned long flags;
+
+	/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
+	spin_lock_irqsave(&host_set->lock, flags);
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap;
+
+		ap = host_set->ports[i];
+		if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			struct ata_queued_cmd *qc;
+
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+				handled += ata_host_intr(ap, qc);
+		}
+	}
+
+	spin_unlock_irqrestore(&host_set->lock, flags);
+
+	return IRQ_RETVAL(handled);
+}
+
+/**
+ *	ata_thread_iter -
+ *	@ap:
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+static unsigned long ata_thread_iter(struct ata_port *ap)
+{
+	long timeout = 0;
+
+	DPRINTK("ata%u: thr_state %s\n",
+		ap->id, ata_thr_state_name(ap->thr_state));
+
+	switch (ap->thr_state) {
+	case THR_UNKNOWN:
+		ap->thr_state = THR_PORT_RESET;
+		break;
+
+	case THR_PROBE_START:
+		ap->thr_state = THR_PORT_RESET;
+		break;
+
+	case THR_PORT_RESET:
+		ata_port_reset(ap);
+		break;
+
+	case THR_PROBE_SUCCESS:
+		up(&ap->probe_sem);
+		ap->thr_state = THR_IDLE;
+		break;
+
+	case THR_PROBE_FAILED:
+		up(&ap->probe_sem);
+		ap->thr_state = THR_AWAIT_DEATH;
+		break;
+
+	case THR_AWAIT_DEATH:
+	case THR_IDLE:
+		timeout = -1;
+		break;
+
+	default:
+		printk(KERN_DEBUG "ata%u: unknown thr state %s\n",
+		       ap->id, ata_thr_state_name(ap->thr_state));
+		break;
+	}
+
+	DPRINTK("ata%u: new thr_state %s, returning %ld\n",
+		ap->id, ata_thr_state_name(ap->thr_state), timeout);
+	return timeout;
+}
+
+/**
+ *	atapi_packet_task - Write CDB bytes to hardware
+ *	@_data: Port to which ATAPI device is attached.
+ *
+ *	When device has indicated its readiness to accept
+ *	a CDB, this function is called.  Send the CDB.
+ *	If DMA is to be performed, exit immediately.
+ *	Otherwise, we are in polling mode, so poll
+ *	status under operation succeeds or fails.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ */
+
+static void atapi_packet_task(void *_data)
+{
+	struct ata_port *ap = _data;
+	struct ata_queued_cmd *qc;
+	u8 status;
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	assert(qc != NULL);
+	assert(qc->flags & ATA_QCFLAG_ACTIVE);
+
+	/* sleep-wait for BSY to clear */
+	DPRINTK("busy wait\n");
+	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
+		goto err_out;
+
+	/* make sure DRQ is set */
+	status = ata_chk_status(ap);
+	if ((status & ATA_DRQ) == 0)
+		goto err_out;
+
+	/* send SCSI cdb */
+	/* FIXME: mmio-ize */
+	DPRINTK("send cdb\n");
+	outsl(ap->ioaddr.data_addr,
+	      qc->scsicmd->cmnd, ap->host->max_cmd_len / 4);
+
+	/* if we are DMA'ing, irq handler takes over from here */
+	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
+		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
+
+	/* non-data commands are also handled via irq */
+	else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) {
+		/* do nothing */
+	}
+
+	/* PIO commands are handled by polling */
+	else {
+		ap->pio_task_state = PIO_ST;
+		schedule_task(&ap->pio_task);
+	}
+
+	return;
+
+err_out:
+	ata_qc_complete(qc, ATA_ERR);
+}
+
+int ata_port_start (struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+
+	ap->prd = pci_alloc_consistent(pdev, ATA_PRD_TBL_SZ, &ap->prd_dma);
+	if (!ap->prd)
+		return -ENOMEM;
+
+	DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
+
+	return 0;
+}
+
+void ata_port_stop (struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+
+	pci_free_consistent(pdev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+}
+
+static void ata_probe_task(void *_data)
+{
+	struct ata_port *ap = _data;
+	long timeout;
+
+	timeout = ata_thread_iter(ap);
+	if (timeout < 0)
+		return;
+
+	if (timeout > 0) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(timeout);
+	}
+
+	schedule_task(&ap->probe_task);
+}
+
+/**
+ *	ata_host_remove - Unregister SCSI host structure with upper layers
+ *	@ap: Port to unregister
+ *	@do_unregister: 1 if we fully unregister, 0 to just stop the port
+ *
+ *	LOCKING:
+ */
+
+static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
+{
+	struct Scsi_Host *sh = ap->host;
+
+	DPRINTK("ENTER\n");
+
+	if (do_unregister)
+		scsi_unregister(sh);
+
+	ap->ops->port_stop(ap);
+}
+
+/**
+ *	ata_host_init - Initialize an ata_port structure
+ *	@ap: Structure to initialize
+ *	@host: associated SCSI mid-layer structure
+ *	@host_set: Collection of hosts to which @ap belongs
+ *	@ent: Probe information provided by low-level driver
+ *	@port_no: Port number associated with this ata_port
+ *
+ *	LOCKING:
+ *
+ */
+
+static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
+			  struct ata_host_set *host_set,
+			  struct ata_probe_ent *ent, unsigned int port_no)
+{
+	unsigned int i;
+
+	host->max_id = 16;
+	host->max_lun = 1;
+	host->max_channel = 1;
+	host->unique_id = ata_unique_id++;
+	host->max_cmd_len = 12;
+	host->pci_dev = ent->pdev;
+
+	ap->flags = ATA_FLAG_PORT_DISABLED;
+	ap->id = host->unique_id;
+	ap->host = host;
+	ap->ctl = ATA_DEVCTL_OBS;
+	ap->host_set = host_set;
+	ap->port_no = port_no;
+	ap->pio_mask = ent->pio_mask;
+	ap->udma_mask = ent->udma_mask;
+	ap->flags |= ent->host_flags;
+	ap->ops = ent->port_ops;
+	ap->thr_state = THR_PROBE_START;
+	ap->cbl = ATA_CBL_NONE;
+	ap->device[0].flags = ATA_DFLAG_MASTER;
+	ap->active_tag = ATA_TAG_POISON;
+	ap->last_ctl = 0xFF;
+
+	INIT_TQUEUE(&ap->packet_task, atapi_packet_task, ap);
+	INIT_TQUEUE(&ap->pio_task, ata_pio_task, ap);
+	INIT_TQUEUE(&ap->probe_task, ata_probe_task, ap);
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		ap->device[i].devno = i;
+
+	init_MUTEX_LOCKED(&ap->probe_sem);
+
+#ifdef ATA_IRQ_TRAP
+	ap->stats.unhandled_irq = 1;
+	ap->stats.idle_irq = 1;
+#endif
+
+	memcpy(&ap->ioaddr, &ent->port[port_no], sizeof(struct ata_ioports));
+}
+
+/**
+ *	ata_host_add - Attach low-level ATA driver to system
+ *	@ent: Information provided by low-level driver
+ *	@host_set: Collections of ports to which we add
+ *	@port_no: Port number associated with this host
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+static struct ata_port * ata_host_add(struct ata_probe_ent *ent,
+				      struct ata_host_set *host_set,
+				      unsigned int port_no)
+{
+	struct Scsi_Host *host;
+	struct ata_port *ap;
+	int rc;
+
+	DPRINTK("ENTER\n");
+	host = scsi_register(ent->sht, sizeof(struct ata_port));
+	if (!host)
+		return NULL;
+
+	ap = (struct ata_port *) &host->hostdata[0];
+
+	ata_host_init(ap, host, host_set, ent, port_no);
+
+	rc = ap->ops->port_start(ap);
+	if (rc)
+		goto err_out;
+
+	return ap;
+
+err_out:
+	scsi_unregister(host);
+	return NULL;
+}
+
+/**
+ *	ata_device_add -
+ *	@ent:
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+int ata_device_add(struct ata_probe_ent *ent)
+{
+	unsigned int count = 0, i;
+	struct pci_dev *pdev = ent->pdev;
+	struct ata_host_set *host_set;
+
+	DPRINTK("ENTER\n");
+	/* alloc a container for our list of ATA ports (buses) */
+	host_set = kmalloc(sizeof(struct ata_host_set) +
+			   (ent->n_ports * sizeof(void *)), GFP_KERNEL);
+	if (!host_set)
+		return 0;
+	memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *)));
+	spin_lock_init(&host_set->lock);
+
+	host_set->pdev = pdev;
+	host_set->n_ports = ent->n_ports;
+	host_set->irq = ent->irq;
+	host_set->mmio_base = ent->mmio_base;
+	host_set->private_data = ent->private_data;
+
+	/* register each port bound to this device */
+	for (i = 0; i < ent->n_ports; i++) {
+		struct ata_port *ap;
+
+		ap = ata_host_add(ent, host_set, i);
+		if (!ap)
+			goto err_out;
+
+		host_set->ports[i] = ap;
+
+		/* print per-port info to dmesg */
+		printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
+				 "bmdma 0x%lX irq %lu\n",
+			ap->id,
+			ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
+			ata_udma_string(ent->udma_mask),
+	       		ap->ioaddr.cmd_addr,
+	       		ap->ioaddr.ctl_addr,
+	       		ap->ioaddr.bmdma_addr,
+	       		ent->irq);
+
+		count++;
+	}
+
+	if (!count) {
+		kfree(host_set);
+		return 0;
+	}
+
+	/* obtain irq, that is shared between channels */
+	if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
+			DRV_NAME, host_set))
+		goto err_out;
+
+	/* perform each probe synchronously */
+	DPRINTK("probe begin\n");
+	for (i = 0; i < count; i++) {
+		struct ata_port *ap;
+
+		ap = host_set->ports[i];
+
+		DPRINTK("ata%u: probe begin\n", ap->id);
+		schedule_task(&ap->probe_task);		/* start probe */
+
+		DPRINTK("ata%u: probe-wait begin\n", ap->id);
+		down(&ap->probe_sem);	/* wait for end */
+
+		DPRINTK("ata%u: probe-wait end\n", ap->id);
+	}
+
+	pci_set_drvdata(pdev, host_set);
+
+	VPRINTK("EXIT, returning %u\n", ent->n_ports);
+	return ent->n_ports; /* success */
+
+err_out:
+	for (i = 0; i < count; i++) {
+		ata_host_remove(host_set->ports[i], 1);
+	}
+	kfree(host_set);
+	VPRINTK("EXIT, returning 0\n");
+	return 0;
+}
+
+/**
+ *	ata_scsi_detect -
+ *	@sht:
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+int ata_scsi_detect(Scsi_Host_Template *sht)
+{
+	struct list_head *node;
+	struct ata_probe_ent *ent;
+	int count = 0;
+
+	VPRINTK("ENTER\n");
+
+	sht->use_new_eh_code = 1;	/* IORL hack, part deux */
+
+	spin_lock(&ata_module_lock);
+	while (!list_empty(&ata_probe_list)) {
+		node = ata_probe_list.next;
+		ent = list_entry(node, struct ata_probe_ent, node);
+		list_del(node);
+
+		spin_unlock(&ata_module_lock);
+
+		count += ata_device_add(ent);
+		kfree(ent);
+
+		spin_lock(&ata_module_lock);
+	}
+	spin_unlock(&ata_module_lock);
+
+	VPRINTK("EXIT, returning %d\n", count);
+	return count;
+}
+
+/**
+ *	ata_scsi_release - SCSI layer callback hook for host unload
+ *	@host: libata host to be unloaded
+ *
+ *	Performs all duties necessary to shut down a libata port...
+ *	Kill port kthread, disable port, and release resources.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer.
+ *
+ *	RETURNS:
+ *	One.
+ */
+
+int ata_scsi_release(struct Scsi_Host *host)
+{
+	struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
+
+	DPRINTK("ENTER\n");
+
+	ap->ops->port_disable(ap);
+	ata_host_remove(ap, 0);
+
+	DPRINTK("EXIT\n");
+	return 1;
+}
+
+/**
+ *	ata_std_ports - initialize ioaddr with standard port offsets.
+ *	@ioaddr: IO address structure to be initialized
+ */
+void ata_std_ports(struct ata_ioports *ioaddr)
+{
+	ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
+	ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR;
+	ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE;
+	ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT;
+	ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL;
+	ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM;
+	ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH;
+	ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE;
+	ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS;
+	ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
+}
+
+/**
+ *	ata_pci_init_one - Initialize/register PCI IDE host controller
+ *	@pdev: Controller to be initialized
+ *	@port_info: Information from low-level host driver
+ *	@n_ports: Number of ports attached to host controller
+ *
+ *	LOCKING:
+ *	Inherited from PCI layer (may sleep).
+ *
+ *	RETURNS:
+ *
+ */
+
+int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
+		      unsigned int n_ports)
+{
+	struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
+	struct ata_port_info *port0, *port1;
+	u8 tmp8, mask;
+	unsigned int legacy_mode = 0;
+	int rc;
+
+	DPRINTK("ENTER\n");
+
+	port0 = port_info[0];
+	if (n_ports > 1)
+		port1 = port_info[1];
+	else
+		port1 = port0;
+
+	if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
+		/* TODO: support transitioning to native mode? */
+		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
+		mask = (1 << 2) | (1 << 0);
+		if ((tmp8 & mask) != mask)
+			legacy_mode = (1 << 3);
+	}
+
+	/* FIXME... */
+	if ((!legacy_mode) && (n_ports > 1)) {
+		printk(KERN_ERR "ata: BUG: native mode, n_ports > 1\n");
+		return -EINVAL;
+	}
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	if (legacy_mode) {
+		if (!request_region(0x1f0, 8, "libata"))
+			printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+		else
+			legacy_mode |= (1 << 0);
+
+		if (!request_region(0x170, 8, "libata"))
+			printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+		else
+			legacy_mode |= (1 << 1);
+	}
+
+	/* we have legacy mode, but all ports are unavailable */
+	if (legacy_mode == (1 << 3)) {
+		rc = -EBUSY;
+		goto err_out_regions;
+	}
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	if (legacy_mode) {
+		probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+		if (!probe_ent2) {
+			rc = -ENOMEM;
+			goto err_out_free_ent;
+		}
+
+		memset(probe_ent2, 0, sizeof(*probe_ent));
+		probe_ent2->pdev = pdev;
+		INIT_LIST_HEAD(&probe_ent2->node);
+	}
+
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+	probe_ent->sht = port0->sht;
+	probe_ent->host_flags = port0->host_flags;
+	probe_ent->pio_mask = port0->pio_mask;
+	probe_ent->udma_mask = port0->udma_mask;
+	probe_ent->port_ops = port0->port_ops;
+
+	if (legacy_mode) {
+		probe_ent->port[0].cmd_addr = 0x1f0;
+		probe_ent->port[0].altstatus_addr =
+		probe_ent->port[0].ctl_addr = 0x3f6;
+		probe_ent->n_ports = 1;
+		probe_ent->irq = 14;
+		ata_std_ports(&probe_ent->port[0]);
+
+		probe_ent2->port[0].cmd_addr = 0x170;
+		probe_ent2->port[0].altstatus_addr =
+		probe_ent2->port[0].ctl_addr = 0x376;
+		probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
+		probe_ent2->n_ports = 1;
+		probe_ent2->irq = 15;
+		ata_std_ports(&probe_ent2->port[0]);
+
+		probe_ent2->sht = port1->sht;
+		probe_ent2->host_flags = port1->host_flags;
+		probe_ent2->pio_mask = port1->pio_mask;
+		probe_ent2->udma_mask = port1->udma_mask;
+		probe_ent2->port_ops = port1->port_ops;
+	} else {
+		probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+		ata_std_ports(&probe_ent->port[0]);
+		probe_ent->port[0].altstatus_addr =
+		probe_ent->port[0].ctl_addr =
+			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+
+		probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+		ata_std_ports(&probe_ent->port[1]);
+		probe_ent->port[1].altstatus_addr =
+		probe_ent->port[1].ctl_addr =
+			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+		probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+
+		probe_ent->n_ports = 2;
+		probe_ent->irq = pdev->irq;
+		probe_ent->irq_flags = SA_SHIRQ;
+	}
+
+	pci_set_master(pdev);
+
+	spin_lock(&ata_module_lock);
+	if (legacy_mode) {
+		if (legacy_mode & (1 << 0))
+			list_add_tail(&probe_ent->node, &ata_probe_list);
+		else
+			kfree(probe_ent);
+		if (legacy_mode & (1 << 1))
+			list_add_tail(&probe_ent2->node, &ata_probe_list);
+		else
+			kfree(probe_ent2);
+	} else {
+		list_add_tail(&probe_ent->node, &ata_probe_list);
+	}
+	spin_unlock(&ata_module_lock);
+
+	return 0;
+
+err_out_free_ent:
+	kfree(probe_ent);
+err_out_regions:
+	if (legacy_mode & (1 << 0))
+		release_region(0x1f0, 8);
+	if (legacy_mode & (1 << 1))
+		release_region(0x170, 8);
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+/**
+ *	ata_pci_remove_one - PCI layer callback for device removal
+ *	@pdev: PCI device that was removed
+ *
+ *	PCI layer indicates to libata via this hook that
+ *	hot-unplug or module unload event has occured.
+ *	Handle this by unregistering all objects associated
+ *	with this PCI device.  Free those objects.  Then finally
+ *	release PCI resources and disable device.
+ *
+ *	LOCKING:
+ *	Inherited from PCI layer (may sleep).
+ */
+
+void ata_pci_remove_one (struct pci_dev *pdev)
+{
+	struct ata_host_set *host_set = pci_get_drvdata(pdev);
+	struct ata_port *ap;
+	unsigned int i;
+	Scsi_Host_Template *sht;
+	int rc;
+
+	/* FIXME: this unregisters all ports attached to the
+	 * Scsi_Host_Template given.  We _might_ have multiple
+	 * templates (though we don't ATM), so this is ok... for now.
+	 */
+	ap = host_set->ports[0];
+	sht = ap->host->hostt;
+	rc = scsi_unregister_module(MODULE_SCSI_HA, sht);
+	/* FIXME: handle 'rc' failure? */
+
+	free_irq(host_set->irq, host_set);
+	if (host_set->mmio_base)
+		iounmap(host_set->mmio_base);
+	if (host_set->ports[0]->ops->host_stop)
+		host_set->ports[0]->ops->host_stop(host_set);
+
+	pci_release_regions(pdev);
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_ioports *ioaddr;
+
+		ap = host_set->ports[i];
+		ioaddr = &ap->ioaddr;
+
+		if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) {
+			if (ioaddr->cmd_addr == 0x1f0)
+				release_region(0x1f0, 8);
+			else if (ioaddr->cmd_addr == 0x170)
+				release_region(0x170, 8);
+		}
+	}
+
+	kfree(host_set);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+/**
+ *	ata_add_to_probe_list - add an entry to the list of things
+ *	to be probed.
+ *	@probe_ent: describes device to be probed.
+ *
+ *	LOCKING:
+ */
+
+void ata_add_to_probe_list(struct ata_probe_ent *probe_ent)
+{
+	spin_lock(&ata_module_lock);
+	list_add_tail(&probe_ent->node, &ata_probe_list);
+	spin_unlock(&ata_module_lock);
+}
+
+/* move to PCI subsystem */
+int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
+{
+	unsigned long tmp = 0;
+
+	switch (bits->width) {
+	case 1: {
+		u8 tmp8 = 0;
+		pci_read_config_byte(pdev, bits->reg, &tmp8);
+		tmp = tmp8;
+		break;
+	}
+	case 2: {
+		u16 tmp16 = 0;
+		pci_read_config_word(pdev, bits->reg, &tmp16);
+		tmp = tmp16;
+		break;
+	}
+	case 4: {
+		u32 tmp32 = 0;
+		pci_read_config_dword(pdev, bits->reg, &tmp32);
+		tmp = tmp32;
+		break;
+	}
+
+	default:
+		return -EINVAL;
+	}
+
+	tmp &= bits->mask;
+
+	return (tmp == bits->val) ? 1 : 0;
+}
+
+
+/**
+ *	ata_init -
+ *
+ *	LOCKING:
+ *
+ *	RETURNS:
+ *
+ */
+
+static int __init ata_init(void)
+{
+	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
+	return 0;
+}
+
+static void __exit ata_exit(void)
+{
+}
+
+module_init(ata_init);
+module_exit(ata_exit);
+
+/*
+ * libata is essentially a library of internal helper functions for
+ * low-level ATA host controller drivers.  As such, the API/ABI is
+ * likely to change as new drivers are added and updated.
+ * Do not depend on ABI/API stability.
+ */
+
+EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_std_bios_param);
+EXPORT_SYMBOL_GPL(ata_std_ports);
+EXPORT_SYMBOL_GPL(ata_device_add);
+EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(ata_eng_timeout);
+EXPORT_SYMBOL_GPL(ata_tf_load_pio);
+EXPORT_SYMBOL_GPL(ata_tf_load_mmio);
+EXPORT_SYMBOL_GPL(ata_tf_read_pio);
+EXPORT_SYMBOL_GPL(ata_tf_read_mmio);
+EXPORT_SYMBOL_GPL(ata_tf_to_fis);
+EXPORT_SYMBOL_GPL(ata_tf_from_fis);
+EXPORT_SYMBOL_GPL(ata_check_status_pio);
+EXPORT_SYMBOL_GPL(ata_check_status_mmio);
+EXPORT_SYMBOL_GPL(ata_exec_command_pio);
+EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
+EXPORT_SYMBOL_GPL(ata_port_start);
+EXPORT_SYMBOL_GPL(ata_port_stop);
+EXPORT_SYMBOL_GPL(ata_interrupt);
+EXPORT_SYMBOL_GPL(ata_fill_sg);
+EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
+EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
+EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
+EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio);
+EXPORT_SYMBOL_GPL(ata_port_probe);
+EXPORT_SYMBOL_GPL(sata_phy_reset);
+EXPORT_SYMBOL_GPL(ata_bus_reset);
+EXPORT_SYMBOL_GPL(ata_port_disable);
+EXPORT_SYMBOL_GPL(ata_pci_init_one);
+EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+EXPORT_SYMBOL_GPL(ata_scsi_error);
+EXPORT_SYMBOL_GPL(ata_scsi_detect);
+EXPORT_SYMBOL_GPL(ata_add_to_probe_list);
+EXPORT_SYMBOL_GPL(ata_scsi_release);
+EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(ata_dev_id_string);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/libata-scsi.c linux-2.4.27-rc4/drivers/scsi/libata-scsi.c
--- linux-2.4.26/drivers/scsi/libata-scsi.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/libata-scsi.c	2004-07-30 16:25:45.000000000 +0000
@@ -0,0 +1,1186 @@
+/*
+   libata-scsi.c - helper library for ATA
+
+   Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+   Copyright 2003-2004 Jeff Garzik
+
+   The contents of this file are subject to the Open
+   Software License version 1.1 that can be found at
+   http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+   by reference.
+
+   Alternatively, the contents of this file may be used under the terms
+   of the GNU General Public License version 2 (the "GPL") as distributed
+   in the kernel source COPYING file, in which case the provisions of
+   the GPL are applicable instead of the above.  If you wish to allow
+   the use of your version of this file only under the terms of the
+   GPL and not to allow others to use your version of this file under
+   the OSL, indicate your decision by deleting the provisions above and
+   replace them with the notice and other provisions required by the GPL.
+   If you do not delete the provisions above, a recipient may use your
+   version of this file under either the OSL or the GPL.
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/blk.h>
+#include <linux/blkdev.h>
+#include <linux/spinlock.h>
+#include <scsi/scsi.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include "sd.h"
+#include <linux/libata.h>
+
+#include "libata.h"
+
+typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, u8 *scsicmd);
+static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
+			      struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *));
+
+
+/**
+ *	ata_std_bios_param - generic bios head/sector/cylinder calculator used by sd.
+ *	@disk: SCSI device for which BIOS geometry is to be determined
+ *	@dev: device major/minor
+ *	@ip: location to which geometry will be output
+ *
+ *	Generic bios head/sector/cylinder calculator
+ *	used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS)
+ *	mapping. Some situations may arise where the disk is not
+ *	bootable if this is not used.
+ *
+ *	LOCKING:
+ *	Defined by the SCSI layer.  We don't really care.
+ *
+ *	RETURNS:
+ *	Zero.
+ */
+int ata_std_bios_param(Disk * disk,	/* SCSI disk */
+		       kdev_t dev,	/* Device major, minor */
+		  int *ip /* Heads, sectors, cylinders in that order */ )
+{
+	ip[0] = 255;
+	ip[1] = 63;
+	ip[2] = disk->capacity / (ip[0] * ip[1]);
+
+	return 0;
+}
+
+
+/**
+ *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
+ *	@ap: ATA port to which the new command is attached
+ *	@dev: ATA device to which the new command is attached
+ *	@cmd: SCSI command that originated this ATA command
+ *	@done: SCSI command completion function
+ *
+ *	Obtain a reference to an unused ata_queued_cmd structure,
+ *	which is the basic libata structure representing a single
+ *	ATA command sent to the hardware.
+ *
+ *	If a command was available, fill in the SCSI-specific
+ *	portions of the structure with information on the
+ *	current command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Command allocated, or %NULL if none available.
+ */
+struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
+				       struct ata_device *dev,
+				       struct scsi_cmnd *cmd,
+				       void (*done)(struct scsi_cmnd *))
+{
+	struct ata_queued_cmd *qc;
+
+	qc = ata_qc_new_init(ap, dev);
+	if (qc) {
+		qc->scsicmd = cmd;
+		qc->scsidone = done;
+
+		if (cmd->use_sg) {
+			qc->sg = (struct scatterlist *) cmd->request_buffer;
+			qc->n_elem = cmd->use_sg;
+		} else {
+			qc->sg = &qc->sgent;
+			qc->n_elem = 1;
+		}
+	} else {
+		cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
+		done(cmd);
+	}
+
+	return qc;
+}
+
+/**
+ *	ata_to_sense_error - convert ATA error to SCSI error
+ *	@qc: Command that we are erroring out
+ *
+ *	Converts an ATA error into a SCSI error.
+ *
+ *	Right now, this routine is laughably primitive.  We
+ *	don't even examine what ATA told us, we just look at
+ *	the command data direction, and return a fatal SCSI
+ *	sense error based on that.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_to_sense_error(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	cmd->result = SAM_STAT_CHECK_CONDITION;
+
+	cmd->sense_buffer[0] = 0x70;
+	cmd->sense_buffer[2] = MEDIUM_ERROR;
+	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
+
+	/* additional-sense-code[-qualifier] */
+	if (cmd->sc_data_direction == SCSI_DATA_READ) {
+		cmd->sense_buffer[12] = 0x11; /* "unrecovered read error" */
+		cmd->sense_buffer[13] = 0x04;
+	} else {
+		cmd->sense_buffer[12] = 0x0C; /* "write error -             */
+		cmd->sense_buffer[13] = 0x02; /*  auto-reallocation failed" */
+	}
+}
+
+/**
+ *	ata_scsi_error - SCSI layer error handler callback
+ *	@host: SCSI host on which error occurred
+ *
+ *	Handles SCSI-layer-thrown error events.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ *
+ *	RETURNS:
+ *	Zero.
+ */
+
+int ata_scsi_error(struct Scsi_Host *host)
+{
+	struct ata_port *ap;
+
+	DPRINTK("ENTER\n");
+
+	ap = (struct ata_port *) &host->hostdata[0];
+	ap->ops->eng_timeout(ap);
+
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
+/**
+ *	ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Converts any of six SCSI read/write commands into the
+ *	ATA counterpart, including starting sector (LBA),
+ *	sector count, and taking into account the device's LBA48
+ *	support.
+ *
+ *	Commands %READ_6, %READ_10, %READ_16, %WRITE_6, %WRITE_10, and
+ *	%WRITE_16 are currently supported.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct ata_taskfile *tf = &qc->tf;
+	unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
+
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf->hob_nsect = 0;
+	tf->hob_lbal = 0;
+	tf->hob_lbam = 0;
+	tf->hob_lbah = 0;
+	tf->protocol = qc->dev->xfer_protocol;
+	tf->device |= ATA_LBA;
+
+	if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
+	    scsicmd[0] == READ_16) {
+		tf->command = qc->dev->read_cmd;
+	} else {
+		tf->command = qc->dev->write_cmd;
+		tf->flags |= ATA_TFLAG_WRITE;
+	}
+
+	if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
+		if (lba48) {
+			tf->hob_nsect = scsicmd[7];
+			tf->hob_lbal = scsicmd[2];
+
+			qc->nsect = ((unsigned int)scsicmd[7] << 8) |
+					scsicmd[8];
+		} else {
+			/* if we don't support LBA48 addressing, the request
+			 * -may- be too large. */
+			if ((scsicmd[2] & 0xf0) || scsicmd[7])
+				return 1;
+
+			/* stores LBA27:24 in lower 4 bits of device reg */
+			tf->device |= scsicmd[2];
+
+			qc->nsect = scsicmd[8];
+		}
+
+		tf->nsect = scsicmd[8];
+		tf->lbal = scsicmd[5];
+		tf->lbam = scsicmd[4];
+		tf->lbah = scsicmd[3];
+
+		VPRINTK("ten-byte command\n");
+		return 0;
+	}
+
+	if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
+		qc->nsect = tf->nsect = scsicmd[4];
+		tf->lbal = scsicmd[3];
+		tf->lbam = scsicmd[2];
+		tf->lbah = scsicmd[1] & 0x1f; /* mask out reserved bits */
+
+		VPRINTK("six-byte command\n");
+		return 0;
+	}
+
+	if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
+		/* rule out impossible LBAs and sector counts */
+		if (scsicmd[2] || scsicmd[3] || scsicmd[10] || scsicmd[11])
+			return 1;
+
+		if (lba48) {
+			tf->hob_nsect = scsicmd[12];
+			tf->hob_lbal = scsicmd[6];
+			tf->hob_lbam = scsicmd[5];
+			tf->hob_lbah = scsicmd[4];
+
+			qc->nsect = ((unsigned int)scsicmd[12] << 8) |
+					scsicmd[13];
+		} else {
+			/* once again, filter out impossible non-zero values */
+			if (scsicmd[4] || scsicmd[5] || scsicmd[12] ||
+			    (scsicmd[6] & 0xf0))
+				return 1;
+
+			/* stores LBA27:24 in lower 4 bits of device reg */
+			tf->device |= scsicmd[2];
+
+			qc->nsect = scsicmd[13];
+		}
+
+		tf->nsect = scsicmd[13];
+		tf->lbal = scsicmd[9];
+		tf->lbam = scsicmd[8];
+		tf->lbah = scsicmd[7];
+
+		VPRINTK("sixteen-byte command\n");
+		return 0;
+	}
+
+	DPRINTK("no-byte command\n");
+	return 1;
+}
+
+/**
+ *	ata_scsi_translate - Translate then issue SCSI command to ATA device
+ *	@ap: ATA port to which the command is addressed
+ *	@dev: ATA device to which the command is addressed
+ *	@cmd: SCSI command to execute
+ *	@done: SCSI command completion function
+ *	@xlat_func: Actor which translates @cmd to an ATA taskfile
+ *
+ *	Our ->queuecommand() function has decided that the SCSI
+ *	command issued can be directly translated into an ATA
+ *	command, rather than handled internally.
+ *
+ *	This function sets up an ata_queued_cmd structure for the
+ *	SCSI command, and sends that ata_queued_cmd to the hardware.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
+			      struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *),
+			      ata_xlat_func_t xlat_func)
+{
+	struct ata_queued_cmd *qc;
+	u8 *scsicmd = cmd->cmnd;
+
+	VPRINTK("ENTER\n");
+
+	qc = ata_scsi_qc_new(ap, dev, cmd, done);
+	if (!qc)
+		return;
+
+	if (cmd->sc_data_direction == SCSI_DATA_READ ||
+	    cmd->sc_data_direction == SCSI_DATA_WRITE) {
+		if (unlikely(cmd->request_bufflen < 1)) {
+			printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
+			       ap->id, dev->devno);
+			goto err_out;
+		}
+
+		qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
+	}
+
+	if (xlat_func(qc, scsicmd))
+		goto err_out;
+
+	/* select device, send command to hardware */
+	if (ata_qc_issue(qc))
+		goto err_out;
+
+	VPRINTK("EXIT\n");
+	return;
+
+err_out:
+	ata_bad_cdb(cmd, done);
+	DPRINTK("EXIT - badcmd\n");
+}
+
+/**
+ *	ata_scsi_rbuf_get - Map response buffer.
+ *	@cmd: SCSI command containing buffer to be mapped.
+ *	@buf_out: Pointer to mapped area.
+ *
+ *	Maps buffer contained within SCSI command @cmd.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Length of response buffer.
+ */
+
+static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out)
+{
+	u8 *buf;
+	unsigned int buflen;
+
+	if (cmd->use_sg) {
+		struct scatterlist *sg;
+
+		sg = (struct scatterlist *) cmd->request_buffer;
+		buf = kmap_atomic(sg->page, KM_USER0) + sg->offset;
+		buflen = sg->length;
+	} else {
+		buf = cmd->request_buffer;
+		buflen = cmd->request_bufflen;
+	}
+
+	memset(buf, 0, buflen);
+	*buf_out = buf;
+	return buflen;
+}
+
+/**
+ *	ata_scsi_rbuf_put - Unmap response buffer.
+ *	@cmd: SCSI command containing buffer to be unmapped.
+ *
+ *	Unmaps response buffer contained within @cmd.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd)
+{
+	if (cmd->use_sg) {
+		struct scatterlist *sg;
+
+		sg = (struct scatterlist *) cmd->request_buffer;
+		kunmap_atomic(sg->page, KM_USER0);
+	}
+}
+
+/**
+ *	ata_scsi_rbuf_fill - wrapper for SCSI command simulators
+ *	@args: Port / device / SCSI command of interest.
+ *	@actor: Callback hook for desired SCSI command simulator
+ *
+ *	Takes care of the hard work of simulating a SCSI command...
+ *	Mapping the response buffer, calling the command's handler,
+ *	and handling the handler's return value.  This return value
+ *	indicates whether the handler wishes the SCSI command to be
+ *	completed successfully, or not.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
+		        unsigned int (*actor) (struct ata_scsi_args *args,
+			     		   u8 *rbuf, unsigned int buflen))
+{
+	u8 *rbuf;
+	unsigned int buflen, rc;
+	struct scsi_cmnd *cmd = args->cmd;
+
+	buflen = ata_scsi_rbuf_get(cmd, &rbuf);
+	rc = actor(args, rbuf, buflen);
+	ata_scsi_rbuf_put(cmd);
+
+	if (rc)
+		ata_bad_cdb(cmd, args->done);
+	else {
+		cmd->result = SAM_STAT_GOOD;
+		args->done(cmd);
+	}
+}
+
+/**
+ *	ata_scsiop_inq_std - Simulate INQUIRY command
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Returns standard device identification data associated
+ *	with non-EVPD INQUIRY command output.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+			       unsigned int buflen)
+{
+	struct ata_device *dev = args->dev;
+
+	u8 hdr[] = {
+		TYPE_DISK,
+		0,
+		0x5,	/* claim SPC-3 version compatibility */
+		2,
+		96 - 4
+	};
+
+	/* set scsi removeable (RMB) bit per ata bit */
+	if (ata_id_removeable(dev))
+		hdr[1] |= (1 << 7);
+
+	VPRINTK("ENTER\n");
+
+	memcpy(rbuf, hdr, sizeof(hdr));
+
+	if (buflen > 36) {
+		memcpy(&rbuf[8], "ATA     ", 8);
+		ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
+		ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
+		if (rbuf[32] == 0 || rbuf[32] == ' ')
+			memcpy(&rbuf[32], "n/a ", 4);
+	}
+
+	if (buflen > 63) {
+		const u8 versions[] = {
+			0x60,	/* SAM-3 (no version claimed) */
+
+			0x03,
+			0x20,	/* SBC-2 (no version claimed) */
+
+			0x02,
+			0x60	/* SPC-3 (no version claimed) */
+		};
+
+		memcpy(rbuf + 59, versions, sizeof(versions));
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_scsiop_inq_00 - Simulate INQUIRY EVPD page 0, list of pages
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Returns list of inquiry EVPD pages available.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+			      unsigned int buflen)
+{
+	const u8 pages[] = {
+		0x00,	/* page 0x00, this page */
+		0x80,	/* page 0x80, unit serial no page */
+		0x83	/* page 0x83, device ident page */
+	};
+	rbuf[3] = sizeof(pages);	/* number of supported EVPD pages */
+
+	if (buflen > 6)
+		memcpy(rbuf + 4, pages, sizeof(pages));
+
+	return 0;
+}
+
+/**
+ *	ata_scsiop_inq_80 - Simulate INQUIRY EVPD page 80, device serial number
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Returns ATA device serial number.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+			      unsigned int buflen)
+{
+	const u8 hdr[] = {
+		0,
+		0x80,			/* this page code */
+		0,
+		ATA_SERNO_LEN,		/* page len */
+	};
+	memcpy(rbuf, hdr, sizeof(hdr));
+
+	if (buflen > (ATA_SERNO_LEN + 4))
+		ata_dev_id_string(args->dev, (unsigned char *) &rbuf[4],
+				  ATA_ID_SERNO_OFS, ATA_SERNO_LEN);
+
+	return 0;
+}
+
+static const char *inq_83_str = "Linux ATA-SCSI simulator";
+
+/**
+ *	ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Returns device identification.  Currently hardcoded to
+ *	return "Linux ATA-SCSI simulator".
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+			      unsigned int buflen)
+{
+	rbuf[1] = 0x83;			/* this page code */
+	rbuf[3] = 4 + strlen(inq_83_str);	/* page len */
+
+	/* our one and only identification descriptor (vendor-specific) */
+	if (buflen > (strlen(inq_83_str) + 4 + 4)) {
+		rbuf[4 + 0] = 2;	/* code set: ASCII */
+		rbuf[4 + 3] = strlen(inq_83_str);
+		memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str));
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_scsiop_noop -
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	No operation.  Simply returns success to caller, to indicate
+ *	that the caller should successfully complete this SCSI command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
+			    unsigned int buflen)
+{
+	VPRINTK("ENTER\n");
+	return 0;
+}
+
+/**
+ *	ata_msense_push - Push data onto MODE SENSE data output buffer
+ *	@ptr_io: (input/output) Location to store more output data
+ *	@last: End of output data buffer
+ *	@buf: Pointer to BLOB being added to output buffer
+ *	@buflen: Length of BLOB
+ *
+ *	Store MODE SENSE data on an output buffer.
+ *
+ *	LOCKING:
+ *	None.
+ */
+
+static void ata_msense_push(u8 **ptr_io, const u8 *last,
+			    const u8 *buf, unsigned int buflen)
+{
+	u8 *ptr = *ptr_io;
+
+	if ((ptr + buflen - 1) > last)
+		return;
+
+	memcpy(ptr, buf, buflen);
+
+	ptr += buflen;
+
+	*ptr_io = ptr;
+}
+
+/**
+ *	ata_msense_caching - Simulate MODE SENSE caching info page
+ *	@dev: Device associated with this MODE SENSE command
+ *	@ptr_io: (input/output) Location to store more output data
+ *	@last: End of output data buffer
+ *
+ *	Generate a caching info page, which conditionally indicates
+ *	write caching to the SCSI layer, depending on device
+ *	capabilities.
+ *
+ *	LOCKING:
+ *	None.
+ */
+
+static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io,
+				       const u8 *last)
+{
+	u8 page[] = {
+		0x8,				/* page code */
+		0x12,				/* page length */
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,	/* 10 zeroes */
+		0, 0, 0, 0, 0, 0, 0, 0		/* 8 zeroes */
+	};
+
+	if (ata_id_wcache_enabled(dev))
+		page[2] |= (1 << 2);	/* write cache enable */
+	if (!ata_id_rahead_enabled(dev))
+		page[12] |= (1 << 5);	/* disable read ahead */
+
+	ata_msense_push(ptr_io, last, page, sizeof(page));
+	return sizeof(page);
+}
+
+/**
+ *	ata_msense_ctl_mode - Simulate MODE SENSE control mode page
+ *	@dev: Device associated with this MODE SENSE command
+ *	@ptr_io: (input/output) Location to store more output data
+ *	@last: End of output data buffer
+ *
+ *	Generate a generic MODE SENSE control mode page.
+ *
+ *	LOCKING:
+ *	None.
+ */
+
+static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
+{
+	const u8 page[] = {0xa, 0xa, 2, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30};
+
+	ata_msense_push(ptr_io, last, page, sizeof(page));
+	return sizeof(page);
+}
+
+/**
+ *	ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
+ *	@dev: Device associated with this MODE SENSE command
+ *	@ptr_io: (input/output) Location to store more output data
+ *	@last: End of output data buffer
+ *
+ *	Generate a generic MODE SENSE r/w error recovery page.
+ *
+ *	LOCKING:
+ *	None.
+ */
+
+static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
+{
+	const u8 page[] = {
+		0x1,			  /* page code */
+		0xa,			  /* page length */
+		(1 << 7) | (1 << 6),	  /* note auto r/w reallocation */
+		0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
+	};
+
+	ata_msense_push(ptr_io, last, page, sizeof(page));
+	return sizeof(page);
+}
+
+/**
+ *	ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Simulate MODE SENSE commands.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+				  unsigned int buflen)
+{
+	u8 *scsicmd = args->cmd->cmnd, *p, *last;
+	struct ata_device *dev = args->dev;
+	unsigned int page_control, six_byte, output_len;
+
+	VPRINTK("ENTER\n");
+
+	six_byte = (scsicmd[0] == MODE_SENSE);
+
+	/* we only support saved and current values (which we treat
+	 * in the same manner)
+	 */
+	page_control = scsicmd[2] >> 6;
+	if ((page_control != 0) && (page_control != 3))
+		return 1;
+
+	if (six_byte)
+		output_len = 4;
+	else
+		output_len = 8;
+
+	p = rbuf + output_len;
+	last = rbuf + buflen - 1;
+
+	switch(scsicmd[2] & 0x3f) {
+	case 0x01:		/* r/w error recovery */
+		output_len += ata_msense_rw_recovery(&p, last);
+		break;
+
+	case 0x08:		/* caching */
+		output_len += ata_msense_caching(dev, &p, last);
+		break;
+
+	case 0x0a: {		/* control mode */
+		output_len += ata_msense_ctl_mode(&p, last);
+		break;
+		}
+
+	case 0x3f:		/* all pages */
+		output_len += ata_msense_rw_recovery(&p, last);
+		output_len += ata_msense_caching(dev, &p, last);
+		output_len += ata_msense_ctl_mode(&p, last);
+		break;
+
+	default:		/* invalid page code */
+		return 1;
+	}
+
+	if (six_byte) {
+		output_len--;
+		rbuf[0] = output_len;
+	} else {
+		output_len -= 2;
+		rbuf[0] = output_len >> 8;
+		rbuf[1] = output_len;
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Simulate READ CAPACITY commands.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+			        unsigned int buflen)
+{
+	u64 n_sectors = args->dev->n_sectors;
+	u32 tmp;
+
+	VPRINTK("ENTER\n");
+
+	n_sectors--;		/* ATA TotalUserSectors - 1 */
+
+	tmp = n_sectors;	/* note: truncates, if lba48 */
+	if (args->cmd->cmnd[0] == READ_CAPACITY) {
+		/* sector count, 32-bit */
+		rbuf[0] = tmp >> (8 * 3);
+		rbuf[1] = tmp >> (8 * 2);
+		rbuf[2] = tmp >> (8 * 1);
+		rbuf[3] = tmp;
+
+		/* sector size */
+		tmp = ATA_SECT_SIZE;
+		rbuf[6] = tmp >> 8;
+		rbuf[7] = tmp;
+
+	} else {
+		/* sector count, 64-bit */
+		rbuf[2] = n_sectors >> (8 * 7);
+		rbuf[3] = n_sectors >> (8 * 6);
+		rbuf[4] = n_sectors >> (8 * 5);
+		rbuf[5] = n_sectors >> (8 * 4);
+		rbuf[6] = tmp >> (8 * 3);
+		rbuf[7] = tmp >> (8 * 2);
+		rbuf[8] = tmp >> (8 * 1);
+		rbuf[9] = tmp;
+
+		/* sector size */
+		tmp = ATA_SECT_SIZE;
+		rbuf[12] = tmp >> 8;
+		rbuf[13] = tmp;
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_scsiop_report_luns - Simulate REPORT LUNS command
+ *	@args: Port / device / SCSI command of interest.
+ *	@rbuf: Response buffer, to which simulated SCSI cmd output is sent.
+ *	@buflen: Response buffer length.
+ *
+ *	Simulate REPORT LUNS command.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+				   unsigned int buflen)
+{
+	VPRINTK("ENTER\n");
+	rbuf[3] = 8;	/* just one lun, LUN 0, size 8 bytes */
+
+	return 0;
+}
+
+/**
+ *	ata_scsi_badcmd - End a SCSI request with an error
+ *	@cmd: SCSI request to be handled
+ *	@done: SCSI command completion function
+ *	@asc: SCSI-defined additional sense code
+ *	@ascq: SCSI-defined additional sense code qualifier
+ *
+ *	Helper function that completes a SCSI command with
+ *	%SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
+ *	and the specified additional sense codes.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
+{
+	DPRINTK("ENTER\n");
+	cmd->result = SAM_STAT_CHECK_CONDITION;
+
+	cmd->sense_buffer[0] = 0x70;
+	cmd->sense_buffer[2] = ILLEGAL_REQUEST;
+	cmd->sense_buffer[7] = 14 - 8;	/* addnl. sense len. FIXME: correct? */
+	cmd->sense_buffer[12] = asc;
+	cmd->sense_buffer[13] = ascq;
+
+	done(cmd);
+}
+
+/**
+ *	atapi_xlat - Initialize PACKET taskfile
+ *	@qc: command structure to be initialized
+ *	@scsicmd: SCSI CDB associated with this PACKET command
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on failure.
+ */
+
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+
+	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
+		qc->tf.flags |= ATA_TFLAG_WRITE;
+		DPRINTK("direction: write\n");
+	}
+
+	qc->tf.command = ATA_CMD_PACKET;
+
+	/* no data - interrupt-driven */
+	if (cmd->sc_data_direction == SCSI_DATA_NONE)
+		qc->tf.protocol = ATA_PROT_ATAPI;
+
+	/* PIO data xfer - polling */
+	else if ((qc->flags & ATA_QCFLAG_DMA) == 0) {
+		ata_qc_set_polling(qc);
+		qc->tf.protocol = ATA_PROT_ATAPI;
+		qc->tf.lbam = (8 * 1024) & 0xff;
+		qc->tf.lbah = (8 * 1024) >> 8;
+
+	/* DMA data xfer - interrupt-driven */
+	} else {
+		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
+		qc->tf.feature |= ATAPI_PKT_DMA;
+
+#ifdef ATAPI_ENABLE_DMADIR
+		/* some SATA bridges need us to indicate data xfer direction */
+		if (cmd->sc_data_direction != SCSI_DATA_WRITE)
+			qc->tf.feature |= ATAPI_DMADIR;
+#endif
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_scsi_find_dev - lookup ata_device from scsi_cmnd
+ *	@ap: ATA port to which the device is attached
+ *	@cmd: SCSI command to be sent to the device
+ *
+ *	Given various information provided in struct scsi_cmnd,
+ *	map that onto an ATA bus, and using that mapping
+ *	determine which ata_device is associated with the
+ *	SCSI command to be sent.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Associated ATA device, or %NULL if not found.
+ */
+
+static inline struct ata_device *
+ata_scsi_find_dev(struct ata_port *ap, struct scsi_cmnd *cmd)
+{
+	struct ata_device *dev;
+
+	/* skip commands not addressed to targets we simulate */
+	if (likely(cmd->target < ATA_MAX_DEVICES))
+		dev = &ap->device[cmd->target];
+	else
+		return NULL;
+
+	if (unlikely((cmd->channel != 0) ||
+		     (cmd->lun != 0)))
+		return NULL;
+
+	if (unlikely(!ata_dev_present(dev)))
+		return NULL;
+
+#ifndef ATA_ENABLE_ATAPI
+	if (unlikely(dev->class == ATA_DEV_ATAPI))
+		return NULL;
+#endif
+
+	return dev;
+}
+
+/**
+ *	ata_get_xlat_func - check if SCSI to ATA translation is possible
+ *	@cmd: SCSI command opcode to consider
+ *
+ *	Look up the SCSI command given, and determine whether the
+ *	SCSI command is to be translated or simulated.
+ *
+ *	RETURNS:
+ *	Pointer to translation function if possible, %NULL if not.
+ */
+
+static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd)
+{
+	switch (cmd) {
+	case READ_6:
+	case READ_10:
+	case READ_16:
+
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_16:
+		return ata_scsi_rw_xlat;
+	}
+
+	return NULL;
+}
+
+/**
+ *	ata_scsi_dump_cdb - dump SCSI command contents to dmesg
+ *	@ap: ATA port to which the command was being sent
+ *	@cmd: SCSI command to dump
+ *
+ *	Prints the contents of a SCSI command via printk().
+ */
+
+static inline void ata_scsi_dump_cdb(struct ata_port *ap,
+				     struct scsi_cmnd *cmd)
+{
+#ifdef ATA_DEBUG
+	u8 *scsicmd = cmd->cmnd;
+
+	DPRINTK("CDB (%u:%d,%d,%d) %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		ap->id,
+		cmd->channel, cmd->target, cmd->lun,
+		scsicmd[0], scsicmd[1], scsicmd[2], scsicmd[3],
+		scsicmd[4], scsicmd[5], scsicmd[6], scsicmd[7],
+		scsicmd[8]);
+#endif
+}
+
+/**
+ *	ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device
+ *	@cmd: SCSI command to be sent
+ *	@done: Completion function, called when command is complete
+ *
+ *	In some cases, this function translates SCSI commands into
+ *	ATA taskfiles, and queues the taskfiles to be sent to
+ *	hardware.  In other cases, this function simulates a
+ *	SCSI device by evaluating and responding to certain
+ *	SCSI commands.  This creates the overall effect of
+ *	ATA and ATAPI devices appearing as SCSI devices.
+ *
+ *	LOCKING:
+ *	Releases scsi-layer-held lock, and obtains host_set lock.
+ *
+ *	RETURNS:
+ *	Zero.
+ */
+
+int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+	struct ata_port *ap;
+	struct ata_device *dev;
+
+	/* Note: spin_lock_irqsave is held by caller... */
+	spin_unlock(&io_request_lock);
+
+	ap = (struct ata_port *) &cmd->host->hostdata[0];
+
+	spin_lock(&ap->host_set->lock);
+
+	ata_scsi_dump_cdb(ap, cmd);
+
+	dev = ata_scsi_find_dev(ap, cmd);
+	if (unlikely(!dev)) {
+		cmd->result = (DID_BAD_TARGET << 16);
+		done(cmd);
+		goto out_unlock;
+	}
+
+	if (dev->class == ATA_DEV_ATA) {
+		ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]);
+
+		if (xlat_func)
+			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
+		else
+			ata_scsi_simulate(ap, dev, cmd, done);
+	} else
+		ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
+
+out_unlock:
+	spin_unlock(&ap->host_set->lock);
+	spin_lock(&io_request_lock);
+	return 0;
+}
+
+/**
+ *	ata_scsi_simulate - simulate SCSI command on ATA device
+ *	@ap: Port to which ATA device is attached.
+ *	@dev: Target device for CDB.
+ *	@cmd: SCSI command being sent to device.
+ *	@done: SCSI command completion function.
+ *
+ *	Interprets and directly executes a select list of SCSI commands
+ *	that can be handled internally.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
+			      struct scsi_cmnd *cmd,
+			      void (*done)(struct scsi_cmnd *))
+{
+	struct ata_scsi_args args;
+	u8 *scsicmd = cmd->cmnd;
+
+	args.ap = ap;
+	args.dev = dev;
+	args.cmd = cmd;
+	args.done = done;
+
+	switch(scsicmd[0]) {
+		/* no-op's, complete with success */
+		case SYNCHRONIZE_CACHE:		/* FIXME: temporary */
+		case REZERO_UNIT:
+		case SEEK_6:
+		case SEEK_10:
+		case TEST_UNIT_READY:
+		case FORMAT_UNIT:		/* FIXME: correct? */
+		case SEND_DIAGNOSTIC:		/* FIXME: correct? */
+			ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
+			break;
+
+		case INQUIRY:
+			if (scsicmd[1] & 2)	           /* is CmdDt set?  */
+				ata_bad_cdb(cmd, done);
+			else if ((scsicmd[1] & 1) == 0)    /* is EVPD clear? */
+				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
+			else if (scsicmd[2] == 0x00)
+				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
+			else if (scsicmd[2] == 0x80)
+				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
+			else if (scsicmd[2] == 0x83)
+				ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
+			else
+				ata_bad_cdb(cmd, done);
+			break;
+
+		case MODE_SENSE:
+		case MODE_SENSE_10:
+			ata_scsi_rbuf_fill(&args, ata_scsiop_mode_sense);
+			break;
+
+		case MODE_SELECT:	/* unconditionally return */
+		case MODE_SELECT_10:	/* bad-field-in-cdb */
+			ata_bad_cdb(cmd, done);
+			break;
+
+		case READ_CAPACITY:
+			ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
+			break;
+
+		case SERVICE_ACTION_IN:
+			if ((scsicmd[1] & 0x1f) == SAI_READ_CAPACITY_16)
+				ata_scsi_rbuf_fill(&args, ata_scsiop_read_cap);
+			else
+				ata_bad_cdb(cmd, done);
+			break;
+
+		case REPORT_LUNS:
+			ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns);
+			break;
+
+		/* mandantory commands we haven't implemented yet */
+		case REQUEST_SENSE:
+
+		/* all other commands */
+		default:
+			ata_bad_scsiop(cmd, done);
+			break;
+	}
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/libata.h linux-2.4.27-rc4/drivers/scsi/libata.h
--- linux-2.4.26/drivers/scsi/libata.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/libata.h	2004-07-30 16:26:38.000000000 +0000
@@ -0,0 +1,88 @@
+/*
+   libata.h - helper library for ATA
+
+   Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+   Copyright 2003-2004 Jeff Garzik
+
+   The contents of this file are subject to the Open
+   Software License version 1.1 that can be found at
+   http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+   by reference.
+
+   Alternatively, the contents of this file may be used under the terms
+   of the GNU General Public License version 2 (the "GPL") as distributed
+   in the kernel source COPYING file, in which case the provisions of
+   the GPL are applicable instead of the above.  If you wish to allow
+   the use of your version of this file only under the terms of the
+   GPL and not to allow others to use your version of this file under
+   the OSL, indicate your decision by deleting the provisions above and
+   replace them with the notice and other provisions required by the GPL.
+   If you do not delete the provisions above, a recipient may use your
+   version of this file under either the OSL or the GPL.
+
+ */
+
+#ifndef __LIBATA_H__
+#define __LIBATA_H__
+
+#define DRV_NAME	"libata"
+#define DRV_VERSION	"1.02"	/* must be exactly four chars */
+
+struct ata_scsi_args {
+	struct ata_port		*ap;
+	struct ata_device	*dev;
+	struct scsi_cmnd		*cmd;
+	void			(*done)(struct scsi_cmnd *);
+};
+
+
+/* libata-core.c */
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
+				      struct ata_device *dev);
+extern int ata_qc_issue(struct ata_queued_cmd *qc);
+extern void ata_dev_select(struct ata_port *ap, unsigned int device,
+                           unsigned int wait, unsigned int can_sleep);
+extern void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf);
+
+
+/* libata-scsi.c */
+extern void ata_to_sense_error(struct ata_queued_cmd *qc);
+extern int ata_scsi_error(struct Scsi_Host *host);
+extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
+			       unsigned int buflen);
+
+extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
+			      unsigned int buflen);
+
+extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
+			      unsigned int buflen);
+extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
+			      unsigned int buflen);
+extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
+			    unsigned int buflen);
+extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
+				  unsigned int buflen);
+extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
+				  unsigned int buflen);
+extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+			        unsigned int buflen);
+extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
+				   unsigned int buflen);
+extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
+			    void (*done)(struct scsi_cmnd *),
+			    u8 asc, u8 ascq);
+extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, 
+                        unsigned int (*actor) (struct ata_scsi_args *args,
+                                           u8 *rbuf, unsigned int buflen));
+
+static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+	ata_scsi_badcmd(cmd, done, 0x20, 0x00);
+}
+
+static inline void ata_bad_cdb(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+{
+	ata_scsi_badcmd(cmd, done, 0x24, 0x00);
+}
+
+#endif /* __LIBATA_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/megaraid2.c linux-2.4.27-rc4/drivers/scsi/megaraid2.c
--- linux-2.4.26/drivers/scsi/megaraid2.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/megaraid2.c	2004-07-30 16:26:34.000000000 +0000
@@ -14,7 +14,10 @@
  *	  - speed-ups (list handling fixes, issued_list, optimizations.)
  *	  - lots of cleanups.
  *
- * Version : v2.10.1 (Dec 03, 2003) - Atul Mukker <Atul.Mukker@lsil.com>
+ * Version : v2.10.3 (Apr 08, 2004)
+ *
+ * Authors:	Atul Mukker <Atul.Mukker@lsil.com>
+ *		Sreenivas Bagalkote <Sreenivas.Bagalkote@lsil.com>
  *
  * Description: Linux device driver for LSI Logic MegaRAID controller
  *
@@ -23,8 +26,6 @@
  *
  * This driver is supported by LSI Logic, with assistance from Red Hat, Dell,
  * and others. Please send updates to the public mailing list
- * linux-megaraid-devel@dell.com, and subscribe to and read archives of this
- * list at http://lists.us.dell.com/.
  *
  * For history of changes, see ChangeLog.megaraid.
  *
@@ -45,6 +46,10 @@
 
 #include "megaraid2.h"
 
+#ifdef LSI_CONFIG_COMPAT
+#include <asm/ioctl32.h>
+#endif
+
 MODULE_AUTHOR ("LSI Logic Corporation");
 MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
 MODULE_LICENSE ("GPL");
@@ -206,6 +211,10 @@ megaraid_detect(Scsi_Host_Template *host
 		 */
 		major = register_chrdev(0, "megadev", &megadev_fops);
 
+		if (major < 0) {
+			printk(KERN_WARNING
+				"megaraid: failed to register char device.\n");
+		}
 		/*
 		 * Register the Shutdown Notification hook in kernel
 		 */
@@ -214,6 +223,13 @@ megaraid_detect(Scsi_Host_Template *host
 				"MegaRAID Shutdown routine not registered!!\n");
 		}
 
+#ifdef LSI_CONFIG_COMPAT
+		/*
+		 * Register the 32-bit ioctl conversion
+		 */
+		register_ioctl32_conversion(MEGAIOCCMD, megadev_compat_ioctl);
+#endif
+
 	}
 
 	return hba_count;
@@ -311,6 +327,7 @@ mega_find_card(Scsi_Host_Template *host_
 				(subsysvid != DELL_SUBSYS_VID) &&
 				(subsysvid != HP_SUBSYS_VID) &&
 				(subsysvid != INTEL_SUBSYS_VID) &&
+				(subsysvid != FSC_SUBSYS_VID) &&
 				(subsysvid != LSI_SUBSYS_VID) ) continue;
 
 
@@ -403,7 +420,8 @@ mega_find_card(Scsi_Host_Template *host_
 		scsi_set_host_lock(&adapter->lock);
 #  endif
 #else
-		/* And this is the remainder of the 2.4 kernel series */
+		/* And this is the remainder of the 2.4 kernel
+		series */
 		adapter->host_lock = &io_request_lock;
 #endif
 
@@ -620,12 +638,15 @@ mega_find_card(Scsi_Host_Template *host_
 
 		/* Set the Mode of addressing to 64 bit if we can */
 		if((adapter->flag & BOARD_64BIT)&&(sizeof(dma_addr_t) == 8)) {
-			pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
-			adapter->has_64bit_addr = 1;
+			if (pci_set_dma_mask(pdev, 0xffffffffffffffffULL) == 0)
+				adapter->has_64bit_addr = 1;
 		}
-		else  {
-			pci_set_dma_mask(pdev, 0xffffffff);
-			adapter->has_64bit_addr = 0;
+		if (!adapter->has_64bit_addr)  {
+			if (pci_set_dma_mask(pdev, 0xffffffffULL) != 0) {
+				printk("megaraid%d: DMA not available.\n",
+					host->host_no);
+				goto fail_attach;
+			}
 		}
 
 		init_MUTEX(&adapter->int_mtx);
@@ -2249,26 +2270,28 @@ mega_free_scb(adapter_t *adapter, scb_t 
 		break;
 
 	case MEGA_BULK_DATA:
-		pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
-			scb->cmd->request_bufflen, scb->dma_direction);
-
 		if( scb->dma_direction == PCI_DMA_FROMDEVICE ) {
 			pci_dma_sync_single(adapter->dev, scb->dma_h_bulkdata,
 					scb->cmd->request_bufflen,
 					PCI_DMA_FROMDEVICE);
 		}
 
+		pci_unmap_page(adapter->dev, scb->dma_h_bulkdata,
+			scb->cmd->request_bufflen, scb->dma_direction);
+
 		break;
 
 	case MEGA_SGLIST:
-		pci_unmap_sg(adapter->dev, scb->cmd->request_buffer,
-			scb->cmd->use_sg, scb->dma_direction);
-
 		if( scb->dma_direction == PCI_DMA_FROMDEVICE ) {
-			pci_dma_sync_sg(adapter->dev, scb->cmd->request_buffer,
-					scb->cmd->use_sg, PCI_DMA_FROMDEVICE);
+			pci_dma_sync_sg(adapter->dev,
+				(struct scatterlist *)scb->cmd->request_buffer,
+				scb->cmd->use_sg, PCI_DMA_FROMDEVICE);
 		}
 
+		pci_unmap_sg(adapter->dev,
+			(struct scatterlist *)scb->cmd->request_buffer,
+			scb->cmd->use_sg, scb->dma_direction);
+
 		break;
 
 	default:
@@ -2402,8 +2425,9 @@ mega_build_sglist(adapter_t *adapter, sc
 	*len = (u32)cmd->request_bufflen;
 
 	if( scb->dma_direction == PCI_DMA_TODEVICE ) {
-		pci_dma_sync_sg(adapter->dev, cmd->request_buffer,
-				cmd->use_sg, PCI_DMA_TODEVICE);
+		pci_dma_sync_sg(adapter->dev,
+			(struct scatterlist *)cmd->request_buffer,
+			cmd->use_sg, PCI_DMA_TODEVICE);
 	}
 
 	/* Return count of SG requests */
@@ -2474,7 +2498,9 @@ megaraid_release(struct Scsi_Host *host)
 	memset(raw_mbox, 0, sizeof(raw_mbox));
 	raw_mbox[0] = FLUSH_ADAPTER;
 
-	irq_disable(adapter);
+	if (adapter->flag & BOARD_IOMAP)
+		irq_disable(adapter);
+
 	free_irq(adapter->host->irq, adapter);
 
 	/* Issue a blocking (interrupts disabled) command to the card */
@@ -2549,7 +2575,9 @@ megaraid_release(struct Scsi_Host *host)
 		/*
 		 * Unregister the character device interface to the driver.
 		 */
-		unregister_chrdev(major, "megadev");
+		if (major >= 0) {
+			unregister_chrdev(major, "megadev");
+		}
 
 		unregister_reboot_notifier(&mega_notifier);
 
@@ -2568,6 +2596,9 @@ megaraid_release(struct Scsi_Host *host)
 	 */
 	scsi_unregister(host);
 
+#ifdef LSI_CONFIG_COMPAT
+	unregister_ioctl32_conversion(MEGAIOCCMD);
+#endif
 
 	printk("ok.\n");
 
@@ -3392,7 +3423,11 @@ proc_pdrv(adapter_t *adapter, char *page
 
 	max_channels = adapter->product_info.nchannels;
 
-	if( channel >= max_channels ) return 0;
+	if (channel >= max_channels) {
+		pci_free_consistent(pdev, 256, scsi_inq, scsi_inq_dma_handle);
+		mega_free_inquiry(inquiry, dma_handle, pdev);
+		return 0;
+	}
 
 	for( tgt = 0; tgt <= MAX_TARGET; tgt++ ) {
 
@@ -3860,153 +3895,6 @@ proc_rdrv(adapter_t *adapter, char *page
 
 
 /**
- * megaraid_biosparam()
- * @disk
- * @dev
- * @geom
- *
- * Return the disk geometry for a particular disk
- * Input:
- *	Disk *disk - Disk geometry
- *	kdev_t dev - Device node
- *	int *geom  - Returns geometry fields
- *		geom[0] = heads
- *		geom[1] = sectors
- *		geom[2] = cylinders
- */
-static int
-megaraid_biosparam(Disk *disk, kdev_t dev, int *geom)
-{
-	int heads, sectors, cylinders;
-	adapter_t *adapter;
-
-	/* Get pointer to host config structure */
-	adapter = (adapter_t *)disk->device->host->hostdata;
-
-	if (IS_RAID_CH(adapter, disk->device->channel)) {
-			/* Default heads (64) & sectors (32) */
-			heads = 64;
-			sectors = 32;
-			cylinders = disk->capacity / (heads * sectors);
-
-			/*
-			 * Handle extended translation size for logical drives
-			 * > 1Gb
-			 */
-			if (disk->capacity >= 0x200000) {
-				heads = 255;
-				sectors = 63;
-				cylinders = disk->capacity / (heads * sectors);
-			}
-
-			/* return result */
-			geom[0] = heads;
-			geom[1] = sectors;
-			geom[2] = cylinders;
-	}
-	else {
-		if( !mega_partsize(disk, dev, geom) )
-			return 0;
-
-		printk(KERN_WARNING
-		"megaraid: invalid partition on this disk on channel %d\n",
-				disk->device->channel);
-
-		/* Default heads (64) & sectors (32) */
-		heads = 64;
-		sectors = 32;
-		cylinders = disk->capacity / (heads * sectors);
-
-		/* Handle extended translation size for logical drives > 1Gb */
-		if (disk->capacity >= 0x200000) {
-			heads = 255;
-			sectors = 63;
-			cylinders = disk->capacity / (heads * sectors);
-		}
-
-		/* return result */
-		geom[0] = heads;
-		geom[1] = sectors;
-		geom[2] = cylinders;
-	}
-
-	return 0;
-}
-
-/*
- * mega_partsize()
- * @disk
- * @geom
- *
- * Purpose : to determine the BIOS mapping used to create the partition
- *	table, storing the results (cyls, hds, and secs) in geom
- *
- * Note:	Code is picked from scsicam.h
- *
- * Returns : -1 on failure, 0 on success.
- */
-static int
-mega_partsize(Disk *disk, kdev_t dev, int *geom)
-{
-	struct buffer_head *bh;
-	struct partition *p, *largest = NULL;
-	int i, largest_cyl;
-	int heads, cyls, sectors;
-	int capacity = disk->capacity;
-
-	int ma = MAJOR(dev);
-	int mi = (MINOR(dev) & ~0xf);
-
-	int block = 1024; 
-
-	if (blksize_size[ma])
-		block = blksize_size[ma][mi];
-
-	if (!(bh = bread(MKDEV(ma,mi), 0, block)))
-		return -1;
-
-	if (*(unsigned short *)(bh->b_data + 510) == 0xAA55 ) {
-
-		for (largest_cyl = -1,
-			p = (struct partition *)(0x1BE + bh->b_data), i = 0;
-			i < 4; ++i, ++p) {
-
-			if (!p->sys_ind) continue;
-
-			cyls = p->end_cyl + ((p->end_sector & 0xc0) << 2);
-
-			if (cyls >= largest_cyl) {
-				largest_cyl = cyls;
-				largest = p;
-			}
-		}
-	}
-
-	if (largest) {
-		heads = largest->end_head + 1;
-		sectors = largest->end_sector & 0x3f;
-
-		if (!heads || !sectors) {
-			brelse(bh);
-			return -1;
-		}
-
-		cyls = capacity/(heads * sectors);
-
-		geom[0] = heads;
-		geom[1] = sectors;
-		geom[2] = cyls;
-
-		brelse(bh);
-		return 0;
-	}
-
-	brelse(bh);
-	return -1;
-}
-
-
-/**
  * megaraid_reboot_notify()
  * @this - unused
  * @code - shutdown code
@@ -4040,7 +3928,9 @@ megaraid_reboot_notify (struct notifier_
 		memset(raw_mbox, 0, sizeof(raw_mbox));
 		raw_mbox[0] = FLUSH_ADAPTER;
 
-		irq_disable(adapter);
+		if (adapter->flag & BOARD_IOMAP)
+			irq_disable(adapter);
+
 		free_irq(adapter->host->irq, adapter);
 
 		/*
@@ -4179,6 +4069,18 @@ megadev_open (struct inode *inode, struc
 }
 
 
+#ifdef LSI_CONFIG_COMPAT
+static int
+megadev_compat_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg,
+		struct file *filep)
+{
+	struct inode *inode = filep->f_dentry->d_inode;
+
+	return megadev_ioctl(inode, filep, cmd, arg);
+}
+#endif
+
+
 /**
  * megadev_ioctl()
  * @inode - Our device inode
@@ -4386,8 +4288,8 @@ megadev_ioctl(struct inode *inode, struc
 			/*
 			 * The user passthru structure
 			 */
-			upthru = (mega_passthru *)MBOX(uioc)->xferaddr;
-
+			upthru = (mega_passthru *)
+					((ulong)(MBOX(uioc)->xferaddr));
 			/*
 			 * Copy in the user passthru here.
 			 */
@@ -4434,8 +4336,9 @@ megadev_ioctl(struct inode *inode, struc
 				/*
 				 * Get the user data
 				 */
-				if( copy_from_user(data, (char *)uxferaddr,
-							pthru->dataxferlen) ) {
+				if( copy_from_user(data,
+						(char *)((ulong)uxferaddr),
+						pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 					goto freemem_and_return;
 				}
@@ -4460,8 +4363,8 @@ megadev_ioctl(struct inode *inode, struc
 			 * Is data going up-stream
 			 */
 			if( pthru->dataxferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char *)uxferaddr, data,
-							pthru->dataxferlen) ) {
+				if( copy_to_user((char *)((ulong)uxferaddr),
+						data, pthru->dataxferlen) ) {
 					rval = (-EFAULT);
 				}
 			}
@@ -4509,12 +4412,13 @@ freemem_and_return:
 				/*
 				 * Get the user data
 				 */
-				if( copy_from_user(data, (char *)uxferaddr,
-							uioc.xferlen) ) {
+				if( copy_from_user(data,
+						(char *)((ulong)uxferaddr),
+						uioc.xferlen) ) {
 
 					pci_free_consistent(pdev,
-							uioc.xferlen,
-							data, data_dma_hndl);
+						uioc.xferlen, data,
+						data_dma_hndl);
 
 					return (-EFAULT);
 				}
@@ -4545,8 +4449,8 @@ freemem_and_return:
 			 * Is data going up-stream
 			 */
 			if( uioc.xferlen && (uioc.flags & UIOC_RD) ) {
-				if( copy_to_user((char *)uxferaddr, data,
-							uioc.xferlen) ) {
+				if( copy_to_user((char *)((ulong)uxferaddr),
+						data, uioc.xferlen) ) {
 
 					rval = (-EFAULT);
 				}
@@ -4731,7 +4635,7 @@ mega_n_to_m(void *arg, megacmd_t *mc)
 
 			umc = MBOX_P(uiocp);
 
-			upthru = (mega_passthru *)umc->xferaddr;
+			upthru = (mega_passthru *)((ulong)(umc->xferaddr));
 
 			if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
 				return (-EFAULT);
@@ -4749,7 +4653,7 @@ mega_n_to_m(void *arg, megacmd_t *mc)
 			if (copy_from_user(&kmc, umc, sizeof(megacmd_t)))
 				return -EFAULT;
 
-			upthru = (mega_passthru *)kmc.xferaddr;
+			upthru = (mega_passthru *)((ulong)kmc.xferaddr);
 
 			if( put_user(mc->status, (u8 *)&upthru->scsistatus) )
 				return (-EFAULT);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/megaraid2.h linux-2.4.27-rc4/drivers/scsi/megaraid2.h
--- linux-2.4.26/drivers/scsi/megaraid2.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/megaraid2.h	2004-07-30 16:24:35.000000000 +0000
@@ -6,7 +6,7 @@
 
 
 #define MEGARAID_VERSION	\
-	"v2.10.1 (Release Date: Wed Dec  3 15:34:42 EST 2003)\n"
+	"v2.10.3 (Release Date: Thu Apr  8 16:16:05 EDT 2004)\n"
 
 /*
  * Driver features - change the values to enable or disable features in the
@@ -44,12 +44,6 @@
  */
 #define MEGA_HAVE_ENH_PROC	1
 
-#define MAX_DEV_TYPE	32
-
-#ifndef PCI_VENDOR_ID_LSI_LOGIC
-#define PCI_VENDOR_ID_LSI_LOGIC		0x1000
-#endif
-
 #ifndef PCI_VENDOR_ID_AMI
 #define PCI_VENDOR_ID_AMI		0x101E
 #endif
@@ -87,6 +81,7 @@
 #define	HP_SUBSYS_VID			0x103C
 #define LSI_SUBSYS_VID			0x1000
 #define INTEL_SUBSYS_VID		0x8086
+#define FSC_SUBSYS_VID			0x1734
 
 #define HBA_SIGNATURE	      		0x3344
 #define HBA_SIGNATURE_471	  	0xCCCC
@@ -134,7 +129,6 @@
 	.info =				megaraid_info,		\
 	.command =			megaraid_command,	\
 	.queuecommand =			megaraid_queue,		\
-	.bios_param =			megaraid_biosparam,	\
 	.max_sectors =			MAX_SECTORS_PER_IO,	\
 	.can_queue =			MAX_COMMANDS,		\
 	.this_id =			DEFAULT_INITIATOR_ID,	\
@@ -662,6 +656,9 @@ typedef struct {
  */
 #define MEGAIOC_MAGIC  	'm'
 
+/* Mega IOCTL command */
+#define MEGAIOCCMD     	_IOWR(MEGAIOC_MAGIC, 0, struct uioctl_t)
+
 #define MEGAIOC_QNADAP		'm'	/* Query # of adapters */
 #define MEGAIOC_QDRVRVER	'e'	/* Query driver version */
 #define MEGAIOC_QADAPINFO   	'g'	/* Query adapter information */
@@ -1115,7 +1112,6 @@ static int megaraid_release (struct Scsi
 static int megaraid_command (Scsi_Cmnd *);
 static int megaraid_abort(Scsi_Cmnd *);
 static int megaraid_reset(Scsi_Cmnd *);
-static int megaraid_biosparam (Disk *, kdev_t, int *);
 
 static int mega_build_sglist (adapter_t *adapter, scb_t *scb,
 			      u32 *buffer, u32 *length);
@@ -1129,6 +1125,16 @@ static void mega_8_to_40ld (mraid_inquir
 static int megaraid_reboot_notify (struct notifier_block *,
 				   unsigned long, void *);
 static int megadev_open (struct inode *, struct file *);
+
+#if defined(CONFIG_COMPAT) || defined( __x86_64__) || defined(IA32_EMULATION)
+#define LSI_CONFIG_COMPAT
+#endif
+
+#ifdef LSI_CONFIG_COMPAT
+static int megadev_compat_ioctl(unsigned int, unsigned int, unsigned long,
+	struct file *);
+#endif
+
 static int megadev_ioctl (struct inode *, struct file *, unsigned int,
 		unsigned long);
 static int mega_m_to_n(void *, nitioctl_t *);
@@ -1172,7 +1178,6 @@ static mega_passthru* mega_prepare_passt
 static mega_ext_passthru* mega_prepare_extpassthru(adapter_t *,
 		scb_t *, Scsi_Cmnd *, int, int);
 static void mega_enum_raid_scsi(adapter_t *);
-static int mega_partsize(Disk *, kdev_t, int *);
 static void mega_get_boot_drv(adapter_t *);
 static inline int mega_get_ldrv_num(adapter_t *, Scsi_Cmnd *, int);
 static int mega_support_random_del(adapter_t *);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/oktagon_esp.c linux-2.4.27-rc4/drivers/scsi/oktagon_esp.c
--- linux-2.4.26/drivers/scsi/oktagon_esp.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/oktagon_esp.c	2004-07-30 16:25:04.000000000 +0000
@@ -548,7 +548,7 @@ static void dma_invalidate(struct NCR_ES
 
 void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp)
 {
-        sp->SCp.have_data_in = (int) sp->SCp.ptr =
+        sp->SCp.ptr =
                 sp->request_buffer;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_promise.c linux-2.4.27-rc4/drivers/scsi/sata_promise.c
--- linux-2.4.26/drivers/scsi/sata_promise.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_promise.c	2004-07-30 16:24:28.000000000 +0000
@@ -0,0 +1,667 @@
+/*
+ *  sata_promise.c - Promise SATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include "sata_promise.h"
+
+#define DRV_NAME	"sata_promise"
+#define DRV_VERSION	"1.00"
+
+
+enum {
+	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
+	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
+	PDC_TBG_MODE		= 0x41,	/* TBG mode */
+	PDC_FLASH_CTL		= 0x44, /* Flash control register */
+	PDC_PCI_CTL		= 0x48, /* PCI control and status register */
+	PDC_GLOBAL_CTL		= 0x48, /* Global control/status (per port) */
+	PDC_CTLSTAT		= 0x60,	/* IDE control and status (per port) */
+	PDC_SATA_PLUG_CSR	= 0x6C, /* SATA Plug control/status reg */
+	PDC_SLEW_CTL		= 0x470, /* slew rate control reg */
+
+	PDC_ERR_MASK		= (1<<19) | (1<<20) | (1<<21) | (1<<22) |
+				  (1<<8) | (1<<9) | (1<<10),
+
+	board_2037x		= 0,	/* FastTrak S150 TX2plus */
+	board_20319		= 1,	/* FastTrak S150 TX4 */
+
+	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */
+
+	PDC_RESET		= (1 << 11), /* HDMA reset */
+};
+
+
+struct pdc_port_priv {
+	u8			*pkt;
+	dma_addr_t		pkt_dma;
+};
+
+static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void pdc_dma_setup(struct ata_queued_cmd *qc);
+static void pdc_dma_start(struct ata_queued_cmd *qc);
+static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static void pdc_eng_timeout(struct ata_port *ap);
+static int pdc_port_start(struct ata_port *ap);
+static void pdc_port_stop(struct ata_port *ap);
+static void pdc_phy_reset(struct ata_port *ap);
+static void pdc_fill_sg(struct ata_queued_cmd *qc);
+static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static inline void pdc_dma_complete (struct ata_port *ap,
+                                     struct ata_queued_cmd *qc, int have_err);
+
+static Scsi_Host_Template pdc_sata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations pdc_sata_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= pdc_tf_load_mmio,
+	.tf_read		= ata_tf_read_mmio,
+	.check_status		= ata_check_status_mmio,
+	.exec_command		= pdc_exec_command_mmio,
+	.phy_reset		= pdc_phy_reset,
+	.bmdma_setup            = pdc_dma_setup,
+	.bmdma_start            = pdc_dma_start,
+	.fill_sg		= pdc_fill_sg,
+	.eng_timeout		= pdc_eng_timeout,
+	.irq_handler		= pdc_interrupt,
+	.scr_read		= pdc_sata_scr_read,
+	.scr_write		= pdc_sata_scr_write,
+	.port_start		= pdc_port_start,
+	.port_stop		= pdc_port_stop,
+};
+
+static struct ata_port_info pdc_port_info[] = {
+	/* board_2037x */
+	{
+		.sht		= &pdc_sata_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
+		.pio_mask	= 0x03, /* pio3-4 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_sata_ops,
+	},
+
+	/* board_20319 */
+	{
+		.sht		= &pdc_sata_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
+		.pio_mask	= 0x03, /* pio3-4 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_sata_ops,
+	},
+};
+
+static struct pci_device_id pdc_sata_pci_tbl[] = {
+	{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3376, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_2037x },
+	{ PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20319 },
+	{ PCI_VENDOR_ID_PROMISE, 0x3319, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20319 },
+	{ }	/* terminate list */
+};
+
+
+static struct pci_driver pdc_sata_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= pdc_sata_pci_tbl,
+	.probe			= pdc_sata_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+
+static int pdc_port_start(struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+	struct pdc_port_priv *pp;
+	int rc;
+
+	rc = ata_port_start(ap);
+	if (rc)
+		return rc;
+
+	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	if (!pp) {
+		rc = -ENOMEM;
+		goto err_out;
+	}
+	memset(pp, 0, sizeof(*pp));
+
+	pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);
+	if (!pp->pkt) {
+		rc = -ENOMEM;
+		goto err_out_kfree;
+	}
+
+	ap->private_data = pp;
+
+	return 0;
+
+err_out_kfree:
+	kfree(pp);
+err_out:
+	ata_port_stop(ap);
+	return rc;
+}
+
+
+static void pdc_port_stop(struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+	struct pdc_port_priv *pp = ap->private_data;
+
+	ap->private_data = NULL;
+	pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma);
+	kfree(pp);
+	ata_port_stop(ap);
+}
+
+
+static void pdc_reset_port(struct ata_port *ap)
+{
+	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
+	unsigned int i;
+	u32 tmp;
+
+	for (i = 11; i > 0; i--) {
+		tmp = readl(mmio);
+		if (tmp & PDC_RESET)
+			break;
+
+		udelay(100);
+
+		tmp |= PDC_RESET;
+		writel(tmp, mmio);
+	}
+
+	tmp &= ~PDC_RESET;
+	writel(tmp, mmio);
+	readl(mmio);	/* flush */
+}
+
+static void pdc_phy_reset(struct ata_port *ap)
+{
+	pdc_reset_port(ap);
+	sata_phy_reset(ap);
+}
+
+static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
+			       u32 val)
+{
+	if (sc_reg > SCR_CONTROL)
+		return;
+	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void pdc_fill_sg(struct ata_queued_cmd *qc)
+{
+	struct pdc_port_priv *pp = qc->ap->private_data;
+	unsigned int i;
+
+	VPRINTK("ENTER\n");
+
+	ata_fill_sg(qc);
+
+	i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,  qc->dev->devno, pp->pkt);
+
+	if (qc->tf.flags & ATA_TFLAG_LBA48)
+		i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
+	else
+		i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
+
+	pdc_pkt_footer(&qc->tf, pp->pkt, i);
+}
+
+static inline void pdc_dma_complete (struct ata_port *ap,
+                                     struct ata_queued_cmd *qc,
+				     int have_err)
+{
+	u8 err_bit = have_err ? ATA_ERR : 0;
+
+	/* get drive status; clear intr; complete txn */
+	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
+}
+
+static void pdc_eng_timeout(struct ata_port *ap)
+{
+	u8 drv_stat;
+	struct ata_queued_cmd *qc;
+
+	DPRINTK("ENTER\n");
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+		goto out;
+	}
+
+	/* hack alert!  We cannot use the supplied completion
+	 * function from inside the ->eh_strategy_handler() thread.
+	 * libata is the only user of ->eh_strategy_handler() in
+	 * any kernel, so the default scsi_done() assumes it is
+	 * not being called from the SCSI EH.
+	 */
+	qc->scsidone = scsi_finish_command;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+		break;
+
+	case ATA_PROT_NODATA:
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat);
+
+		ata_qc_complete(qc, drv_stat);
+		break;
+
+	default:
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat);
+
+		ata_qc_complete(qc, drv_stat);
+		break;
+	}
+
+out:
+	DPRINTK("EXIT\n");
+}
+
+static inline unsigned int pdc_host_intr( struct ata_port *ap,
+                                          struct ata_queued_cmd *qc)
+{
+	u8 status;
+	unsigned int handled = 0, have_err = 0;
+	u32 tmp;
+	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+
+	tmp = readl(mmio);
+	if (tmp & PDC_ERR_MASK) {
+		have_err = 1;
+		pdc_reset_port(ap);
+	}
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		pdc_dma_complete(ap, qc, have_err);
+		handled = 1;
+		break;
+
+	case ATA_PROT_NODATA:   /* command completion, but no data xfer */
+		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+		if (have_err)
+			status |= ATA_ERR;
+		ata_qc_complete(qc, status);
+		handled = 1;
+		break;
+
+        default:
+                ap->stats.idle_irq++;
+                break;
+        }
+
+        return handled;
+}
+
+static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	struct ata_port *ap;
+	u32 mask = 0;
+	unsigned int i, tmp;
+	unsigned int handled = 0;
+	void *mmio_base;
+
+	VPRINTK("ENTER\n");
+
+	if (!host_set || !host_set->mmio_base) {
+		VPRINTK("QUICK EXIT\n");
+		return IRQ_NONE;
+	}
+
+	mmio_base = host_set->mmio_base;
+
+	/* reading should also clear interrupts */
+	mask = readl(mmio_base + PDC_INT_SEQMASK);
+
+	if (mask == 0xffffffff) {
+		VPRINTK("QUICK EXIT 2\n");
+		return IRQ_NONE;
+	}
+	mask &= 0xffff;		/* only 16 tags possible */
+	if (!mask) {
+		VPRINTK("QUICK EXIT 3\n");
+		return IRQ_NONE;
+	}
+
+        spin_lock(&host_set->lock);
+
+        for (i = 0; i < host_set->n_ports; i++) {
+		VPRINTK("port %u\n", i);
+		ap = host_set->ports[i];
+		tmp = mask & (1 << (i + 1));
+		if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			struct ata_queued_cmd *qc;
+
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+				handled += pdc_host_intr(ap, qc);
+		}
+	}
+
+        spin_unlock(&host_set->lock);
+
+	VPRINTK("EXIT\n");
+
+	return IRQ_RETVAL(handled);
+}
+
+static void pdc_dma_setup(struct ata_queued_cmd *qc)
+{
+	/* nothing for now.  later, we will call standard
+	 * code in libata-core for ATAPI here */
+}
+
+static void pdc_dma_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_port_priv *pp = ap->private_data;
+	unsigned int port_no = ap->port_no;
+	u8 seq = (u8) (port_no + 1);
+
+	VPRINTK("ENTER, ap %p\n", ap);
+
+	writel(0x00000001, ap->host_set->mmio_base + (seq * 4));
+	readl(ap->host_set->mmio_base + (seq * 4));	/* flush */
+
+	pp->pkt[2] = seq;
+	wmb();			/* flush PRD, pkt writes */
+	writel(pp->pkt_dma, (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+	readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
+}
+
+static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (tf->protocol != ATA_PROT_DMA)
+		ata_tf_load_mmio(ap, tf);
+}
+
+
+static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (tf->protocol != ATA_PROT_DMA)
+		ata_exec_command_mmio(ap, tf);
+}
+
+
+static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+	port->cmd_addr		= base;
+	port->data_addr		= base;
+	port->feature_addr	=
+	port->error_addr	= base + 0x4;
+	port->nsect_addr	= base + 0x8;
+	port->lbal_addr		= base + 0xc;
+	port->lbam_addr		= base + 0x10;
+	port->lbah_addr		= base + 0x14;
+	port->device_addr	= base + 0x18;
+	port->command_addr	=
+	port->status_addr	= base + 0x1c;
+	port->altstatus_addr	=
+	port->ctl_addr		= base + 0x38;
+}
+
+
+static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
+{
+	void *mmio = pe->mmio_base;
+	u32 tmp;
+
+	/*
+	 * Except for the hotplug stuff, this is voodoo from the
+	 * Promise driver.  Label this entire section
+	 * "TODO: figure out why we do this"
+	 */
+
+	/* change FIFO_SHD to 8 dwords, enable BMR_BURST */
+	tmp = readl(mmio + PDC_FLASH_CTL);
+	tmp |= 0x12000;	/* bit 16 (fifo 8 dw) and 13 (bmr burst?) */
+	writel(tmp, mmio + PDC_FLASH_CTL);
+
+	/* clear plug/unplug flags for all ports */
+	tmp = readl(mmio + PDC_SATA_PLUG_CSR);
+	writel(tmp | 0xff, mmio + PDC_SATA_PLUG_CSR);
+
+	/* mask plug/unplug ints */
+	tmp = readl(mmio + PDC_SATA_PLUG_CSR);
+	writel(tmp | 0xff0000, mmio + PDC_SATA_PLUG_CSR);
+
+	/* reduce TBG clock to 133 Mhz. */
+	tmp = readl(mmio + PDC_TBG_MODE);
+	tmp &= ~0x30000; /* clear bit 17, 16*/
+	tmp |= 0x10000;  /* set bit 17:16 = 0:1 */
+	writel(tmp, mmio + PDC_TBG_MODE);
+
+	readl(mmio + PDC_TBG_MODE);	/* flush */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(msecs_to_jiffies(10) + 1);
+
+	/* adjust slew rate control register. */
+	tmp = readl(mmio + PDC_SLEW_CTL);
+	tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */
+	tmp  |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */
+	writel(tmp, mmio + PDC_SLEW_CTL);
+}
+
+static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	unsigned long base;
+	void *mmio_base;
+	unsigned int board_idx = (unsigned int) ent->driver_data;
+	int rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	/*
+	 * If this driver happens to only be useful on Apple's K2, then
+	 * we should check that here as it has a normal Serverworks ID
+	 */
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	mmio_base = ioremap(pci_resource_start(pdev, 3),
+		            pci_resource_len(pdev, 3));
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+	base = (unsigned long) mmio_base;
+
+	probe_ent->sht		= pdc_port_info[board_idx].sht;
+	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
+	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
+	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
+
+       	probe_ent->irq = pdev->irq;
+       	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->mmio_base = mmio_base;
+
+	pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
+	pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
+
+	probe_ent->port[0].scr_addr = base + 0x400;
+	probe_ent->port[1].scr_addr = base + 0x500;
+
+	/* notice 4-port boards */
+	switch (board_idx) {
+	case board_20319:
+       		probe_ent->n_ports = 4;
+
+		pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+		pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
+
+		probe_ent->port[2].scr_addr = base + 0x600;
+		probe_ent->port[3].scr_addr = base + 0x700;
+		break;
+	case board_2037x:
+       		probe_ent->n_ports = 2;
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	pci_set_master(pdev);
+
+	/* initialize adapter */
+	pdc_host_init(board_idx, probe_ent);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_free_ent:
+	kfree(probe_ent);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+
+static int __init pdc_sata_init(void)
+{
+	int rc;
+
+	rc = pci_module_init(&pdc_sata_pci_driver);
+	if (rc)
+		return rc;
+
+	rc = scsi_register_module(MODULE_SCSI_HA, &pdc_sata_sht);
+	if (rc) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	pci_unregister_driver(&pdc_sata_pci_driver);
+	return rc;
+}
+
+
+static void __exit pdc_sata_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &pdc_sata_sht);
+	pci_unregister_driver(&pdc_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl);
+
+module_init(pdc_sata_init);
+module_exit(pdc_sata_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_promise.h linux-2.4.27-rc4/drivers/scsi/sata_promise.h
--- linux-2.4.26/drivers/scsi/sata_promise.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_promise.h	2004-07-30 16:31:26.000000000 +0000
@@ -0,0 +1,154 @@
+/*
+ *  sata_promise.h - Promise SATA common definitions and inline funcs
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#ifndef __SATA_PROMISE_H__
+#define __SATA_PROMISE_H__
+
+#include <linux/ata.h>
+
+enum pdc_packet_bits {
+	PDC_PKT_READ		= (1 << 2),
+	PDC_PKT_NODATA		= (1 << 3),
+
+	PDC_PKT_SIZEMASK	= (1 << 7) | (1 << 6) | (1 << 5),
+	PDC_PKT_CLEAR_BSY	= (1 << 4),
+	PDC_PKT_WAIT_DRDY	= (1 << 3) | (1 << 4),
+	PDC_LAST_REG		= (1 << 3),
+
+	PDC_REG_DEVCTL		= (1 << 3) | (1 << 2) | (1 << 1),
+};
+
+static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
+					  dma_addr_t sg_table,
+					  unsigned int devno, u8 *buf)
+{
+	u8 dev_reg;
+	u32 *buf32 = (u32 *) buf;
+
+	/* set control bits (byte 0), zero delay seq id (byte 3),
+	 * and seq id (byte 2)
+	 */
+	switch (tf->protocol) {
+	case ATA_PROT_DMA:
+		if (!(tf->flags & ATA_TFLAG_WRITE))
+			buf32[0] = cpu_to_le32(PDC_PKT_READ);
+		else
+			buf32[0] = 0;
+		break;
+
+	case ATA_PROT_NODATA:
+		buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
+		break;
+
+	default:
+		BUG();
+		break;
+	}
+
+	buf32[1] = cpu_to_le32(sg_table);	/* S/G table addr */
+	buf32[2] = 0;				/* no next-packet */
+
+	if (devno == 0)
+		dev_reg = ATA_DEVICE_OBS;
+	else
+		dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
+
+	/* select device */
+	buf[12] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
+	buf[13] = dev_reg;
+
+	/* device control register */
+	buf[14] = (1 << 5) | PDC_REG_DEVCTL;
+	buf[15] = tf->ctl;
+
+	return 16; 	/* offset of next byte */
+}
+
+static inline unsigned int pdc_pkt_footer(struct ata_taskfile *tf, u8 *buf,
+				  unsigned int i)
+{
+	if (tf->flags & ATA_TFLAG_DEVICE) {
+		buf[i++] = (1 << 5) | ATA_REG_DEVICE;
+		buf[i++] = tf->device;
+	}
+
+	/* and finally the command itself; also includes end-of-pkt marker */
+	buf[i++] = (1 << 5) | PDC_LAST_REG | ATA_REG_CMD;
+	buf[i++] = tf->command;
+
+	return i;
+}
+
+static inline unsigned int pdc_prep_lba28(struct ata_taskfile *tf, u8 *buf, unsigned int i)
+{
+	/* the "(1 << 5)" should be read "(count << 5)" */
+
+	/* ATA command block registers */
+	buf[i++] = (1 << 5) | ATA_REG_FEATURE;
+	buf[i++] = tf->feature;
+
+	buf[i++] = (1 << 5) | ATA_REG_NSECT;
+	buf[i++] = tf->nsect;
+
+	buf[i++] = (1 << 5) | ATA_REG_LBAL;
+	buf[i++] = tf->lbal;
+
+	buf[i++] = (1 << 5) | ATA_REG_LBAM;
+	buf[i++] = tf->lbam;
+
+	buf[i++] = (1 << 5) | ATA_REG_LBAH;
+	buf[i++] = tf->lbah;
+
+	return i;
+}
+
+static inline unsigned int pdc_prep_lba48(struct ata_taskfile *tf, u8 *buf, unsigned int i)
+{
+	/* the "(2 << 5)" should be read "(count << 5)" */
+
+	/* ATA command block registers */
+	buf[i++] = (2 << 5) | ATA_REG_FEATURE;
+	buf[i++] = tf->hob_feature;
+	buf[i++] = tf->feature;
+
+	buf[i++] = (2 << 5) | ATA_REG_NSECT;
+	buf[i++] = tf->hob_nsect;
+	buf[i++] = tf->nsect;
+
+	buf[i++] = (2 << 5) | ATA_REG_LBAL;
+	buf[i++] = tf->hob_lbal;
+	buf[i++] = tf->lbal;
+
+	buf[i++] = (2 << 5) | ATA_REG_LBAM;
+	buf[i++] = tf->hob_lbam;
+	buf[i++] = tf->lbam;
+
+	buf[i++] = (2 << 5) | ATA_REG_LBAH;
+	buf[i++] = tf->hob_lbah;
+	buf[i++] = tf->lbah;
+
+	return i;
+}
+
+
+#endif /* __SATA_PROMISE_H__ */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_sil.c linux-2.4.27-rc4/drivers/scsi/sata_sil.c
--- linux-2.4.26/drivers/scsi/sata_sil.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_sil.c	2004-07-30 16:28:56.000000000 +0000
@@ -0,0 +1,455 @@
+/*
+ *  sata_sil.c - Silicon Image SATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2003 Red Hat, Inc.
+ *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME	"sata_sil"
+#define DRV_VERSION	"0.54"
+
+enum {
+	sil_3112		= 0,
+	sil_3114		= 1,
+
+	SIL_SYSCFG		= 0x48,
+	SIL_MASK_IDE0_INT	= (1 << 22),
+	SIL_MASK_IDE1_INT	= (1 << 23),
+	SIL_MASK_IDE2_INT	= (1 << 24),
+	SIL_MASK_IDE3_INT	= (1 << 25),
+	SIL_MASK_2PORT		= SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT,
+	SIL_MASK_4PORT		= SIL_MASK_2PORT |
+				  SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT,
+
+	SIL_IDE2_BMDMA		= 0x200,
+
+	SIL_INTR_STEERING	= (1 << 1),
+	SIL_QUIRK_MOD15WRITE	= (1 << 0),
+	SIL_QUIRK_UDMA5MAX	= (1 << 1),
+};
+
+static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
+static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+static void sil_post_set_mode (struct ata_port *ap);
+
+static struct pci_device_id sil_pci_tbl[] = {
+	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
+	{ }	/* terminate list */
+};
+
+
+/* TODO firmware versions should be added - eric */
+struct sil_drivelist {
+	const char * product;
+	unsigned int quirk;
+} sil_blacklist [] = {
+	{ "ST320012AS",		SIL_QUIRK_MOD15WRITE },
+	{ "ST330013AS",		SIL_QUIRK_MOD15WRITE },
+	{ "ST340017AS",		SIL_QUIRK_MOD15WRITE },
+	{ "ST360015AS",		SIL_QUIRK_MOD15WRITE },
+	{ "ST380023AS",		SIL_QUIRK_MOD15WRITE },
+	{ "ST3120023AS",	SIL_QUIRK_MOD15WRITE },
+	{ "ST340014ASL",	SIL_QUIRK_MOD15WRITE },
+	{ "ST360014ASL",	SIL_QUIRK_MOD15WRITE },
+	{ "ST380011ASL",	SIL_QUIRK_MOD15WRITE },
+	{ "ST3120022ASL",	SIL_QUIRK_MOD15WRITE },
+	{ "ST3160021ASL",	SIL_QUIRK_MOD15WRITE },
+	{ "Maxtor 4D060H3",	SIL_QUIRK_UDMA5MAX },
+	{ }
+};
+
+static struct pci_driver sil_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= sil_pci_tbl,
+	.probe			= sil_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template sil_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations sil_ops = {
+	.port_disable		= ata_port_disable,
+	.dev_config		= sil_dev_config,
+	.tf_load		= ata_tf_load_mmio,
+	.tf_read		= ata_tf_read_mmio,
+	.check_status		= ata_check_status_mmio,
+	.exec_command		= ata_exec_command_mmio,
+	.phy_reset		= sata_phy_reset,
+	.post_set_mode		= sil_post_set_mode,
+	.bmdma_setup            = ata_bmdma_setup_mmio,
+	.bmdma_start            = ata_bmdma_start_mmio,
+	.fill_sg		= ata_fill_sg,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= ata_interrupt,
+	.scr_read		= sil_scr_read,
+	.scr_write		= sil_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+static struct ata_port_info sil_port_info[] = {
+	/* sil_3112 */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
+		.pio_mask	= 0x03,			/* pio3-4 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
+	}, /* sil_3114 */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
+		.pio_mask	= 0x03,			/* pio3-4 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
+	},
+};
+
+/* per-port register offsets */
+/* TODO: we can probably calculate rather than use a table */
+static const struct {
+	unsigned long tf;	/* ATA taskfile register block */
+	unsigned long ctl;	/* ATA control/altstatus register block */
+	unsigned long bmdma;	/* DMA register block */
+	unsigned long scr;	/* SATA control register block */
+	unsigned long sien;	/* SATA Interrupt Enable register */
+	unsigned long xfer_mode;/* data transfer mode register */
+} sil_port[] = {
+	/* port 0 ... */
+	{ 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4 },
+	{ 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4 },
+	{ 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4 },
+	{ 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4 },
+	/* ... port 3 */
+};
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
+
+static void sil_post_set_mode (struct ata_port *ap)
+{
+	struct ata_host_set *host_set = ap->host_set;
+	struct ata_device *dev;
+	void *addr = host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
+	u32 tmp, dev_mode[2];
+	unsigned int i;
+
+	for (i = 0; i < 2; i++) {
+		dev = &ap->device[i];
+		if (!ata_dev_present(dev))
+			dev_mode[i] = 0;	/* PIO0/1/2 */
+		else if (dev->flags & ATA_DFLAG_PIO)
+			dev_mode[i] = 1;	/* PIO3/4 */
+		else
+			dev_mode[i] = 3;	/* UDMA */
+		/* value 2 indicates MDMA */
+	}
+
+	tmp = readl(addr);
+	tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0));
+	tmp |= dev_mode[0];
+	tmp |= (dev_mode[1] << 4);
+	writel(tmp, addr);
+	readl(addr);	/* flush */
+}
+
+static inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg)
+{
+	unsigned long offset = ap->ioaddr.scr_addr;
+
+	switch (sc_reg) {
+	case SCR_STATUS:
+		return offset + 4;
+	case SCR_ERROR:
+		return offset + 8;
+	case SCR_CONTROL:
+		return offset;
+	default:
+		/* do nothing */
+		break;
+	}
+
+	return 0;
+}
+
+static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+	if (mmio)
+		return readl(mmio);
+	return 0xffffffffU;
+}
+
+static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+	void *mmio = (void *) sil_scr_addr(ap, sc_reg);
+	if (mmio)
+		writel(val, mmio);
+}
+
+/**
+ *	sil_dev_config - Apply device/host-specific errata fixups
+ *	@ap: Port containing device to be examined
+ *	@dev: Device to be examined
+ *
+ *	After the IDENTIFY [PACKET] DEVICE step is complete, and a
+ *	device is known to be present, this function is called.
+ *	We apply two errata fixups which are specific to Silicon Image,
+ *	a Seagate and a Maxtor fixup.
+ *
+ *	For certain Seagate devices, we must limit the maximum sectors
+ *	to under 8K.
+ *
+ *	For certain Maxtor devices, we must not program the drive
+ *	beyond udma5.
+ *
+ *	Both fixups are unfairly pessimistic.  As soon as I get more
+ *	information on these errata, I will create a more exhaustive
+ *	list, and apply the fixups to only the specific
+ *	devices/hosts/firmwares that need it.
+ *
+ *	20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
+ *	The Maxtor quirk is in the blacklist, but I'm keeping the original
+ *	pessimistic fix for the following reasons...
+ *	- There seems to be less info on it, only one device gleaned off the
+ *	Windows	driver, maybe only one is affected.  More info would be greatly
+ *	appreciated.
+ *	- But then again UDMA5 is hardly anything to complain about
+ */
+static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
+{
+	unsigned int n, quirks = 0;
+	unsigned char model_num[40];
+	const char *s;
+	unsigned int len;
+
+	ata_dev_id_string(dev, model_num, ATA_ID_PROD_OFS,
+			  sizeof(model_num));
+	s = &model_num[0];
+	len = strnlen(s, sizeof(model_num));
+
+	/* ATAPI specifies that empty space is blank-filled; remove blanks */
+	while ((len > 0) && (s[len - 1] == ' '))
+		len--;
+
+	for (n = 0; sil_blacklist[n].product; n++) 
+		if (!memcmp(sil_blacklist[n].product, s,
+			    strlen(sil_blacklist[n].product))) {
+			quirks = sil_blacklist[n].quirk;
+			break;
+		}
+	
+	/* limit requests to 15 sectors */
+	if (quirks & SIL_QUIRK_MOD15WRITE) {
+		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n",
+		       ap->id, dev->devno);
+		ap->host->max_sectors = 15;
+		ap->host->hostt->max_sectors = 15;
+		return;
+	}
+
+	/* limit to udma5 */
+	if (quirks & SIL_QUIRK_UDMA5MAX) {
+		printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
+		       ap->id, dev->devno, s);
+		ap->udma_mask &= ATA_UDMA5;
+		return;
+	}
+}
+
+static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	unsigned long base;
+	void *mmio_base;
+	int rc;
+	unsigned int i;
+	u32 tmp, irq_mask;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	/*
+	 * If this driver happens to only be useful on Apple's K2, then
+	 * we should check that here as it has a normal Serverworks ID
+	 */
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	INIT_LIST_HEAD(&probe_ent->node);
+	probe_ent->pdev = pdev;
+	probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops;
+	probe_ent->sht = sil_port_info[ent->driver_data].sht;
+	probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
+	probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
+	probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
+       	probe_ent->irq = pdev->irq;
+       	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
+
+	mmio_base = ioremap(pci_resource_start(pdev, 5),
+		            pci_resource_len(pdev, 5));
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+
+	probe_ent->mmio_base = mmio_base;
+
+	base = (unsigned long) mmio_base;
+
+	for (i = 0; i < probe_ent->n_ports; i++) {
+		probe_ent->port[i].cmd_addr = base + sil_port[i].tf;
+		probe_ent->port[i].altstatus_addr =
+		probe_ent->port[i].ctl_addr = base + sil_port[i].ctl;
+		probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma;
+		probe_ent->port[i].scr_addr = base + sil_port[i].scr;
+		ata_std_ports(&probe_ent->port[i]);
+	}
+
+	if (ent->driver_data == sil_3114) {
+		irq_mask = SIL_MASK_4PORT;
+
+		/* flip the magic "make 4 ports work" bit */
+		tmp = readl(mmio_base + SIL_IDE2_BMDMA);
+		if ((tmp & SIL_INTR_STEERING) == 0)
+			writel(tmp | SIL_INTR_STEERING,
+			       mmio_base + SIL_IDE2_BMDMA);
+
+	} else {
+		irq_mask = SIL_MASK_2PORT;
+	}
+
+	/* make sure IDE0/1/2/3 interrupts are not masked */
+	tmp = readl(mmio_base + SIL_SYSCFG);
+	if (tmp & irq_mask) {
+		tmp &= ~irq_mask;
+		writel(tmp, mmio_base + SIL_SYSCFG);
+		readl(mmio_base + SIL_SYSCFG);	/* flush */
+	}
+
+	/* mask all SATA phy-related interrupts */
+	/* TODO: unmask bit 6 (SError N bit) for hotplug */
+	for (i = 0; i < probe_ent->n_ports; i++)
+		writel(0, mmio_base + sil_port[i].sien);
+
+	pci_set_master(pdev);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_free_ent:
+	kfree(probe_ent);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init sil_init(void)
+{
+	int rc;
+
+	rc = pci_module_init(&sil_pci_driver);
+	if (rc)
+		return rc;
+
+	rc = scsi_register_module(MODULE_SCSI_HA, &sil_sht);
+	if (rc) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	pci_unregister_driver(&sil_pci_driver);
+	return rc;
+}
+
+static void __exit sil_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &sil_sht);
+	pci_unregister_driver(&sil_pci_driver);
+}
+
+
+module_init(sil_init);
+module_exit(sil_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_sis.c linux-2.4.27-rc4/drivers/scsi/sata_sis.c
--- linux-2.4.26/drivers/scsi/sata_sis.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_sis.c	2004-07-30 16:27:54.000000000 +0000
@@ -0,0 +1,294 @@
+/*
+ *  sata_sis.c - Silicon Integrated Systems SATA
+ *
+ *  Maintained by:  Uwe Koziolek
+ *  		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2004 Uwe Koziolek
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME	"sata_sis"
+#define DRV_VERSION	"0.10"
+
+enum {
+	sis_180			= 0,
+	SIS_SCR_PCI_BAR		= 5,
+
+	/* PCI configuration registers */
+	SIS_GENCTL		= 0x54, /* IDE General Control register */
+	SIS_SCR_BASE		= 0xc0, /* sata0 phy SCR registers */
+	SIS_SATA1_OFS		= 0x10, /* offset from sata0->sata1 phy regs */
+
+	/* random bits */
+	SIS_FLAG_CFGSCR		= (1 << 30), /* host flag: SCRs via PCI cfg */
+
+	GENCTL_IOMAPPED_SCR	= (1 << 26), /* if set, SCRs are in IO space */
+};
+
+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static struct pci_device_id sis_pci_tbl[] = {
+	{ PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+	{ PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 },
+	{ }	/* terminate list */
+};
+
+
+static struct pci_driver sis_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= sis_pci_tbl,
+	.probe			= sis_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template sis_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= ATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations sis_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.check_status		= ata_check_status_pio,
+	.exec_command		= ata_exec_command_pio,
+	.phy_reset		= sata_phy_reset,
+	.bmdma_setup            = ata_bmdma_setup_pio,
+	.bmdma_start            = ata_bmdma_start_pio,
+	.fill_sg		= ata_fill_sg,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= ata_interrupt,
+	.scr_read		= sis_scr_read,
+	.scr_write		= sis_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+
+MODULE_AUTHOR("Uwe Koziolek");
+MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
+
+static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg)
+{
+	unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
+
+	if (port_no)
+		addr += SIS_SATA1_OFS;
+	return addr;
+}
+
+static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg);
+	u32 val;
+
+	if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
+		return 0xffffffff;
+	pci_read_config_dword(ap->host_set->pdev, cfg_addr, &val);
+	return val;
+}
+
+static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
+{
+	unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr);
+
+	if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */
+		return;
+	pci_write_config_dword(ap->host_set->pdev, cfg_addr, val);
+}
+
+static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+
+	if (ap->flags & SIS_FLAG_CFGSCR)
+		return sis_scr_cfg_read(ap, sc_reg);
+	return inl(ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+	if (sc_reg > SCR_CONTROL)
+		return;
+
+	if (ap->flags & SIS_FLAG_CFGSCR)
+		sis_scr_cfg_write(ap, sc_reg, val);
+	else
+		outl(val, ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+/* move to PCI layer, integrate w/ MSI stuff */
+static void pci_enable_intx(struct pci_dev *pdev)
+{
+	u16 pci_command;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+	if (pci_command & PCI_COMMAND_INTX_DISABLE) {
+		pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+	}
+}
+
+static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct ata_probe_ent *probe_ent = NULL;
+	int rc;
+	u32 genctl;
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	probe_ent->sht = &sis_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+				ATA_FLAG_NO_LEGACY;
+
+	/* check and see if the SCRs are in IO space or PCI cfg space */
+	pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
+	if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
+		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
+	
+	/* if hardware thinks SCRs are in IO space, but there are
+	 * no IO resources assigned, change to PCI cfg space.
+	 */
+	if ((!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) &&
+	    ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) ||
+	     (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) {
+		genctl &= ~GENCTL_IOMAPPED_SCR;
+		pci_write_config_dword(pdev, SIS_GENCTL, genctl);
+		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
+	}
+
+	probe_ent->pio_mask = 0x03;
+	probe_ent->udma_mask = 0x7f;
+	probe_ent->port_ops = &sis_ops;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	ata_std_ports(&probe_ent->port[0]);
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
+		probe_ent->port[0].scr_addr =
+			pci_resource_start(pdev, SIS_SCR_PCI_BAR);
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	ata_std_ports(&probe_ent->port[1]);
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
+		probe_ent->port[1].scr_addr =
+			pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
+
+	probe_ent->n_ports = 2;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+
+	pci_set_master(pdev);
+	pci_enable_intx(pdev);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_regions:
+	pci_release_regions(pdev);
+
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+
+}
+
+static int __init sis_init(void)
+{
+	int rc = pci_module_init(&sis_pci_driver);
+	if (rc)
+		return rc;
+
+	rc = scsi_register_module(MODULE_SCSI_HA, &sis_sht);
+	if (rc) {
+		pci_unregister_driver(&sis_pci_driver);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit sis_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &sis_sht);
+	pci_unregister_driver(&sis_pci_driver);
+}
+
+module_init(sis_init);
+module_exit(sis_exit);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_svw.c linux-2.4.27-rc4/drivers/scsi/sata_svw.c
--- linux-2.4.26/drivers/scsi/sata_svw.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_svw.c	2004-07-30 16:29:41.000000000 +0000
@@ -0,0 +1,415 @@
+/*
+ *  sata_svw.c - ServerWorks / Apple K2 SATA
+ *
+ *  Maintained by: Benjamin Herrenschmidt <benh@kernel.crashing.org> and
+ *		   Jeff Garzik <jgarzik@pobox.com>
+ *  		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ *
+ *  Bits from Jeff Garzik, Copyright RedHat, Inc.
+ *
+ *  This driver probably works with non-Apple versions of the
+ *  Broadcom chipset...
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif /* CONFIG_PPC_OF */
+
+#define DRV_NAME	"sata_svw"
+#define DRV_VERSION	"1.04"
+
+/* Taskfile registers offsets */
+#define K2_SATA_TF_CMD_OFFSET		0x00
+#define K2_SATA_TF_DATA_OFFSET		0x00
+#define K2_SATA_TF_ERROR_OFFSET		0x04
+#define K2_SATA_TF_NSECT_OFFSET		0x08
+#define K2_SATA_TF_LBAL_OFFSET		0x0c
+#define K2_SATA_TF_LBAM_OFFSET		0x10
+#define K2_SATA_TF_LBAH_OFFSET		0x14
+#define K2_SATA_TF_DEVICE_OFFSET	0x18
+#define K2_SATA_TF_CMDSTAT_OFFSET      	0x1c
+#define K2_SATA_TF_CTL_OFFSET		0x20
+
+/* DMA base */
+#define K2_SATA_DMA_CMD_OFFSET		0x30
+
+/* SCRs base */
+#define K2_SATA_SCR_STATUS_OFFSET	0x40
+#define K2_SATA_SCR_ERROR_OFFSET	0x44
+#define K2_SATA_SCR_CONTROL_OFFSET	0x48
+
+/* Others */
+#define K2_SATA_SICR1_OFFSET		0x80
+#define K2_SATA_SICR2_OFFSET		0x84
+#define K2_SATA_SIM_OFFSET		0x88
+
+/* Port stride */
+#define K2_SATA_PORT_OFFSET		0x100
+
+
+static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void k2_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
+			       u32 val)
+{
+	if (sc_reg > SCR_CONTROL)
+		return;
+	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	if (tf->ctl != ap->last_ctl) {
+		writeb(tf->ctl, ioaddr->ctl_addr);
+		ap->last_ctl = tf->ctl;
+		ata_wait_idle(ap);
+	}
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
+		writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
+		writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
+		writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
+		writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
+	} else if (is_addr) {
+		writew(tf->feature, ioaddr->feature_addr);
+		writew(tf->nsect, ioaddr->nsect_addr);
+		writew(tf->lbal, ioaddr->lbal_addr);
+		writew(tf->lbam, ioaddr->lbam_addr);
+		writew(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE)
+		writeb(tf->device, ioaddr->device_addr);
+
+	ata_wait_idle(ap);
+}
+
+
+static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u16 nsect, lbal, lbam, lbah;
+
+	nsect = tf->nsect = readw(ioaddr->nsect_addr);
+	lbal = tf->lbal = readw(ioaddr->lbal_addr);
+	lbam = tf->lbam = readw(ioaddr->lbam_addr);
+	lbah = tf->lbah = readw(ioaddr->lbah_addr);
+	tf->device = readw(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		tf->hob_feature = readw(ioaddr->error_addr) >> 8;
+		tf->hob_nsect = nsect >> 8;
+		tf->hob_lbal = lbal >> 8;
+		tf->hob_lbam = lbam >> 8;
+		tf->hob_lbah = lbah >> 8;
+        }
+}
+
+
+static u8 k2_stat_check_status(struct ata_port *ap)
+{
+       	return readl((void *) ap->ioaddr.status_addr);
+}
+
+#ifdef CONFIG_PPC_OF
+/*
+ * k2_sata_proc_info
+ * inout : decides on the direction of the dataflow and the meaning of the
+ *	   variables
+ * buffer: If inout==FALSE data is being written to it else read from it
+ * *start: If inout==FALSE start of the valid data in the buffer
+ * offset: If inout==FALSE offset from the beginning of the imaginary file
+ *	   from which we start writing into the buffer
+ * length: If inout==FALSE max number of bytes to be written into the buffer
+ *	   else number of bytes in the buffer
+ */
+static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start,
+			     off_t offset, int count, int inout)
+{
+	struct ata_port *ap;
+	struct device_node *np;
+	int len, index;
+
+	/* Find  the ata_port */
+	ap = (struct ata_port *) &shost->hostdata[0];
+	if (ap == NULL)
+		return 0;
+
+	/* Find the OF node for the PCI device proper */
+	np = pci_device_to_OF_node(ap->host_set->pdev);
+	if (np == NULL)
+		return 0;
+
+	/* Match it to a port node */
+	index = (ap == ap->host_set->ports[0]) ? 0 : 1;
+	for (np = np->child; np != NULL; np = np->sibling) {
+		u32 *reg = (u32 *)get_property(np, "reg", NULL);
+		if (!reg)
+			continue;
+		if (index == *reg)
+			break;
+	}
+	if (np == NULL)
+		return 0;
+
+	len = sprintf(page, "devspec: %s\n", np->full_name);
+
+	return len;
+}
+#endif /* CONFIG_PPC_OF */
+
+
+static Scsi_Host_Template k2_sata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+#ifdef CONFIG_PPC_OF
+	.proc_info		= k2_sata_proc_info,
+#endif
+	.bios_param		= ata_std_bios_param,
+};
+
+
+static struct ata_port_operations k2_sata_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= k2_sata_tf_load,
+	.tf_read		= k2_sata_tf_read,
+	.check_status		= k2_stat_check_status,
+	.exec_command		= ata_exec_command_mmio,
+	.phy_reset		= sata_phy_reset,
+	.bmdma_setup            = ata_bmdma_setup_mmio,
+	.bmdma_start            = ata_bmdma_start_mmio,
+	.fill_sg		= ata_fill_sg,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= ata_interrupt,
+	.scr_read		= k2_sata_scr_read,
+	.scr_write		= k2_sata_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+	port->cmd_addr		= base + K2_SATA_TF_CMD_OFFSET;
+	port->data_addr		= base + K2_SATA_TF_DATA_OFFSET;
+	port->feature_addr	=
+	port->error_addr	= base + K2_SATA_TF_ERROR_OFFSET;
+	port->nsect_addr	= base + K2_SATA_TF_NSECT_OFFSET;
+	port->lbal_addr		= base + K2_SATA_TF_LBAL_OFFSET;
+	port->lbam_addr		= base + K2_SATA_TF_LBAM_OFFSET;
+	port->lbah_addr		= base + K2_SATA_TF_LBAH_OFFSET;
+	port->device_addr	= base + K2_SATA_TF_DEVICE_OFFSET;
+	port->command_addr	=
+	port->status_addr	= base + K2_SATA_TF_CMDSTAT_OFFSET;
+	port->altstatus_addr	=
+	port->ctl_addr		= base + K2_SATA_TF_CTL_OFFSET;
+	port->bmdma_addr	= base + K2_SATA_DMA_CMD_OFFSET;
+	port->scr_addr		= base + K2_SATA_SCR_STATUS_OFFSET;
+}
+
+
+static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	unsigned long base;
+	void *mmio_base;
+	int rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	/*
+	 * If this driver happens to only be useful on Apple's K2, then
+	 * we should check that here as it has a normal Serverworks ID
+	 */
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+	/*
+	 * Check if we have resources mapped at all (second function may
+	 * have been disabled by firmware)
+	 */
+	if (pci_resource_len(pdev, 5) == 0)
+		return -ENODEV;
+
+	/* Request PCI regions */
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	mmio_base = ioremap(pci_resource_start(pdev, 5),
+		            pci_resource_len(pdev, 5));
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+	base = (unsigned long) mmio_base;
+
+	/* Clear a magic bit in SCR1 according to Darwin, those help
+	 * some funky seagate drives (though so far, those were already
+	 * set by the firmware on the machines I had access to
+	 */
+	writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000,
+	       mmio_base + K2_SATA_SICR1_OFFSET);
+
+	/* Clear SATA error & interrupts we don't use */
+	writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET);
+	writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
+
+	probe_ent->sht = &k2_sata_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+				ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
+	probe_ent->port_ops = &k2_sata_ops;
+	probe_ent->n_ports = 4;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->mmio_base = mmio_base;
+
+	/* We don't care much about the PIO/UDMA masks, but the core won't like us
+	 * if we don't fill these
+	 */
+	probe_ent->pio_mask = 0x1f;
+	probe_ent->udma_mask = 0x7f;
+
+	/* We have 4 ports per PCI function */
+	k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET);
+	k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET);
+	k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET);
+	k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET);
+
+	pci_set_master(pdev);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_free_ent:
+	kfree(probe_ent);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+
+static struct pci_device_id k2_sata_pci_tbl[] = {
+	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }
+};
+
+
+static struct pci_driver k2_sata_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= k2_sata_pci_tbl,
+	.probe			= k2_sata_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+
+static int __init k2_sata_init(void)
+{
+	int rc;
+
+	rc = pci_module_init(&k2_sata_pci_driver);
+	if (rc)
+		return rc;
+
+	rc = scsi_register_module(MODULE_SCSI_HA, &k2_sata_sht);
+	if (rc) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	pci_unregister_driver(&k2_sata_pci_driver);
+	return rc;
+}
+
+
+static void __exit k2_sata_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &k2_sata_sht);
+	pci_unregister_driver(&k2_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Benjamin Herrenschmidt");
+MODULE_DESCRIPTION("low-level driver for K2 SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl);
+
+module_init(k2_sata_init);
+module_exit(k2_sata_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_sx4.c linux-2.4.27-rc4/drivers/scsi/sata_sx4.c
--- linux-2.4.26/drivers/scsi/sata_sx4.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_sx4.c	2004-07-30 16:28:27.000000000 +0000
@@ -0,0 +1,1459 @@
+/*
+ *  sata_sx4.c - Promise SATA
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *  		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2003-2004 Red Hat, Inc.
+ *
+ *  The contents of this file are subject to the Open
+ *  Software License version 1.1 that can be found at
+ *  http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ *  by reference.
+ *
+ *  Alternatively, the contents of this file may be used under the terms
+ *  of the GNU General Public License version 2 (the "GPL") as distributed
+ *  in the kernel source COPYING file, in which case the provisions of
+ *  the GPL are applicable instead of the above.  If you wish to allow
+ *  the use of your version of this file only under the terms of the
+ *  GPL and not to allow others to use your version of this file under
+ *  the OSL, indicate your decision by deleting the provisions above and
+ *  replace them with the notice and other provisions required by the GPL.
+ *  If you do not delete the provisions above, a recipient may use your
+ *  version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+#include "sata_promise.h"
+
+#define DRV_NAME	"sata_sx4"
+#define DRV_VERSION	"0.50"
+
+
+enum {
+	PDC_PRD_TBL		= 0x44,	/* Direct command DMA table addr */
+
+	PDC_PKT_SUBMIT		= 0x40, /* Command packet pointer addr */
+	PDC_HDMA_PKT_SUBMIT	= 0x100, /* Host DMA packet pointer addr */
+	PDC_INT_SEQMASK		= 0x40,	/* Mask of asserted SEQ INTs */
+	PDC_HDMA_CTLSTAT	= 0x12C, /* Host DMA control / status */
+
+	PDC_20621_SEQCTL	= 0x400,
+	PDC_20621_SEQMASK	= 0x480,
+	PDC_20621_GENERAL_CTL	= 0x484,
+	PDC_20621_PAGE_SIZE	= (32 * 1024),
+
+	/* chosen, not constant, values; we design our own DIMM mem map */
+	PDC_20621_DIMM_WINDOW	= 0x0C,	/* page# for 32K DIMM window */
+	PDC_20621_DIMM_BASE	= 0x00200000,
+	PDC_20621_DIMM_DATA	= (64 * 1024),
+	PDC_DIMM_DATA_STEP	= (256 * 1024),
+	PDC_DIMM_WINDOW_STEP	= (8 * 1024),
+	PDC_DIMM_HOST_PRD	= (6 * 1024),
+	PDC_DIMM_HOST_PKT	= (128 * 0),
+	PDC_DIMM_HPKT_PRD	= (128 * 1),
+	PDC_DIMM_ATA_PKT	= (128 * 2),
+	PDC_DIMM_APKT_PRD	= (128 * 3),
+	PDC_DIMM_HEADER_SZ	= PDC_DIMM_APKT_PRD + 128,
+	PDC_PAGE_WINDOW		= 0x40,
+	PDC_PAGE_DATA		= PDC_PAGE_WINDOW +
+				  (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE),
+	PDC_PAGE_SET		= PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE,
+
+	PDC_CHIP0_OFS		= 0xC0000, /* offset of chip #0 */
+
+	PDC_20621_ERR_MASK	= (1<<19) | (1<<20) | (1<<21) | (1<<22) |
+				  (1<<23),
+
+	board_20621		= 0,	/* FastTrak S150 SX4 */
+
+	PDC_RESET		= (1 << 11), /* HDMA reset */
+
+	PDC_MAX_HDMA		= 32,
+	PDC_HDMA_Q_MASK		= (PDC_MAX_HDMA - 1),
+
+	PDC_DIMM0_SPD_DEV_ADDRESS     = 0x50,
+	PDC_DIMM1_SPD_DEV_ADDRESS     = 0x51,
+	PDC_MAX_DIMM_MODULE           = 0x02,
+	PDC_I2C_CONTROL_OFFSET        = 0x48,
+	PDC_I2C_ADDR_DATA_OFFSET      = 0x4C,
+	PDC_DIMM0_CONTROL_OFFSET      = 0x80,
+	PDC_DIMM1_CONTROL_OFFSET      = 0x84,
+	PDC_SDRAM_CONTROL_OFFSET      = 0x88,
+	PDC_I2C_WRITE                 = 0x00000000,
+	PDC_I2C_READ                  = 0x00000040,	
+	PDC_I2C_START                 = 0x00000080,
+	PDC_I2C_MASK_INT              = 0x00000020,
+	PDC_I2C_COMPLETE              = 0x00010000,
+	PDC_I2C_NO_ACK                = 0x00100000,
+	PDC_DIMM_SPD_SUBADDRESS_START = 0x00,
+	PDC_DIMM_SPD_SUBADDRESS_END   = 0x7F,
+	PDC_DIMM_SPD_ROW_NUM          = 3,
+	PDC_DIMM_SPD_COLUMN_NUM       = 4,
+	PDC_DIMM_SPD_MODULE_ROW       = 5,
+	PDC_DIMM_SPD_TYPE             = 11,
+	PDC_DIMM_SPD_FRESH_RATE       = 12,         
+	PDC_DIMM_SPD_BANK_NUM         = 17,	
+	PDC_DIMM_SPD_CAS_LATENCY      = 18,
+	PDC_DIMM_SPD_ATTRIBUTE        = 21,    
+	PDC_DIMM_SPD_ROW_PRE_CHARGE   = 27,
+	PDC_DIMM_SPD_ROW_ACTIVE_DELAY = 28,      
+	PDC_DIMM_SPD_RAS_CAS_DELAY    = 29,
+	PDC_DIMM_SPD_ACTIVE_PRECHARGE = 30,
+	PDC_DIMM_SPD_SYSTEM_FREQ      = 126,
+	PDC_CTL_STATUS		      = 0x08,	
+	PDC_DIMM_WINDOW_CTLR	      = 0x0C,
+	PDC_TIME_CONTROL              = 0x3C,
+	PDC_TIME_PERIOD               = 0x40,
+	PDC_TIME_COUNTER              = 0x44,
+	PDC_GENERAL_CTLR	      = 0x484,
+	PCI_PLL_INIT                  = 0x8A531824,
+	PCI_X_TCOUNT                  = 0xEE1E5CFF
+};
+
+
+struct pdc_port_priv {
+	u8			dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512];
+	u8			*pkt;
+	dma_addr_t		pkt_dma;
+};
+
+struct pdc_host_priv {
+	void			*dimm_mmio;
+
+	unsigned int		doing_hdma;
+	unsigned int		hdma_prod;
+	unsigned int		hdma_cons;
+	struct {
+		struct ata_queued_cmd *qc;
+		unsigned int	seq;
+		unsigned long	pkt_ofs;
+	} hdma[32];
+};
+
+
+static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static void pdc20621_dma_setup(struct ata_queued_cmd *qc);
+static void pdc20621_dma_start(struct ata_queued_cmd *qc);
+static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static void pdc_eng_timeout(struct ata_port *ap);
+static void pdc_20621_phy_reset (struct ata_port *ap);
+static int pdc_port_start(struct ata_port *ap);
+static void pdc_port_stop(struct ata_port *ap);
+static void pdc20621_fill_sg(struct ata_queued_cmd *qc);
+static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+static void pdc20621_host_stop(struct ata_host_set *host_set);
+static inline void pdc_dma_complete (struct ata_port *ap,
+                                     struct ata_queued_cmd *qc, int have_err);
+static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe);
+static int pdc20621_detect_dimm(struct ata_probe_ent *pe);
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, 
+				      u32 device, u32 subaddr, u32 *pdata);
+static int pdc20621_prog_dimm0(struct ata_probe_ent *pe);
+static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe);
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, 
+				   void *psource, u32 offset, u32 size);
+#endif
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, 
+				 void *psource, u32 offset, u32 size);
+
+
+static Scsi_Host_Template pdc_sata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations pdc_20621_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= pdc_tf_load_mmio,
+	.tf_read		= ata_tf_read_mmio,
+	.check_status		= ata_check_status_mmio,
+	.exec_command		= pdc_exec_command_mmio,
+	.phy_reset		= pdc_20621_phy_reset,
+	.bmdma_setup            = pdc20621_dma_setup,
+	.bmdma_start            = pdc20621_dma_start,
+	.fill_sg		= pdc20621_fill_sg,
+	.eng_timeout		= pdc_eng_timeout,
+	.irq_handler		= pdc20621_interrupt,
+	.port_start		= pdc_port_start,
+	.port_stop		= pdc_port_stop,
+	.host_stop		= pdc20621_host_stop,
+};
+
+static struct ata_port_info pdc_port_info[] = {
+	/* board_20621 */
+	{
+		.sht		= &pdc_sata_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_SRST | ATA_FLAG_MMIO,
+		.pio_mask	= 0x03, /* pio3-4 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_20621_ops,
+	},
+
+};
+
+static struct pci_device_id pdc_sata_pci_tbl[] = {
+	{ PCI_VENDOR_ID_PROMISE, 0x6622, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20621 },
+	{ }	/* terminate list */
+};
+
+
+static struct pci_driver pdc_sata_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= pdc_sata_pci_tbl,
+	.probe			= pdc_sata_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+
+static void pdc20621_host_stop(struct ata_host_set *host_set)
+{
+	struct pdc_host_priv *hpriv = host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+
+	iounmap(dimm_mmio);
+	kfree(hpriv);
+}
+
+static int pdc_port_start(struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+	struct pdc_port_priv *pp;
+	int rc;
+
+	rc = ata_port_start(ap);
+	if (rc)
+		return rc;
+
+	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
+	if (!pp) {
+		rc = -ENOMEM;
+		goto err_out;
+	}
+	memset(pp, 0, sizeof(*pp));
+
+	pp->pkt = pci_alloc_consistent(pdev, 128, &pp->pkt_dma);
+	if (!pp->pkt) {
+		rc = -ENOMEM;
+		goto err_out_kfree;
+	}
+
+	ap->private_data = pp;
+
+	return 0;
+
+err_out_kfree:
+	kfree(pp);
+err_out:
+	ata_port_stop(ap);
+	return rc;
+}
+
+
+static void pdc_port_stop(struct ata_port *ap)
+{
+	struct pci_dev *pdev = ap->host_set->pdev;
+	struct pdc_port_priv *pp = ap->private_data;
+
+	ap->private_data = NULL;
+	pci_free_consistent(pdev, 128, pp->pkt, pp->pkt_dma);
+	kfree(pp);
+	ata_port_stop(ap);
+}
+
+
+static void pdc_20621_phy_reset (struct ata_port *ap)
+{
+	VPRINTK("ENTER\n");
+        ap->cbl = ATA_CBL_SATA;
+        ata_port_probe(ap);
+        ata_bus_reset(ap);
+}
+
+static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
+				    	   unsigned int portno,
+					   unsigned int total_len)
+{
+	u32 addr;
+	unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
+	u32 *buf32 = (u32 *) buf;
+
+	/* output ATA packet S/G table */
+	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
+	       (PDC_DIMM_DATA_STEP * portno);
+	VPRINTK("ATA sg addr 0x%x, %d\n", addr, addr);
+	buf32[dw] = cpu_to_le32(addr);
+	buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
+
+	VPRINTK("ATA PSG @ %x == (0x%x, 0x%x)\n",
+		PDC_20621_DIMM_BASE +
+		       (PDC_DIMM_WINDOW_STEP * portno) +
+		       PDC_DIMM_APKT_PRD,
+		buf32[dw], buf32[dw + 1]);
+}
+
+static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
+				    	    unsigned int portno,
+					    unsigned int total_len)
+{
+	u32 addr;
+	unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
+	u32 *buf32 = (u32 *) buf;
+
+	/* output Host DMA packet S/G table */
+	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
+	       (PDC_DIMM_DATA_STEP * portno);
+
+	buf32[dw] = cpu_to_le32(addr);
+	buf32[dw + 1] = cpu_to_le32(total_len | ATA_PRD_EOT);
+
+	VPRINTK("HOST PSG @ %x == (0x%x, 0x%x)\n",
+		PDC_20621_DIMM_BASE +
+		       (PDC_DIMM_WINDOW_STEP * portno) +
+		       PDC_DIMM_HPKT_PRD,
+		buf32[dw], buf32[dw + 1]);
+}
+
+static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
+					    unsigned int devno, u8 *buf,
+					    unsigned int portno)
+{
+	unsigned int i, dw;
+	u32 *buf32 = (u32 *) buf;
+	u8 dev_reg;
+
+	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
+			       (PDC_DIMM_WINDOW_STEP * portno) +
+			       PDC_DIMM_APKT_PRD;
+	VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
+
+	i = PDC_DIMM_ATA_PKT;
+
+	/*
+	 * Set up ATA packet
+	 */
+	if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
+		buf[i++] = PDC_PKT_READ;
+	else if (tf->protocol == ATA_PROT_NODATA)
+		buf[i++] = PDC_PKT_NODATA;
+	else
+		buf[i++] = 0;
+	buf[i++] = 0;			/* reserved */
+	buf[i++] = portno + 1;		/* seq. id */
+	buf[i++] = 0xff;		/* delay seq. id */
+
+	/* dimm dma S/G, and next-pkt */
+	dw = i >> 2;
+	buf32[dw] = cpu_to_le32(dimm_sg);
+	buf32[dw + 1] = 0;
+	i += 8;
+
+	if (devno == 0)
+		dev_reg = ATA_DEVICE_OBS;
+	else
+		dev_reg = ATA_DEVICE_OBS | ATA_DEV1;
+
+	/* select device */
+	buf[i++] = (1 << 5) | PDC_PKT_CLEAR_BSY | ATA_REG_DEVICE;
+	buf[i++] = dev_reg;
+
+	/* device control register */
+	buf[i++] = (1 << 5) | PDC_REG_DEVCTL;
+	buf[i++] = tf->ctl;
+
+	return i;
+}
+
+static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
+				     unsigned int portno)
+{
+	unsigned int dw;
+	u32 tmp, *buf32 = (u32 *) buf;
+
+	unsigned int host_sg = PDC_20621_DIMM_BASE +
+			       (PDC_DIMM_WINDOW_STEP * portno) +
+			       PDC_DIMM_HOST_PRD;
+	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
+			       (PDC_DIMM_WINDOW_STEP * portno) +
+			       PDC_DIMM_HPKT_PRD;
+	VPRINTK("ENTER, dimm_sg == 0x%x, %d\n", dimm_sg, dimm_sg);
+	VPRINTK("host_sg == 0x%x, %d\n", host_sg, host_sg);
+
+	dw = PDC_DIMM_HOST_PKT >> 2;
+
+	/*
+	 * Set up Host DMA packet
+	 */
+	if ((tf->protocol == ATA_PROT_DMA) && (!(tf->flags & ATA_TFLAG_WRITE)))
+		tmp = PDC_PKT_READ;
+	else
+		tmp = 0;
+	tmp |= ((portno + 1 + 4) << 16);	/* seq. id */
+	tmp |= (0xff << 24);			/* delay seq. id */
+	buf32[dw + 0] = cpu_to_le32(tmp);
+	buf32[dw + 1] = cpu_to_le32(host_sg);
+	buf32[dw + 2] = cpu_to_le32(dimm_sg);
+	buf32[dw + 3] = 0;
+
+	VPRINTK("HOST PKT @ %x == (0x%x 0x%x 0x%x 0x%x)\n",
+		PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * portno) +
+			PDC_DIMM_HOST_PKT,
+		buf32[dw + 0],
+		buf32[dw + 1],
+		buf32[dw + 2],
+		buf32[dw + 3]);
+}
+
+static void pdc20621_fill_sg(struct ata_queued_cmd *qc)
+{
+	struct scatterlist *sg = qc->sg;
+	struct ata_port *ap = qc->ap;
+	struct pdc_port_priv *pp = ap->private_data;
+	void *mmio = ap->host_set->mmio_base;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+	unsigned int portno = ap->port_no;
+	unsigned int i, last, idx, total_len = 0, sgt_len;
+	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
+
+	VPRINTK("ata%u: ENTER\n", ap->id);
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	/*
+	 * Build S/G table
+	 */
+	last = qc->n_elem;
+	idx = 0;
+	for (i = 0; i < last; i++) {
+		buf[idx++] = cpu_to_le32(sg_dma_address(&sg[i]));
+		buf[idx++] = cpu_to_le32(sg_dma_len(&sg[i]));
+		total_len += sg[i].length;
+	}
+	buf[idx - 1] |= cpu_to_le32(ATA_PRD_EOT);
+	sgt_len = idx * 4;
+
+	/*
+	 * Build ATA, host DMA packets
+	 */
+	pdc20621_host_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+	pdc20621_host_pkt(&qc->tf, &pp->dimm_buf[0], portno);
+
+	pdc20621_ata_sg(&qc->tf, &pp->dimm_buf[0], portno, total_len);
+	i = pdc20621_ata_pkt(&qc->tf, qc->dev->devno, &pp->dimm_buf[0], portno);
+
+	if (qc->tf.flags & ATA_TFLAG_LBA48)
+		i = pdc_prep_lba48(&qc->tf, &pp->dimm_buf[0], i);
+	else
+		i = pdc_prep_lba28(&qc->tf, &pp->dimm_buf[0], i);
+
+	pdc_pkt_footer(&qc->tf, &pp->dimm_buf[0], i);
+
+	/* copy three S/G tables and two packets to DIMM MMIO window */
+	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP),
+		    &pp->dimm_buf, PDC_DIMM_HEADER_SZ);
+	memcpy_toio(dimm_mmio + (portno * PDC_DIMM_WINDOW_STEP) +
+		    PDC_DIMM_HOST_PRD,
+		    &pp->dimm_buf[PDC_DIMM_HEADER_SZ], sgt_len);
+
+	/* force host FIFO dump */
+	writel(0x00000001, mmio + PDC_20621_GENERAL_CTL);
+
+	readl(dimm_mmio);	/* MMIO PCI posting flush */
+
+	VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
+}
+
+static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
+				 unsigned int seq,
+				 u32 pkt_ofs)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_host_set *host_set = ap->host_set;
+	void *mmio = host_set->mmio_base;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+	readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
+
+	writel(pkt_ofs, mmio + PDC_HDMA_PKT_SUBMIT);
+	readl(mmio + PDC_HDMA_PKT_SUBMIT);	/* flush */
+}
+
+static void pdc20621_push_hdma(struct ata_queued_cmd *qc,
+				unsigned int seq,
+				u32 pkt_ofs)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_host_priv *pp = ap->host_set->private_data;
+	unsigned int idx = pp->hdma_prod & PDC_HDMA_Q_MASK;
+
+	if (!pp->doing_hdma) {
+		__pdc20621_push_hdma(qc, seq, pkt_ofs);
+		pp->doing_hdma = 1;
+		return;
+	}
+
+	pp->hdma[idx].qc = qc;
+	pp->hdma[idx].seq = seq;
+	pp->hdma[idx].pkt_ofs = pkt_ofs;
+	pp->hdma_prod++;
+}
+
+static void pdc20621_pop_hdma(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct pdc_host_priv *pp = ap->host_set->private_data;
+	unsigned int idx = pp->hdma_cons & PDC_HDMA_Q_MASK;
+
+	/* if nothing on queue, we're done */
+	if (pp->hdma_prod == pp->hdma_cons) {
+		pp->doing_hdma = 0;
+		return;
+	}
+
+	__pdc20621_push_hdma(pp->hdma[idx].qc, pp->hdma[idx].seq,
+			     pp->hdma[idx].pkt_ofs);
+	pp->hdma_cons++;
+}
+
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int port_no = ap->port_no;
+	struct pdc_host_priv *hpriv = ap->host_set->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+
+	dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
+	dimm_mmio += PDC_DIMM_HOST_PKT;
+
+	printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio));
+	printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4));
+	printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8));
+	printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12));
+}
+#else
+static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
+#endif /* ATA_VERBOSE_DEBUG */
+
+static void pdc20621_dma_setup(struct ata_queued_cmd *qc)
+{
+	/* nothing for now.  later, we will call standard
+	 * code in libata-core for ATAPI here */
+}
+
+static void pdc20621_dma_start(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct ata_host_set *host_set = ap->host_set;
+	unsigned int port_no = ap->port_no;
+	void *mmio = host_set->mmio_base;
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 seq = (u8) (port_no + 1);
+	unsigned int doing_hdma = 0, port_ofs;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	VPRINTK("ata%u: ENTER\n", ap->id);
+
+	port_ofs = PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
+
+	/* if writing, we (1) DMA to DIMM, then (2) do ATA command */
+	if (rw) {
+		doing_hdma = 1;
+		seq += 4;
+	}
+
+	wmb();			/* flush PRD, pkt writes */
+
+	if (doing_hdma) {
+		pdc20621_dump_hdma(qc);
+		pdc20621_push_hdma(qc, seq, port_ofs + PDC_DIMM_HOST_PKT);
+		VPRINTK("queued ofs 0x%x (%u), seq %u\n",
+			port_ofs + PDC_DIMM_HOST_PKT,
+			port_ofs + PDC_DIMM_HOST_PKT,
+			seq);
+	} else {
+		writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+		readl(mmio + PDC_20621_SEQCTL + (seq * 4));	/* flush */
+
+		writel(port_ofs + PDC_DIMM_ATA_PKT,
+		       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		VPRINTK("submitted ofs 0x%x (%u), seq %u\n",
+			port_ofs + PDC_DIMM_ATA_PKT,
+			port_ofs + PDC_DIMM_ATA_PKT,
+			seq);
+	}
+}
+
+static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
+                                          struct ata_queued_cmd *qc,
+					  unsigned int doing_hdma,
+					  void *mmio)
+{
+	unsigned int port_no = ap->port_no;
+	unsigned int port_ofs =
+		PDC_20621_DIMM_BASE + (PDC_DIMM_WINDOW_STEP * port_no);
+	u8 status;
+	unsigned int handled = 0;
+
+	VPRINTK("ENTER\n");
+
+	if ((qc->tf.protocol == ATA_PROT_DMA) &&	/* read */
+	    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+
+		/* step two - DMA from DIMM to host */
+		if (doing_hdma) {
+			VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
+				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+			pdc_dma_complete(ap, qc, 0);
+			pdc20621_pop_hdma(qc);
+		}
+
+		/* step one - exec ATA command */
+		else {
+			u8 seq = (u8) (port_no + 1 + 4);
+			VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
+				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+
+			/* submit hdma pkt */
+			pdc20621_dump_hdma(qc);
+			pdc20621_push_hdma(qc, seq,
+					   port_ofs + PDC_DIMM_HOST_PKT);
+		}
+		handled = 1;
+
+	} else if (qc->tf.protocol == ATA_PROT_DMA) {	/* write */
+
+		/* step one - DMA from host to DIMM */
+		if (doing_hdma) {
+			u8 seq = (u8) (port_no + 1);
+			VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
+				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+
+			/* submit ata pkt */
+			writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
+			readl(mmio + PDC_20621_SEQCTL + (seq * 4));
+			writel(port_ofs + PDC_DIMM_ATA_PKT,
+			       (void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+			readl((void *) ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
+		}
+
+		/* step two - execute ATA command */
+		else {
+			VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
+				readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
+			pdc_dma_complete(ap, qc, 0);
+			pdc20621_pop_hdma(qc);
+		}
+		handled = 1;
+
+	/* command completion, but no data xfer */
+	} else if (qc->tf.protocol == ATA_PROT_NODATA) {
+
+		status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+		DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
+		ata_qc_complete(qc, status);
+		handled = 1;
+
+	} else {
+		ap->stats.idle_irq++;
+	}
+
+	return handled;
+}
+
+static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	struct ata_port *ap;
+	u32 mask = 0;
+	unsigned int i, tmp, port_no;
+	unsigned int handled = 0;
+	void *mmio_base;
+
+	VPRINTK("ENTER\n");
+
+	if (!host_set || !host_set->mmio_base) {
+		VPRINTK("QUICK EXIT\n");
+		return IRQ_NONE;
+	}
+
+	mmio_base = host_set->mmio_base;
+
+	/* reading should also clear interrupts */
+	mmio_base += PDC_CHIP0_OFS;
+	mask = readl(mmio_base + PDC_20621_SEQMASK);
+	VPRINTK("mask == 0x%x\n", mask);
+
+	if (mask == 0xffffffff) {
+		VPRINTK("QUICK EXIT 2\n");
+		return IRQ_NONE;
+	}
+	mask &= 0xffff;		/* only 16 tags possible */
+	if (!mask) {
+		VPRINTK("QUICK EXIT 3\n");
+		return IRQ_NONE;
+	}
+
+        spin_lock(&host_set->lock);
+
+        for (i = 1; i < 9; i++) {
+		port_no = i - 1;
+		if (port_no > 3)
+			port_no -= 4;
+		if (port_no >= host_set->n_ports)
+			ap = NULL;
+		else
+			ap = host_set->ports[port_no];
+		tmp = mask & (1 << i);
+		VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
+		if (tmp && ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+			struct ata_queued_cmd *qc;
+
+			qc = ata_qc_from_tag(ap, ap->active_tag);
+			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+				handled += pdc20621_host_intr(ap, qc, (i > 4),
+							      mmio_base);
+		}
+	}
+
+        spin_unlock(&host_set->lock);
+
+	VPRINTK("mask == 0x%x\n", mask);
+
+	VPRINTK("EXIT\n");
+
+	return IRQ_RETVAL(handled);
+}
+
+static inline void pdc_dma_complete (struct ata_port *ap,
+                                     struct ata_queued_cmd *qc,
+				     int have_err)
+{
+	u8 err_bit = have_err ? ATA_ERR : 0;
+
+	/* get drive status; clear intr; complete txn */
+	ata_qc_complete(qc, ata_wait_idle(ap) | err_bit);
+}
+
+static void pdc_eng_timeout(struct ata_port *ap)
+{
+	u8 drv_stat;
+	struct ata_queued_cmd *qc;
+
+	DPRINTK("ENTER\n");
+
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (!qc) {
+		printk(KERN_ERR "ata%u: BUG: timeout without command\n",
+		       ap->id);
+		goto out;
+	}
+
+	/* hack alert!  We cannot use the supplied completion
+	 * function from inside the ->eh_strategy_handler() thread.
+	 * libata is the only user of ->eh_strategy_handler() in
+	 * any kernel, so the default scsi_done() assumes it is
+	 * not being called from the SCSI EH.
+	 */
+	qc->scsidone = scsi_finish_command;
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		printk(KERN_ERR "ata%u: DMA timeout\n", ap->id);
+		ata_qc_complete(qc, ata_wait_idle(ap) | ATA_ERR);
+		break;
+
+	case ATA_PROT_NODATA:
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat);
+
+		ata_qc_complete(qc, drv_stat);
+		break;
+
+	default:
+		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
+
+		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
+		       ap->id, qc->tf.command, drv_stat);
+
+		ata_qc_complete(qc, drv_stat);
+		break;
+	}
+
+out:
+	DPRINTK("EXIT\n");
+}
+
+static void pdc_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (tf->protocol != ATA_PROT_DMA)
+		ata_tf_load_mmio(ap, tf);
+}
+
+
+static void pdc_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (tf->protocol != ATA_PROT_DMA)
+		ata_exec_command_mmio(ap, tf);
+}
+
+
+static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+	port->cmd_addr		= base;
+	port->data_addr		= base;
+	port->feature_addr	=
+	port->error_addr	= base + 0x4;
+	port->nsect_addr	= base + 0x8;
+	port->lbal_addr		= base + 0xc;
+	port->lbam_addr		= base + 0x10;
+	port->lbah_addr		= base + 0x14;
+	port->device_addr	= base + 0x18;
+	port->command_addr	=
+	port->status_addr	= base + 0x1c;
+	port->altstatus_addr	=
+	port->ctl_addr		= base + 0x38;
+}
+
+
+#ifdef ATA_VERBOSE_DEBUG
+static void pdc20621_get_from_dimm(struct ata_probe_ent *pe, void *psource, 
+				   u32 offset, u32 size)
+{
+	u32 window_size;
+	u16 idx;
+	u8 page_mask;
+	long dist;
+	void *mmio = pe->mmio_base;
+	struct pdc_host_priv *hpriv = pe->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	page_mask = 0x00;	
+   	window_size = 0x2000 * 4; /* 32K byte uchar size */  
+	idx = (u16) (offset / window_size); 
+
+	writel(0x01, mmio + PDC_GENERAL_CTLR);
+	readl(mmio + PDC_GENERAL_CTLR);
+	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+	readl(mmio + PDC_DIMM_WINDOW_CTLR);
+
+	offset -= (idx * window_size);
+	idx++;
+	dist = ((long) (window_size - (offset + size))) >= 0 ? size : 
+		(long) (window_size - offset);
+	memcpy_fromio((char *) psource, (char *) (dimm_mmio + offset / 4), 
+		      dist);
+
+	psource += dist;    
+	size -= dist;
+	for (; (long) size >= (long) window_size ;) {
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+			      window_size / 4);
+		psource += window_size;
+		size -= window_size;
+		idx ++;
+	}
+
+	if (size) {
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_fromio((char *) psource, (char *) (dimm_mmio), 
+			      size / 4);
+	}
+}
+#endif
+
+
+static void pdc20621_put_to_dimm(struct ata_probe_ent *pe, void *psource, 
+				 u32 offset, u32 size)
+{
+	u32 window_size;
+	u16 idx;
+	u8 page_mask;
+	long dist;
+	void *mmio = pe->mmio_base;
+	struct pdc_host_priv *hpriv = pe->private_data;
+	void *dimm_mmio = hpriv->dimm_mmio;
+
+	/* hard-code chip #0 */   
+	mmio += PDC_CHIP0_OFS;
+
+	page_mask = 0x00;	
+   	window_size = 0x2000 * 4;       /* 32K byte uchar size */  
+	idx = (u16) (offset / window_size);
+
+	writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+	readl(mmio + PDC_DIMM_WINDOW_CTLR);
+	offset -= (idx * window_size); 
+	idx++;
+	dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
+		(long) (window_size - offset);
+	memcpy_toio((char *) (dimm_mmio + offset / 4), (char *) psource, dist);
+	writel(0x01, mmio + PDC_GENERAL_CTLR);
+	readl(mmio + PDC_GENERAL_CTLR);
+
+	psource += dist;    
+	size -= dist;
+	for (; (long) size >= (long) window_size ;) {
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_toio((char *) (dimm_mmio), (char *) psource, 
+			    window_size / 4);
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+		psource += window_size;
+		size -= window_size;
+		idx ++;
+	}
+    
+	if (size) {
+		writel(((idx) << page_mask), mmio + PDC_DIMM_WINDOW_CTLR);
+		readl(mmio + PDC_DIMM_WINDOW_CTLR);
+		memcpy_toio((char *) (dimm_mmio), (char *) psource, size / 4);
+		writel(0x01, mmio + PDC_GENERAL_CTLR);
+		readl(mmio + PDC_GENERAL_CTLR);
+	}
+}
+
+
+static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device, 
+				      u32 subaddr, u32 *pdata)
+{
+	void *mmio = pe->mmio_base;
+	u32 i2creg  = 0;
+	u32 status;     
+	u32 count =0;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	i2creg |= device << 24;
+	i2creg |= subaddr << 16;
+
+	/* Set the device and subaddress */
+	writel(i2creg, mmio + PDC_I2C_ADDR_DATA_OFFSET);
+	readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+
+	/* Write Control to perform read operation, mask int */
+	writel(PDC_I2C_READ | PDC_I2C_START | PDC_I2C_MASK_INT, 
+	       mmio + PDC_I2C_CONTROL_OFFSET);
+
+	for (count = 0; count <= 1000; count ++) {
+		status = readl(mmio + PDC_I2C_CONTROL_OFFSET);
+		if (status & PDC_I2C_COMPLETE) {
+			status = readl(mmio + PDC_I2C_ADDR_DATA_OFFSET);
+			break;
+		} else if (count == 1000)
+			return 0;
+	}
+
+	*pdata = (status >> 8) & 0x000000ff;
+	return 1;           
+}
+
+
+static int pdc20621_detect_dimm(struct ata_probe_ent *pe)
+{
+	u32 data=0 ;
+  	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+			     PDC_DIMM_SPD_SYSTEM_FREQ, &data)) {
+   		if (data == 100)
+			return 100;
+  	} else
+		return 0;
+ 	
+   	if (pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 9, &data)) {
+		if(data <= 0x75) 
+			return 133;
+   	} else
+		return 0;
+   	
+   	return 0;
+}
+
+
+static int pdc20621_prog_dimm0(struct ata_probe_ent *pe)
+{
+	u32 spd0[50];
+	u32 data = 0;
+   	int size, i;
+   	u8 bdimmsize; 
+   	void *mmio = pe->mmio_base;
+	static const struct {
+		unsigned int reg;
+		unsigned int ofs;
+	} pdc_i2c_read_data [] = {
+		{ PDC_DIMM_SPD_TYPE, 11 },		
+		{ PDC_DIMM_SPD_FRESH_RATE, 12 },
+		{ PDC_DIMM_SPD_COLUMN_NUM, 4 }, 
+		{ PDC_DIMM_SPD_ATTRIBUTE, 21 },
+		{ PDC_DIMM_SPD_ROW_NUM, 3 },
+		{ PDC_DIMM_SPD_BANK_NUM, 17 },
+		{ PDC_DIMM_SPD_MODULE_ROW, 5 },
+		{ PDC_DIMM_SPD_ROW_PRE_CHARGE, 27 },
+		{ PDC_DIMM_SPD_ROW_ACTIVE_DELAY, 28 },
+		{ PDC_DIMM_SPD_RAS_CAS_DELAY, 29 },
+		{ PDC_DIMM_SPD_ACTIVE_PRECHARGE, 30 },
+		{ PDC_DIMM_SPD_CAS_LATENCY, 18 },       
+	};
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	for(i=0; i<ARRAY_SIZE(pdc_i2c_read_data); i++)
+		pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS,
+				  pdc_i2c_read_data[i].reg, 
+				  &spd0[pdc_i2c_read_data[i].ofs]);
+  
+   	data |= (spd0[4] - 8) | ((spd0[21] != 0) << 3) | ((spd0[3]-11) << 4);
+   	data |= ((spd0[17] / 4) << 6) | ((spd0[5] / 2) << 7) | 
+		((((spd0[27] + 9) / 10) - 1) << 8) ;
+   	data |= (((((spd0[29] > spd0[28]) 
+		    ? spd0[29] : spd0[28]) + 9) / 10) - 1) << 10; 
+   	data |= ((spd0[30] - spd0[29] + 9) / 10 - 2) << 12;
+   
+   	if (spd0[18] & 0x08) 
+		data |= ((0x03) << 14);
+   	else if (spd0[18] & 0x04)
+		data |= ((0x02) << 14);
+   	else if (spd0[18] & 0x01)
+		data |= ((0x01) << 14);
+   	else
+		data |= (0 << 14);
+
+  	/* 
+	   Calculate the size of bDIMMSize (power of 2) and
+	   merge the DIMM size by program start/end address.
+	*/
+
+   	bdimmsize = spd0[4] + (spd0[5] / 2) + spd0[3] + (spd0[17] / 2) + 3;
+   	size = (1 << bdimmsize) >> 20;	/* size = xxx(MB) */
+   	data |= (((size / 16) - 1) << 16);
+   	data |= (0 << 23);
+	data |= 8;
+   	writel(data, mmio + PDC_DIMM0_CONTROL_OFFSET); 
+	readl(mmio + PDC_DIMM0_CONTROL_OFFSET);
+   	return size;                          
+}
+
+
+static unsigned int pdc20621_prog_dimm_global(struct ata_probe_ent *pe)
+{
+	u32 data, spd0;
+   	int error, i;
+   	void *mmio = pe->mmio_base;
+
+	/* hard-code chip #0 */
+   	mmio += PDC_CHIP0_OFS;
+
+   	/*
+	  Set To Default : DIMM Module Global Control Register (0x022259F1)
+	  DIMM Arbitration Disable (bit 20)
+	  DIMM Data/Control Output Driving Selection (bit12 - bit15)
+	  Refresh Enable (bit 17)
+	*/
+
+	data = 0x022259F1;   
+	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+	readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+
+	/* Turn on for ECC */
+	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+			  PDC_DIMM_SPD_TYPE, &spd0);
+	if (spd0 == 0x02) {
+		data |= (0x01 << 16);
+		writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+		readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		printk(KERN_ERR "Local DIMM ECC Enabled\n");
+   	}
+
+   	/* DIMM Initialization Select/Enable (bit 18/19) */
+   	data &= (~(1<<18));
+   	data |= (1<<19);
+   	writel(data, mmio + PDC_SDRAM_CONTROL_OFFSET);
+
+   	error = 1;                     
+   	for (i = 1; i <= 10; i++) {   /* polling ~5 secs */
+		data = readl(mmio + PDC_SDRAM_CONTROL_OFFSET);
+		if (!(data & (1<<19))) {
+	   		error = 0;
+	   		break;     
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout((i * 100) * HZ / 1000 + 1);
+   	}
+   	return error;
+}
+	
+
+static unsigned int pdc20621_dimm_init(struct ata_probe_ent *pe)
+{
+	int speed, size, length; 
+	u32 addr,spd0,pci_status;
+	u32 tmp=0;
+	u32 time_period=0;
+	u32 tcount=0;
+	u32 ticks=0;
+	u32 clock=0;
+	u32 fparam=0;
+   	void *mmio = pe->mmio_base;
+
+	/* hard-code chip #0 */
+   	mmio += PDC_CHIP0_OFS;
+
+	/* Initialize PLL based upon PCI Bus Frequency */
+
+	/* Initialize Time Period Register */
+	writel(0xffffffff, mmio + PDC_TIME_PERIOD);
+	time_period = readl(mmio + PDC_TIME_PERIOD);
+	VPRINTK("Time Period Register (0x40): 0x%x\n", time_period);
+
+	/* Enable timer */
+	writel(0x00001a0, mmio + PDC_TIME_CONTROL);
+	readl(mmio + PDC_TIME_CONTROL);
+
+	/* Wait 3 seconds */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(3 * HZ);
+
+	/* 
+	   When timer is enabled, counter is decreased every internal
+	   clock cycle.
+	*/
+
+	tcount = readl(mmio + PDC_TIME_COUNTER);
+	VPRINTK("Time Counter Register (0x44): 0x%x\n", tcount);
+
+	/* 
+	   If SX4 is on PCI-X bus, after 3 seconds, the timer counter
+	   register should be >= (0xffffffff - 3x10^8).
+	*/
+	if(tcount >= PCI_X_TCOUNT) {
+		ticks = (time_period - tcount);
+		VPRINTK("Num counters 0x%x (%d)\n", ticks, ticks);
+	
+		clock = (ticks / 300000);
+		VPRINTK("10 * Internal clk = 0x%x (%d)\n", clock, clock);
+		
+		clock = (clock * 33);
+		VPRINTK("10 * Internal clk * 33 = 0x%x (%d)\n", clock, clock);
+
+		/* PLL F Param (bit 22:16) */
+		fparam = (1400000 / clock) - 2;
+		VPRINTK("PLL F Param: 0x%x (%d)\n", fparam, fparam);
+		
+		/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
+		pci_status = (0x8a001824 | (fparam << 16));
+	} else
+		pci_status = PCI_PLL_INIT;
+
+	/* Initialize PLL. */
+	VPRINTK("pci_status: 0x%x\n", pci_status);
+	writel(pci_status, mmio + PDC_CTL_STATUS);
+	readl(mmio + PDC_CTL_STATUS);
+
+	/* 
+	   Read SPD of DIMM by I2C interface,
+	   and program the DIMM Module Controller.
+	*/
+ 	if (!(speed = pdc20621_detect_dimm(pe))) {
+		printk(KERN_ERR "Detect Local DIMM Fail\n");  
+		return 1;	/* DIMM error */
+   	}
+   	VPRINTK("Local DIMM Speed = %d\n", speed);
+
+   	/* Programming DIMM0 Module Control Register (index_CID0:80h) */ 
+   	size = pdc20621_prog_dimm0(pe);
+   	VPRINTK("Local DIMM Size = %dMB\n",size);
+
+   	/* Programming DIMM Module Global Control Register (index_CID0:88h) */ 
+   	if (pdc20621_prog_dimm_global(pe)) {
+		printk(KERN_ERR "Programming DIMM Module Global Control Register Fail\n");
+		return 1;
+   	}
+
+#ifdef ATA_VERBOSE_DEBUG
+	{
+		u8 test_parttern1[40] = {0x55,0xAA,'P','r','o','m','i','s','e',' ',
+  				'N','o','t',' ','Y','e','t',' ','D','e','f','i','n','e','d',' ',
+ 				 '1','.','1','0',
+  				'9','8','0','3','1','6','1','2',0,0};
+		u8 test_parttern2[40] = {0};
+
+		pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x10040, 40);
+		pdc20621_put_to_dimm(pe, (void *) test_parttern2, 0x40, 40);
+
+		pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x10040, 40);
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		       test_parttern2[1], &(test_parttern2[2]));
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x10040, 
+				       40);
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		       test_parttern2[1], &(test_parttern2[2]));
+
+		pdc20621_put_to_dimm(pe, (void *) test_parttern1, 0x40, 40);
+		pdc20621_get_from_dimm(pe, (void *) test_parttern2, 0x40, 40);
+		printk(KERN_ERR "%x, %x, %s\n", test_parttern2[0], 
+		       test_parttern2[1], &(test_parttern2[2]));
+	}
+#endif
+
+	/* ECC initiliazation. */
+
+	pdc20621_i2c_read(pe, PDC_DIMM0_SPD_DEV_ADDRESS, 
+			  PDC_DIMM_SPD_TYPE, &spd0);
+	if (spd0 == 0x02) {
+		VPRINTK("Start ECC initialization\n");
+		addr = 0;
+		length = size * 1024 * 1024;
+		while (addr < length) {
+			pdc20621_put_to_dimm(pe, (void *) &tmp, addr, 
+					     sizeof(u32));
+			addr += sizeof(u32);
+		}
+		VPRINTK("Finish ECC initialization\n");
+	}
+	return 0;
+}
+
+
+static void pdc_20621_init(struct ata_probe_ent *pe)
+{
+	u32 tmp;
+	void *mmio = pe->mmio_base;
+
+	/* hard-code chip #0 */
+	mmio += PDC_CHIP0_OFS;
+
+	/*
+	 * Select page 0x40 for our 32k DIMM window
+	 */
+	tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000;
+	tmp |= PDC_PAGE_WINDOW;	/* page 40h; arbitrarily selected */
+	writel(tmp, mmio + PDC_20621_DIMM_WINDOW);
+
+	/*
+	 * Reset Host DMA
+	 */
+	tmp = readl(mmio + PDC_HDMA_CTLSTAT);
+	tmp |= PDC_RESET;
+	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
+	readl(mmio + PDC_HDMA_CTLSTAT);		/* flush */
+
+	udelay(10);
+
+	tmp = readl(mmio + PDC_HDMA_CTLSTAT);
+	tmp &= ~PDC_RESET;
+	writel(tmp, mmio + PDC_HDMA_CTLSTAT);
+	readl(mmio + PDC_HDMA_CTLSTAT);		/* flush */
+}
+
+static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	unsigned long base;
+	void *mmio_base, *dimm_mmio = NULL;
+	struct pdc_host_priv *hpriv = NULL;
+	unsigned int board_idx = (unsigned int) ent->driver_data;
+	int rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	/*
+	 * If this driver happens to only be useful on Apple's K2, then
+	 * we should check that here as it has a normal Serverworks ID
+	 */
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	mmio_base = ioremap(pci_resource_start(pdev, 3),
+		            pci_resource_len(pdev, 3));
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+	base = (unsigned long) mmio_base;
+
+	hpriv = kmalloc(sizeof(*hpriv), GFP_KERNEL);
+	if (!hpriv) {
+		rc = -ENOMEM;
+		goto err_out_iounmap;
+	}
+	memset(hpriv, 0, sizeof(*hpriv));
+
+	dimm_mmio = ioremap(pci_resource_start(pdev, 4),
+			    pci_resource_len(pdev, 4));
+	if (!dimm_mmio) {
+		kfree(hpriv);
+		rc = -ENOMEM;
+		goto err_out_iounmap;
+	}
+
+	hpriv->dimm_mmio = dimm_mmio;
+
+	probe_ent->sht		= pdc_port_info[board_idx].sht;
+	probe_ent->host_flags	= pdc_port_info[board_idx].host_flags;
+	probe_ent->pio_mask	= pdc_port_info[board_idx].pio_mask;
+	probe_ent->udma_mask	= pdc_port_info[board_idx].udma_mask;
+	probe_ent->port_ops	= pdc_port_info[board_idx].port_ops;
+
+       	probe_ent->irq = pdev->irq;
+       	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->mmio_base = mmio_base;
+
+	probe_ent->private_data = hpriv;
+	base += PDC_CHIP0_OFS;
+
+	pdc_sata_setup_port(&probe_ent->port[0], base + 0x200);
+	pdc_sata_setup_port(&probe_ent->port[1], base + 0x280);
+
+	/* notice 4-port boards */
+	switch (board_idx) {
+	case board_20621:
+       		probe_ent->n_ports = 4;
+
+		pdc_sata_setup_port(&probe_ent->port[2], base + 0x300);
+		pdc_sata_setup_port(&probe_ent->port[3], base + 0x380);
+		break;
+	default:
+		BUG();
+		break;
+	}
+
+	pci_set_master(pdev);
+
+	/* initialize adapter */
+	/* initialize local dimm */
+	if (pdc20621_dimm_init(probe_ent)) {
+		rc = -ENOMEM;
+		goto err_out_iounmap_dimm;
+	}
+	pdc_20621_init(probe_ent);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_iounmap_dimm:		/* only get to this label if 20621 */
+	kfree(hpriv);
+	iounmap(dimm_mmio);
+err_out_iounmap:
+	iounmap(mmio_base);
+err_out_free_ent:
+	kfree(probe_ent);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+
+static int __init pdc_sata_init(void)
+{
+	int rc;
+
+	rc = pci_module_init(&pdc_sata_pci_driver);
+	if (rc)
+		return rc;
+
+	rc = scsi_register_module(MODULE_SCSI_HA, &pdc_sata_sht);
+	if (rc) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	return 0;
+
+err_out:
+	pci_unregister_driver(&pdc_sata_pci_driver);
+	return rc;
+}
+
+
+static void __exit pdc_sata_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &pdc_sata_sht);
+	pci_unregister_driver(&pdc_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("Promise SATA low-level driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, pdc_sata_pci_tbl);
+
+module_init(pdc_sata_init);
+module_exit(pdc_sata_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_via.c linux-2.4.27-rc4/drivers/scsi/sata_via.c
--- linux-2.4.26/drivers/scsi/sata_via.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_via.c	2004-07-30 16:31:37.000000000 +0000
@@ -0,0 +1,303 @@
+/*
+   sata_via.c - VIA Serial ATA controllers
+
+   Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+   		   Please ALWAYS copy linux-ide@vger.kernel.org
+ 		   on emails.
+
+   Copyright 2003-2004 Red Hat, Inc.  All rights reserved.
+   Copyright 2003-2004 Jeff Garzik
+
+   The contents of this file are subject to the Open
+   Software License version 1.1 that can be found at
+   http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+   by reference.
+
+   Alternatively, the contents of this file may be used under the terms
+   of the GNU General Public License version 2 (the "GPL") as distributed
+   in the kernel source COPYING file, in which case the provisions of
+   the GPL are applicable instead of the above.  If you wish to allow
+   the use of your version of this file only under the terms of the
+   GPL and not to allow others to use your version of this file under
+   the OSL, indicate your decision by deleting the provisions above and
+   replace them with the notice and other provisions required by the GPL.
+   If you do not delete the provisions above, a recipient may use your
+   version of this file under either the OSL or the GPL.
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+#include <asm/io.h>
+
+#define DRV_NAME	"sata_via"
+#define DRV_VERSION	"0.20"
+
+enum {
+	via_sata		= 0,
+
+	SATA_CHAN_ENAB		= 0x40, /* SATA channel enable */
+	SATA_INT_GATE		= 0x41, /* SATA interrupt gating */
+	SATA_NATIVE_MODE	= 0x42, /* Native mode enable */
+	SATA_PATA_SHARING	= 0x49, /* PATA/SATA sharing func ctrl */
+
+	PORT0			= (1 << 1),
+	PORT1			= (1 << 0),
+
+	ENAB_ALL		= PORT0 | PORT1,
+
+	INT_GATE_ALL		= PORT0 | PORT1,
+
+	NATIVE_MODE_ALL		= (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
+
+	SATA_EXT_PHY		= (1 << 6), /* 0==use PATA, 1==ext phy */
+	SATA_2DEV		= (1 << 5), /* SATA is master/slave */
+};
+
+static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static struct pci_device_id svia_pci_tbl[] = {
+	{ 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata },
+
+	{ }	/* terminate list */
+};
+
+static struct pci_driver svia_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= svia_pci_tbl,
+	.probe			= svia_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+static Scsi_Host_Template svia_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+static struct ata_port_operations svia_sata_ops = {
+	.port_disable		= ata_port_disable,
+
+	.tf_load		= ata_tf_load_pio,
+	.tf_read		= ata_tf_read_pio,
+	.check_status		= ata_check_status_pio,
+	.exec_command		= ata_exec_command_pio,
+
+	.phy_reset		= sata_phy_reset,
+
+	.bmdma_setup            = ata_bmdma_setup_pio,
+	.bmdma_start            = ata_bmdma_start_pio,
+	.fill_sg		= ata_fill_sg,
+	.eng_timeout		= ata_eng_timeout,
+
+	.irq_handler		= ata_interrupt,
+
+	.scr_read		= svia_scr_read,
+	.scr_write		= svia_scr_write,
+
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+MODULE_AUTHOR("Jeff Garzik");
+MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, svia_pci_tbl);
+
+static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+	return inl(ap->ioaddr.scr_addr + (4 * sc_reg));
+}
+
+static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+	if (sc_reg > SCR_CONTROL)
+		return;
+	outl(val, ap->ioaddr.scr_addr + (4 * sc_reg));
+}
+
+static const unsigned int svia_bar_sizes[] = {
+	8, 4, 8, 4, 16, 256
+};
+
+static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
+{
+	return addr + (port * 128);
+}
+
+static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	unsigned int i;
+	int rc;
+	struct ata_probe_ent *probe_ent;
+	u8 tmp8;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
+	if (tmp8 & SATA_2DEV) {
+		printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
+		       pci_name(pdev), (int) tmp8);
+		rc = -EIO;
+		goto err_out_regions;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
+		if ((pci_resource_start(pdev, i) == 0) ||
+		    (pci_resource_len(pdev, i) < svia_bar_sizes[i])) {
+			printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
+			       pci_name(pdev), i,
+			       pci_resource_start(pdev, i),
+			       pci_resource_len(pdev, i));
+			rc = -ENODEV;
+			goto err_out_regions;
+		}
+
+	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (!probe_ent) {
+		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
+		       pci_name(pdev));
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	INIT_LIST_HEAD(&probe_ent->node);
+	probe_ent->pdev = pdev;
+	probe_ent->sht = &svia_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
+				ATA_FLAG_NO_LEGACY;
+	probe_ent->port_ops = &svia_sata_ops;
+	probe_ent->n_ports = 2;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->pio_mask = 0x1f;
+	probe_ent->udma_mask = 0x7f;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	ata_std_ports(&probe_ent->port[0]);
+	probe_ent->port[0].altstatus_addr =
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+	probe_ent->port[0].scr_addr =
+		svia_scr_addr(pci_resource_start(pdev, 5), 0);
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	ata_std_ports(&probe_ent->port[1]);
+	probe_ent->port[1].altstatus_addr =
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+	probe_ent->port[1].scr_addr =
+		svia_scr_addr(pci_resource_start(pdev, 5), 1);
+
+	pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
+	printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
+	       pci_name(pdev),
+	       (int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
+
+	/* make sure SATA channels are enabled */
+	pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
+	if ((tmp8 & ENAB_ALL) != ENAB_ALL) {
+		printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
+		       pci_name(pdev), (int) tmp8);
+		tmp8 |= ENAB_ALL;
+		pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
+	}
+
+	/* make sure interrupts for each channel sent to us */
+	pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
+	if ((tmp8 & INT_GATE_ALL) != INT_GATE_ALL) {
+		printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
+		       pci_name(pdev), (int) tmp8);
+		tmp8 |= INT_GATE_ALL;
+		pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
+	}
+
+	/* make sure native mode is enabled */
+	pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
+	if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
+		printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
+		       pci_name(pdev), (int) tmp8);
+		tmp8 |= NATIVE_MODE_ALL;
+		pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
+	}
+
+	pci_set_master(pdev);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+static int __init svia_init(void)
+{
+	int rc;
+
+	rc = pci_module_init(&svia_pci_driver);
+	if (rc)
+		return rc;
+	
+	rc = scsi_register_module(MODULE_SCSI_HA, &svia_sht);
+	if (rc) {
+		pci_unregister_driver(&svia_pci_driver);
+		/* TODO: does scsi_register_module return errno val? */
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit svia_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &svia_sht);
+	pci_unregister_driver(&svia_pci_driver);
+}
+
+module_init(svia_init);
+module_exit(svia_exit);
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sata_vsc.c linux-2.4.27-rc4/drivers/scsi/sata_vsc.c
--- linux-2.4.26/drivers/scsi/sata_vsc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sata_vsc.c	2004-07-30 16:29:15.000000000 +0000
@@ -0,0 +1,401 @@
+/*
+ *  sata_vsc.c - Vitesse VSC7174 4 port DPA SATA
+ *
+ *  Maintained by:  Jeremy Higdon @ SGI
+ * 		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2004 SGI
+ *
+ *  Bits from Jeff Garzik, Copyright RedHat, Inc.
+ *
+ *  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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "scsi.h"
+#include <scsi/scsi_host.h>
+#include <linux/libata.h>
+
+#define DRV_NAME	"sata_vsc"
+#define DRV_VERSION	"0.01"
+
+/* Interrupt register offsets (from chip base address) */
+#define VSC_SATA_INT_STAT_OFFSET	0x00
+#define VSC_SATA_INT_MASK_OFFSET	0x04
+
+/* Taskfile registers offsets */
+#define VSC_SATA_TF_CMD_OFFSET		0x00
+#define VSC_SATA_TF_DATA_OFFSET		0x00
+#define VSC_SATA_TF_ERROR_OFFSET	0x04
+#define VSC_SATA_TF_FEATURE_OFFSET	0x06
+#define VSC_SATA_TF_NSECT_OFFSET	0x08
+#define VSC_SATA_TF_LBAL_OFFSET		0x0c
+#define VSC_SATA_TF_LBAM_OFFSET		0x10
+#define VSC_SATA_TF_LBAH_OFFSET		0x14
+#define VSC_SATA_TF_DEVICE_OFFSET	0x18
+#define VSC_SATA_TF_STATUS_OFFSET	0x1c
+#define VSC_SATA_TF_COMMAND_OFFSET	0x1d
+#define VSC_SATA_TF_ALTSTATUS_OFFSET	0x28
+#define VSC_SATA_TF_CTL_OFFSET		0x29
+
+/* DMA base */
+#define VSC_SATA_UP_DESCRIPTOR_OFFSET	0x64
+#define VSC_SATA_UP_DATA_BUFFER_OFFSET	0x6C
+#define VSC_SATA_DMA_CMD_OFFSET		0x70
+
+/* SCRs base */
+#define VSC_SATA_SCR_STATUS_OFFSET	0x100
+#define VSC_SATA_SCR_ERROR_OFFSET	0x104
+#define VSC_SATA_SCR_CONTROL_OFFSET	0x108
+
+/* Port stride */
+#define VSC_SATA_PORT_OFFSET		0x200
+
+
+static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+	if (sc_reg > SCR_CONTROL)
+		return 0xffffffffU;
+	return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
+			       u32 val)
+{
+	if (sc_reg > SCR_CONTROL)
+		return;
+	writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4));
+}
+
+
+static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
+{
+	unsigned long mask_addr;
+	u8 mask;
+
+	mask_addr = (unsigned long) ap->host_set->mmio_base +
+		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
+	mask = readb(mask_addr);
+	if (ctl & ATA_NIEN)
+		mask |= 0x80;
+	else
+		mask &= 0x7F;
+	writeb(mask, mask_addr);
+}
+
+
+static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
+
+	/*
+	 * The only thing the ctl register is used for is SRST.
+	 * That is not enabled or disabled via tf_load.
+	 * However, if ATA_NIEN is changed, then we need to change the interrupt register.
+	 */
+	if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) {
+		ap->last_ctl = tf->ctl;
+		vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN);
+	}
+	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
+		writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr);
+		writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
+		writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr);
+		writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr);
+		writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr);
+	} else if (is_addr) {
+		writew(tf->feature, ioaddr->feature_addr);
+		writew(tf->nsect, ioaddr->nsect_addr);
+		writew(tf->lbal, ioaddr->lbal_addr);
+		writew(tf->lbam, ioaddr->lbam_addr);
+		writew(tf->lbah, ioaddr->lbah_addr);
+	}
+
+	if (tf->flags & ATA_TFLAG_DEVICE)
+		writeb(tf->device, ioaddr->device_addr);
+
+	ata_wait_idle(ap);
+}
+
+
+static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+	u16 nsect, lbal, lbam, lbah;
+
+	nsect = tf->nsect = readw(ioaddr->nsect_addr);
+	lbal = tf->lbal = readw(ioaddr->lbal_addr);
+	lbam = tf->lbam = readw(ioaddr->lbam_addr);
+	lbah = tf->lbah = readw(ioaddr->lbah_addr);
+	tf->device = readw(ioaddr->device_addr);
+
+	if (tf->flags & ATA_TFLAG_LBA48) {
+		tf->hob_feature = readb(ioaddr->error_addr);
+		tf->hob_nsect = nsect >> 8;
+		tf->hob_lbal = lbal >> 8;
+		tf->hob_lbam = lbam >> 8;
+		tf->hob_lbah = lbah >> 8;
+        }
+}
+
+
+/*
+ * vsc_sata_interrupt
+ *
+ * Read the interrupt register and process for the devices that have them pending.
+ */
+irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	unsigned int i;
+	unsigned int handled = 0;
+	u32 int_status;
+
+	spin_lock(&host_set->lock);
+
+	int_status = readl(host_set->mmio_base + VSC_SATA_INT_STAT_OFFSET);
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		if (int_status & ((u32) 0xFF << (8 * i))) {
+			struct ata_port *ap;
+
+			ap = host_set->ports[i];
+			if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) {
+				struct ata_queued_cmd *qc;
+
+				qc = ata_qc_from_tag(ap, ap->active_tag);
+				if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+					handled += ata_host_intr(ap, qc);
+			}
+		}
+	}
+
+	spin_unlock(&host_set->lock);
+
+	return IRQ_RETVAL(handled);
+}
+
+
+static Scsi_Host_Template vsc_sata_sht = {
+	.module			= THIS_MODULE,
+	.name			= DRV_NAME,
+	.detect			= ata_scsi_detect,
+	.release		= ata_scsi_release,
+	.queuecommand		= ata_scsi_queuecmd,
+	.eh_strategy_handler	= ata_scsi_error,
+	.can_queue		= ATA_DEF_QUEUE,
+	.this_id		= ATA_SHT_THIS_ID,
+	.sg_tablesize		= LIBATA_MAX_PRD,
+	.max_sectors		= ATA_MAX_SECTORS,
+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+	.use_new_eh_code	= ATA_SHT_NEW_EH_CODE,
+	.emulated		= ATA_SHT_EMULATED,
+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+	.proc_name		= DRV_NAME,
+	.bios_param		= ata_std_bios_param,
+};
+
+
+static struct ata_port_operations vsc_sata_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= vsc_sata_tf_load,
+	.tf_read		= vsc_sata_tf_read,
+	.exec_command		= ata_exec_command_mmio,
+	.check_status		= ata_check_status_mmio,
+	.phy_reset		= sata_phy_reset,
+	.bmdma_setup            = ata_bmdma_setup_mmio,
+	.bmdma_start            = ata_bmdma_start_mmio,
+	.fill_sg		= ata_fill_sg,
+	.eng_timeout		= ata_eng_timeout,
+	.irq_handler		= vsc_sata_interrupt,
+	.scr_read		= vsc_sata_scr_read,
+	.scr_write		= vsc_sata_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+};
+
+static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
+{
+	port->cmd_addr		= base + VSC_SATA_TF_CMD_OFFSET;
+	port->data_addr		= base + VSC_SATA_TF_DATA_OFFSET;
+	port->error_addr	= base + VSC_SATA_TF_ERROR_OFFSET;
+	port->feature_addr	= base + VSC_SATA_TF_FEATURE_OFFSET;
+	port->nsect_addr	= base + VSC_SATA_TF_NSECT_OFFSET;
+	port->lbal_addr		= base + VSC_SATA_TF_LBAL_OFFSET;
+	port->lbam_addr		= base + VSC_SATA_TF_LBAM_OFFSET;
+	port->lbah_addr		= base + VSC_SATA_TF_LBAH_OFFSET;
+	port->device_addr	= base + VSC_SATA_TF_DEVICE_OFFSET;
+	port->status_addr	= base + VSC_SATA_TF_STATUS_OFFSET;
+	port->command_addr	= base + VSC_SATA_TF_COMMAND_OFFSET;
+	port->altstatus_addr	= base + VSC_SATA_TF_ALTSTATUS_OFFSET;
+	port->ctl_addr		= base + VSC_SATA_TF_CTL_OFFSET;
+	port->bmdma_addr	= base + VSC_SATA_DMA_CMD_OFFSET;
+	port->scr_addr		= base + VSC_SATA_SCR_STATUS_OFFSET;
+	writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
+	writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
+}
+
+
+static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	static int printed_version;
+	struct ata_probe_ent *probe_ent = NULL;
+	unsigned long base;
+	void *mmio_base;
+	int rc;
+
+	if (!printed_version++)
+		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+
+	rc = pci_enable_device(pdev);
+	if (rc)
+		return rc;
+
+	/*
+	 * Check if we have needed resource mapped.
+	 */
+	if (pci_resource_len(pdev, 0) == 0) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out;
+
+	/*
+	 * Use 32 bit DMA mask, because 64 bit address support is poor.
+	 */
+	rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL);
+	if (rc)
+		goto err_out_regions;
+
+	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (probe_ent == NULL) {
+		rc = -ENOMEM;
+		goto err_out_regions;
+	}
+	memset(probe_ent, 0, sizeof(*probe_ent));
+	probe_ent->pdev = pdev;
+	INIT_LIST_HEAD(&probe_ent->node);
+
+	mmio_base = ioremap(pci_resource_start(pdev, 0),
+		            pci_resource_len(pdev, 0));
+	if (mmio_base == NULL) {
+		rc = -ENOMEM;
+		goto err_out_free_ent;
+	}
+	base = (unsigned long) mmio_base;
+
+	/*
+	 * Due to a bug in the chip, the default cache line size can't be used
+	 */
+	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
+
+	probe_ent->sht = &vsc_sata_sht;
+	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET;
+	probe_ent->port_ops = &vsc_sata_ops;
+	probe_ent->n_ports = 4;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+	probe_ent->mmio_base = mmio_base;
+
+	/* We don't care much about the PIO/UDMA masks, but the core won't like us
+	 * if we don't fill these
+	 */
+	probe_ent->pio_mask = 0x1f;
+	probe_ent->udma_mask = 0x7f;
+
+	/* We have 4 ports per PCI function */
+	vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET);
+	vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET);
+
+	pci_set_master(pdev);
+
+	ata_add_to_probe_list(probe_ent);
+
+	return 0;
+
+err_out_free_ent:
+	kfree(probe_ent);
+err_out_regions:
+	pci_release_regions(pdev);
+err_out:
+	pci_disable_device(pdev);
+	return rc;
+}
+
+
+/*
+ * 0x1725/0x7174 is the Vitesse VSC-7174
+ * 0x8086/0x3200 is the Intel 31244, which is supposed to be identical
+ * compatibility is untested as of yet
+ */
+static struct pci_device_id vsc_sata_pci_tbl[] = {
+	{ 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
+	{ 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
+	{ }
+};
+
+
+static struct pci_driver vsc_sata_pci_driver = {
+	.name			= DRV_NAME,
+	.id_table		= vsc_sata_pci_tbl,
+	.probe			= vsc_sata_init_one,
+	.remove			= ata_pci_remove_one,
+};
+
+
+static int __init vsc_sata_init(void)
+{
+	int rc;
+
+	DPRINTK("pci_module_init\n");
+	rc = pci_module_init(&vsc_sata_pci_driver);
+	if (rc)
+		return rc;
+
+	DPRINTK("scsi_register_host\n");
+	rc = scsi_register_module(MODULE_SCSI_HA, &vsc_sata_sht);
+	if (rc) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	DPRINTK("done\n");
+	return 0;
+
+err_out:
+	pci_unregister_driver(&vsc_sata_pci_driver);
+	return rc;
+}
+
+
+static void __exit vsc_sata_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &vsc_sata_sht);
+	pci_unregister_driver(&vsc_sata_pci_driver);
+}
+
+
+MODULE_AUTHOR("Jeremy Higdon");
+MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl);
+
+module_init(vsc_sata_init);
+module_exit(vsc_sata_exit);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/scsi_scan.c linux-2.4.27-rc4/drivers/scsi/scsi_scan.c
--- linux-2.4.26/drivers/scsi/scsi_scan.c	2004-04-14 13:05:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/scsi_scan.c	2004-07-30 16:30:26.000000000 +0000
@@ -148,7 +148,7 @@ static struct dev_info device_list[] =
 	{"EMULEX", "MD21/S2     ESDI", "*", BLIST_SINGLELUN},
 	{"CANON", "IPUBJD", "*", BLIST_SPARSELUN},
 	{"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN},
-	{"DEC","HSG80","*", BLIST_FORCELUN | BLIST_NOSTARTONADD},
+	{"DEC","HSG80","*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_NOSTARTONADD},
 	{"COMPAQ","LOGICAL VOLUME","*", BLIST_FORCELUN},
 	{"COMPAQ","CR3500","*", BLIST_FORCELUN},
 	{"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/scsi/sr.c linux-2.4.27-rc4/drivers/scsi/sr.c
--- linux-2.4.26/drivers/scsi/sr.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.27-rc4/drivers/scsi/sr.c	2004-07-30 16:26:42.000000000 +0000
@@ -1,6 +1,7 @@
 /*
  *  sr.c Copyright (C) 1992 David Giller
  *           Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
+ *       Copyright (C) 2004 Iomega Corp
  *
  *  adapted from:
  *      sd.c Copyright (C) 1992 Drew Eckhardt
@@ -128,7 +129,7 @@ static struct cdrom_device_ops sr_dops =
 				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
 				CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS |
 				CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
-				CDC_DVD_RAM | CDC_GENERIC_PACKET,
+				CDC_DVD_RAM | CDC_GENERIC_PACKET | CDC_RAM,
 	generic_packet:		sr_packet,
 };
 
@@ -693,7 +694,7 @@ void get_capabilities(int i)
 {
 	unsigned char cmd[6];
 	unsigned char *buffer;
-	int rc, n;
+	int rc, n, ram_write=0;
 
 	static char *loadmech[] =
 	{
@@ -731,6 +732,11 @@ void get_capabilities(int i)
 		printk("sr%i: scsi-1 drive\n", i);
 		return;
 	}
+	if (cdrom_is_random_writable(&scsi_CDs[i].cdi, &ram_write))
+		scsi_CDs[i].cdi.mask |= CDC_RAM;
+	if (!ram_write)
+		scsi_CDs[i].cdi.mask |= CDC_RAM;
+
 	n = buffer[3] + 4;
 	scsi_CDs[i].cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176;
 	scsi_CDs[i].readcd_known = 1;
@@ -754,8 +760,6 @@ void get_capabilities(int i)
 	if ((buffer[n + 3] & 0x20) == 0) {
 		/* can't write DVD-RAM media */
 		scsi_CDs[i].cdi.mask |= CDC_DVD_RAM;
-	} else {
-		scsi_CDs[i].device->writeable = 1;
 	}
 	if ((buffer[n + 3] & 0x10) == 0)
 		/* can't write DVD-R media */
@@ -780,6 +784,13 @@ void get_capabilities(int i)
 	/*else    I don't think it can close its tray
 	   scsi_CDs[i].cdi.mask |= CDC_CLOSE_TRAY; */
 
+	/*
+	 * if DVD-RAM of MRW-W, we are randomly writeable
+	 */
+	if ((scsi_CDs[i].cdi.mask & (CDC_DVD_RAM | CDC_RAM)) !=
+	    (CDC_DVD_RAM | CDC_RAM))
+		scsi_CDs[i].device->writeable = 1;
+
 	scsi_free(buffer, 512);
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/724hwmcode.h linux-2.4.27-rc4/drivers/sound/724hwmcode.h
--- linux-2.4.26/drivers/sound/724hwmcode.h	2000-11-12 02:33:13.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/724hwmcode.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,1575 +0,0 @@
-//=============================================================================
-// Copyright (c) 1997-1999	Yamaha Corporation.	All Rights Reserved.
-//
-//	Title:
-//		hwmcode.c
-//	Desc:
-//		micro-code for CTRL & DSP
-//=============================================================================
-#ifndef _HWMCODE_
-#define _HWMCODE_
-
-static unsigned long int	DspInst[] __initdata = {
-	0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
-	0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
-	0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
-	0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000
-};
-
-static unsigned long int	CntrlInst[] __initdata = {
-	0x000007, 0x240007, 0x0C0007, 0x1C0007,
-	0x060007, 0x700002, 0x000020, 0x030040,
-	0x007104, 0x004286, 0x030040, 0x000F0D,
-	0x000810, 0x20043A, 0x000282, 0x00020D,
-	0x000810, 0x20043A, 0x001282, 0x200E82,
-	0x001A82, 0x032D0D, 0x000810, 0x10043A,
-	0x02D38D, 0x000810, 0x18043A, 0x00010D,
-	0x020015, 0x0000FD, 0x000020, 0x038860,
-	0x039060, 0x038060, 0x038040, 0x038040,
-	0x038040, 0x018040, 0x000A7D, 0x038040,
-	0x038040, 0x018040, 0x200402, 0x000882,
-	0x08001A, 0x000904, 0x015986, 0x000007,
-	0x260007, 0x000007, 0x000007, 0x018A06,
-	0x000007, 0x030C8D, 0x000810, 0x18043A,
-	0x260007, 0x00087D, 0x018042, 0x00160A,
-	0x04A206, 0x000007, 0x00218D, 0x000810,
-	0x08043A, 0x21C206, 0x000007, 0x0007FD,
-	0x018042, 0x08000A, 0x000904, 0x029386,
-	0x000195, 0x090D04, 0x000007, 0x000820,
-	0x0000F5, 0x000B7D, 0x01F060, 0x0000FD,
-	0x032206, 0x018040, 0x000A7D, 0x038042,
-	0x13804A, 0x18000A, 0x001820, 0x059060,
-	0x058860, 0x018040, 0x0000FD, 0x018042,
-	0x70000A, 0x000115, 0x071144, 0x032386,
-	0x030000, 0x007020, 0x034A06, 0x018040,
-	0x00348D, 0x000810, 0x08043A, 0x21EA06,
-	0x000007, 0x02D38D, 0x000810, 0x18043A,
-	0x018206, 0x000007, 0x240007, 0x000F8D,
-	0x000810, 0x00163A, 0x002402, 0x005C02,
-	0x0028FD, 0x000020, 0x018040, 0x08000D,
-	0x000815, 0x510984, 0x000007, 0x00004D,
-	0x000E5D, 0x000E02, 0x00418D, 0x000810,
-	0x08043A, 0x2C8A06, 0x000007, 0x00008D,
-	0x000924, 0x000F02, 0x00458D, 0x000810,
-	0x08043A, 0x2C8A06, 0x000007, 0x00387D,
-	0x018042, 0x08000A, 0x001015, 0x010984,
-	0x018386, 0x000007, 0x01AA06, 0x000007,
-	0x0008FD, 0x018042, 0x18000A, 0x001904,
-	0x218086, 0x280007, 0x001810, 0x28043A,
-	0x280C02, 0x00000D, 0x000810, 0x28143A,
-	0x08808D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00020D, 0x189904, 0x000007,
-	0x00402D, 0x0000BD, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x055A86, 0x000007,
-	0x000100, 0x000A20, 0x00047D, 0x018040,
-	0x018042, 0x20000A, 0x003015, 0x012144,
-	0x034986, 0x000007, 0x002104, 0x034986,
-	0x000007, 0x000F8D, 0x000810, 0x280C3A,
-	0x023944, 0x06C986, 0x000007, 0x001810,
-	0x28043A, 0x08810D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x002810, 0x78003A,
-	0x00688D, 0x000810, 0x08043A, 0x288A06,
-	0x000007, 0x00400D, 0x001015, 0x189904,
-	0x292904, 0x393904, 0x000007, 0x060206,
-	0x000007, 0x0004F5, 0x00007D, 0x000020,
-	0x00008D, 0x010860, 0x018040, 0x00047D,
-	0x038042, 0x21804A, 0x18000A, 0x021944,
-	0x215886, 0x000007, 0x004075, 0x71F104,
-	0x000007, 0x010042, 0x28000A, 0x002904,
-	0x212086, 0x000007, 0x003C0D, 0x30A904,
-	0x000007, 0x00077D, 0x018042, 0x08000A,
-	0x000904, 0x07DA86, 0x00057D, 0x002820,
-	0x03B060, 0x07F206, 0x018040, 0x003020,
-	0x03A860, 0x018040, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x07FA86, 0x000007,
-	0x00057D, 0x018042, 0x28040A, 0x000E8D,
-	0x000810, 0x280C3A, 0x00000D, 0x000810,
-	0x28143A, 0x09000D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x003DFD, 0x000020,
-	0x018040, 0x00107D, 0x008D8D, 0x000810,
-	0x08043A, 0x288A06, 0x000007, 0x000815,
-	0x08001A, 0x010984, 0x095186, 0x00137D,
-	0x200500, 0x280F20, 0x338F60, 0x3B8F60,
-	0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-	0x038A60, 0x018040, 0x007FBD, 0x383DC4,
-	0x000007, 0x001A7D, 0x001375, 0x018042,
-	0x09004A, 0x10000A, 0x0B8D04, 0x139504,
-	0x000007, 0x000820, 0x019060, 0x001104,
-	0x212086, 0x010040, 0x0017FD, 0x018042,
-	0x08000A, 0x000904, 0x212286, 0x000007,
-	0x00197D, 0x038042, 0x09804A, 0x10000A,
-	0x000924, 0x001664, 0x0011FD, 0x038042,
-	0x2B804A, 0x19804A, 0x00008D, 0x218944,
-	0x000007, 0x002244, 0x0AE186, 0x000007,
-	0x001A64, 0x002A24, 0x00197D, 0x080102,
-	0x100122, 0x000820, 0x039060, 0x018040,
-	0x003DFD, 0x00008D, 0x000820, 0x018040,
-	0x001375, 0x001A7D, 0x010042, 0x09804A,
-	0x10000A, 0x00021D, 0x0189E4, 0x2992E4,
-	0x309144, 0x000007, 0x00060D, 0x000A15,
-	0x000C1D, 0x001025, 0x00A9E4, 0x012BE4,
-	0x000464, 0x01B3E4, 0x0232E4, 0x000464,
-	0x000464, 0x000464, 0x000464, 0x00040D,
-	0x08B1C4, 0x000007, 0x000820, 0x000BF5,
-	0x030040, 0x00197D, 0x038042, 0x09804A,
-	0x000A24, 0x08000A, 0x080E64, 0x000007,
-	0x100122, 0x000820, 0x031060, 0x010040,
-	0x0064AC, 0x00027D, 0x000020, 0x018040,
-	0x00107D, 0x018042, 0x0011FD, 0x3B804A,
-	0x09804A, 0x20000A, 0x000095, 0x1A1144,
-	0x00A144, 0x0D2086, 0x00040D, 0x00B984,
-	0x0D2186, 0x0018FD, 0x018042, 0x0010FD,
-	0x09804A, 0x28000A, 0x000095, 0x010924,
-	0x002A64, 0x0D1186, 0x000007, 0x002904,
-	0x0D2286, 0x000007, 0x0D2A06, 0x080002,
-	0x00008D, 0x00387D, 0x000820, 0x018040,
-	0x00127D, 0x018042, 0x10000A, 0x003904,
-	0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984,
-	0x0DA186, 0x000025, 0x0E7A06, 0x00002D,
-	0x000015, 0x00082D, 0x02C78D, 0x000820,
-	0x0EC206, 0x00000D, 0x7F8035, 0x00B984,
-	0x0E7186, 0x400025, 0x00008D, 0x110944,
-	0x000007, 0x00018D, 0x109504, 0x000007,
-	0x009164, 0x000424, 0x000424, 0x000424,
-	0x100102, 0x280002, 0x02C68D, 0x000820,
-	0x0EC206, 0x00018D, 0x00042D, 0x00008D,
-	0x109504, 0x000007, 0x00020D, 0x109184,
-	0x000007, 0x02C70D, 0x000820, 0x00008D,
-	0x0038FD, 0x018040, 0x003BFD, 0x001020,
-	0x03A860, 0x000815, 0x313184, 0x212184,
-	0x000007, 0x03B060, 0x03A060, 0x018040,
-	0x0022FD, 0x000095, 0x010924, 0x000424,
-	0x000424, 0x001264, 0x100102, 0x000820,
-	0x039060, 0x018040, 0x001924, 0x00FB8D,
-	0x00397D, 0x000820, 0x058040, 0x038042,
-	0x09844A, 0x000606, 0x08040A, 0x000424,
-	0x000424, 0x00117D, 0x018042, 0x08000A,
-	0x000A24, 0x280502, 0x280C02, 0x09800D,
-	0x000820, 0x0002FD, 0x018040, 0x200007,
-	0x0022FD, 0x018042, 0x08000A, 0x000095,
-	0x280DC4, 0x011924, 0x00197D, 0x018042,
-	0x0011FD, 0x09804A, 0x10000A, 0x0000B5,
-	0x113144, 0x0A8D04, 0x000007, 0x080A44,
-	0x129504, 0x000007, 0x0023FD, 0x001020,
-	0x038040, 0x101244, 0x000007, 0x000820,
-	0x039060, 0x018040, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x10FA86, 0x000007,
-	0x003BFD, 0x000100, 0x000A10, 0x0B807A,
-	0x13804A, 0x090984, 0x000007, 0x000095,
-	0x013D04, 0x118086, 0x10000A, 0x100002,
-	0x090984, 0x000007, 0x038042, 0x11804A,
-	0x090D04, 0x000007, 0x10000A, 0x090D84,
-	0x000007, 0x00257D, 0x000820, 0x018040,
-	0x00010D, 0x000810, 0x28143A, 0x00127D,
-	0x018042, 0x20000A, 0x00197D, 0x018042,
-	0x00117D, 0x31804A, 0x10000A, 0x003124,
-	0x01280D, 0x00397D, 0x000820, 0x058040,
-	0x038042, 0x09844A, 0x000606, 0x08040A,
-	0x300102, 0x003124, 0x000424, 0x000424,
-	0x001224, 0x280502, 0x001A4C, 0x130186,
-	0x700002, 0x00002D, 0x030000, 0x00387D,
-	0x018042, 0x10000A, 0x132A06, 0x002124,
-	0x0000AD, 0x100002, 0x00010D, 0x000924,
-	0x006B24, 0x01368D, 0x00397D, 0x000820,
-	0x058040, 0x038042, 0x09844A, 0x000606,
-	0x08040A, 0x003264, 0x00008D, 0x000A24,
-	0x001020, 0x00227D, 0x018040, 0x013C0D,
-	0x000810, 0x08043A, 0x29D206, 0x000007,
-	0x002820, 0x00207D, 0x018040, 0x00117D,
-	0x038042, 0x13804A, 0x33800A, 0x00387D,
-	0x018042, 0x08000A, 0x000904, 0x163A86,
-	0x000007, 0x00008D, 0x030964, 0x01478D,
-	0x00397D, 0x000820, 0x058040, 0x038042,
-	0x09844A, 0x000606, 0x08040A, 0x380102,
-	0x000424, 0x000424, 0x001224, 0x0002FD,
-	0x018042, 0x08000A, 0x000904, 0x14A286,
-	0x000007, 0x280502, 0x001A4C, 0x163986,
-	0x000007, 0x032164, 0x00632C, 0x003DFD,
-	0x018042, 0x08000A, 0x000095, 0x090904,
-	0x000007, 0x000820, 0x001A4C, 0x156186,
-	0x018040, 0x030000, 0x157A06, 0x002124,
-	0x00010D, 0x000924, 0x006B24, 0x015B8D,
-	0x00397D, 0x000820, 0x058040, 0x038042,
-	0x09844A, 0x000606, 0x08040A, 0x003A64,
-	0x000095, 0x001224, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x15DA86, 0x000007,
-	0x01628D, 0x000810, 0x08043A, 0x29D206,
-	0x000007, 0x14D206, 0x000007, 0x007020,
-	0x08010A, 0x10012A, 0x0020FD, 0x038860,
-	0x039060, 0x018040, 0x00227D, 0x018042,
-	0x003DFD, 0x08000A, 0x31844A, 0x000904,
-	0x16D886, 0x18008B, 0x00008D, 0x189904,
-	0x00312C, 0x17AA06, 0x000007, 0x00324C,
-	0x173386, 0x000007, 0x001904, 0x173086,
-	0x000007, 0x000095, 0x199144, 0x00222C,
-	0x003124, 0x00636C, 0x000E3D, 0x001375,
-	0x000BFD, 0x010042, 0x09804A, 0x10000A,
-	0x038AEC, 0x0393EC, 0x00224C, 0x17A986,
-	0x000007, 0x00008D, 0x189904, 0x00226C,
-	0x00322C, 0x30050A, 0x301DAB, 0x002083,
-	0x0018FD, 0x018042, 0x08000A, 0x018924,
-	0x300502, 0x001083, 0x001875, 0x010042,
-	0x10000A, 0x00008D, 0x010924, 0x001375,
-	0x330542, 0x330CCB, 0x332CCB, 0x3334CB,
-	0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB,
-	0x305C8B, 0x006083, 0x0002F5, 0x010042,
-	0x08000A, 0x000904, 0x187A86, 0x000007,
-	0x001E2D, 0x0005FD, 0x018042, 0x08000A,
-	0x028924, 0x280502, 0x00060D, 0x000810,
-	0x280C3A, 0x00008D, 0x000810, 0x28143A,
-	0x0A808D, 0x000820, 0x0002F5, 0x010040,
-	0x220007, 0x001275, 0x030042, 0x21004A,
-	0x00008D, 0x1A0944, 0x000007, 0x01980D,
-	0x000810, 0x08043A, 0x2B2206, 0x000007,
-	0x0001F5, 0x030042, 0x0D004A, 0x10000A,
-	0x089144, 0x000007, 0x000820, 0x010040,
-	0x0025F5, 0x0A3144, 0x000007, 0x000820,
-	0x032860, 0x030040, 0x00217D, 0x038042,
-	0x0B804A, 0x10000A, 0x000820, 0x031060,
-	0x030040, 0x00008D, 0x000124, 0x00012C,
-	0x000E64, 0x001A64, 0x00636C, 0x08010A,
-	0x10012A, 0x000820, 0x031060, 0x030040,
-	0x0020FD, 0x018042, 0x08000A, 0x00227D,
-	0x018042, 0x10000A, 0x000820, 0x031060,
-	0x030040, 0x00197D, 0x018042, 0x08000A,
-	0x0022FD, 0x038042, 0x10000A, 0x000820,
-	0x031060, 0x030040, 0x090D04, 0x000007,
-	0x000820, 0x030040, 0x038042, 0x0B804A,
-	0x10000A, 0x000820, 0x031060, 0x030040,
-	0x038042, 0x13804A, 0x19804A, 0x110D04,
-	0x198D04, 0x000007, 0x08000A, 0x001020,
-	0x031860, 0x030860, 0x030040, 0x00008D,
-	0x0B0944, 0x000007, 0x000820, 0x010040,
-	0x0005F5, 0x030042, 0x08000A, 0x000820,
-	0x010040, 0x0000F5, 0x010042, 0x08000A,
-	0x000904, 0x1C6086, 0x001E75, 0x030042,
-	0x01044A, 0x000C0A, 0x1C7206, 0x000007,
-	0x000402, 0x000C02, 0x00177D, 0x001AF5,
-	0x018042, 0x03144A, 0x031C4A, 0x03244A,
-	0x032C4A, 0x03344A, 0x033C4A, 0x03444A,
-	0x004C0A, 0x00043D, 0x0013F5, 0x001AFD,
-	0x030042, 0x0B004A, 0x1B804A, 0x13804A,
-	0x20000A, 0x089144, 0x19A144, 0x0389E4,
-	0x0399EC, 0x005502, 0x005D0A, 0x030042,
-	0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
-	0x089144, 0x19A144, 0x0389E4, 0x0399EC,
-	0x006502, 0x006D0A, 0x030042, 0x0B004A,
-	0x19004A, 0x2B804A, 0x13804A, 0x21804A,
-	0x30000A, 0x089144, 0x19A144, 0x2AB144,
-	0x0389E4, 0x0399EC, 0x007502, 0x007D0A,
-	0x03A9E4, 0x000702, 0x00107D, 0x000415,
-	0x018042, 0x08000A, 0x0109E4, 0x000F02,
-	0x002AF5, 0x0019FD, 0x010042, 0x09804A,
-	0x10000A, 0x000934, 0x001674, 0x0029F5,
-	0x010042, 0x10000A, 0x00917C, 0x002075,
-	0x010042, 0x08000A, 0x000904, 0x1ED286,
-	0x0026F5, 0x0027F5, 0x030042, 0x09004A,
-	0x10000A, 0x000A3C, 0x00167C, 0x001A75,
-	0x000BFD, 0x010042, 0x51804A, 0x48000A,
-	0x160007, 0x001075, 0x010042, 0x282C0A,
-	0x281D12, 0x282512, 0x001F32, 0x1E0007,
-	0x0E0007, 0x001975, 0x010042, 0x002DF5,
-	0x0D004A, 0x10000A, 0x009144, 0x1FB286,
-	0x010042, 0x28340A, 0x000E5D, 0x00008D,
-	0x000375, 0x000820, 0x010040, 0x05D2F4,
-	0x54D104, 0x00735C, 0x205386, 0x000007,
-	0x0C0007, 0x080007, 0x0A0007, 0x02040D,
-	0x000810, 0x08043A, 0x332206, 0x000007,
-	0x205A06, 0x000007, 0x080007, 0x002275,
-	0x010042, 0x20000A, 0x002104, 0x212086,
-	0x001E2D, 0x0002F5, 0x010042, 0x08000A,
-	0x000904, 0x209286, 0x000007, 0x002010,
-	0x30043A, 0x00057D, 0x0180C3, 0x08000A,
-	0x028924, 0x280502, 0x280C02, 0x0A810D,
-	0x000820, 0x0002F5, 0x010040, 0x220007,
-	0x0004FD, 0x018042, 0x70000A, 0x030000,
-	0x007020, 0x06FA06, 0x018040, 0x02180D,
-	0x000810, 0x08043A, 0x2B2206, 0x000007,
-	0x0002FD, 0x018042, 0x08000A, 0x000904,
-	0x218A86, 0x000007, 0x01F206, 0x000007,
-	0x000875, 0x0009FD, 0x00010D, 0x220A06,
-	0x000295, 0x000B75, 0x00097D, 0x00000D,
-	0x000515, 0x010042, 0x18000A, 0x001904,
-	0x287886, 0x0006F5, 0x001020, 0x010040,
-	0x0004F5, 0x000820, 0x010040, 0x000775,
-	0x010042, 0x09804A, 0x10000A, 0x001124,
-	0x000904, 0x22BA86, 0x000815, 0x080102,
-	0x101204, 0x22DA06, 0x000575, 0x081204,
-	0x000007, 0x100102, 0x000575, 0x000425,
-	0x021124, 0x100102, 0x000820, 0x031060,
-	0x010040, 0x001924, 0x287886, 0x00008D,
-	0x000464, 0x009D04, 0x278886, 0x180102,
-	0x000575, 0x010042, 0x28040A, 0x00018D,
-	0x000924, 0x280D02, 0x00000D, 0x000924,
-	0x281502, 0x10000D, 0x000820, 0x0002F5,
-	0x010040, 0x200007, 0x001175, 0x0002FD,
-	0x018042, 0x08000A, 0x000904, 0x23C286,
-	0x000007, 0x000100, 0x080B20, 0x130B60,
-	0x1B0B60, 0x030A60, 0x010040, 0x050042,
-	0x3D004A, 0x35004A, 0x2D004A, 0x20000A,
-	0x0006F5, 0x010042, 0x28140A, 0x0004F5,
-	0x010042, 0x08000A, 0x000315, 0x010D04,
-	0x24CA86, 0x004015, 0x000095, 0x010D04,
-	0x24B886, 0x100022, 0x10002A, 0x24E206,
-	0x000007, 0x333104, 0x2AA904, 0x000007,
-	0x032124, 0x280502, 0x001124, 0x000424,
-	0x000424, 0x003224, 0x00292C, 0x00636C,
-	0x25F386, 0x000007, 0x02B164, 0x000464,
-	0x000464, 0x00008D, 0x000A64, 0x280D02,
-	0x10008D, 0x000820, 0x0002F5, 0x010040,
-	0x220007, 0x00008D, 0x38B904, 0x000007,
-	0x03296C, 0x30010A, 0x0002F5, 0x010042,
-	0x08000A, 0x000904, 0x25BA86, 0x000007,
-	0x02312C, 0x28050A, 0x00008D, 0x01096C,
-	0x280D0A, 0x10010D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x001124, 0x000424,
-	0x000424, 0x003224, 0x300102, 0x032944,
-	0x267A86, 0x000007, 0x300002, 0x0004F5,
-	0x010042, 0x08000A, 0x000315, 0x010D04,
-	0x26C086, 0x003124, 0x000464, 0x300102,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x26CA86, 0x000007, 0x003124, 0x300502,
-	0x003924, 0x300583, 0x000883, 0x0005F5,
-	0x010042, 0x28040A, 0x00008D, 0x008124,
-	0x280D02, 0x00008D, 0x008124, 0x281502,
-	0x10018D, 0x000820, 0x0002F5, 0x010040,
-	0x220007, 0x001025, 0x000575, 0x030042,
-	0x09004A, 0x10000A, 0x0A0904, 0x121104,
-	0x000007, 0x001020, 0x050860, 0x050040,
-	0x0006FD, 0x018042, 0x09004A, 0x10000A,
-	0x0000A5, 0x0A0904, 0x121104, 0x000007,
-	0x000820, 0x019060, 0x010040, 0x0002F5,
-	0x010042, 0x08000A, 0x000904, 0x284286,
-	0x000007, 0x230A06, 0x000007, 0x000606,
-	0x000007, 0x0002F5, 0x010042, 0x08000A,
-	0x000904, 0x289286, 0x000007, 0x000100,
-	0x080B20, 0x138B60, 0x1B8B60, 0x238B60,
-	0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60,
-	0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60,
-	0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60,
-	0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60,
-	0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60,
-	0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60,
-	0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60,
-	0x000606, 0x018040, 0x00008D, 0x000A64,
-	0x280D02, 0x000A24, 0x00027D, 0x018042,
-	0x10000A, 0x001224, 0x0003FD, 0x018042,
-	0x08000A, 0x000904, 0x2A8286, 0x000007,
-	0x00018D, 0x000A24, 0x000464, 0x000464,
-	0x080102, 0x000924, 0x000424, 0x000424,
-	0x100102, 0x02000D, 0x009144, 0x2AD986,
-	0x000007, 0x0001FD, 0x018042, 0x08000A,
-	0x000A44, 0x2ABB86, 0x018042, 0x0A000D,
-	0x000820, 0x0002FD, 0x018040, 0x200007,
-	0x00027D, 0x001020, 0x000606, 0x018040,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x2B2A86, 0x000007, 0x00037D, 0x018042,
-	0x08000A, 0x000904, 0x2B5A86, 0x000007,
-	0x000075, 0x002E7D, 0x010042, 0x0B804A,
-	0x000020, 0x000904, 0x000686, 0x010040,
-	0x31844A, 0x30048B, 0x000883, 0x00008D,
-	0x000810, 0x28143A, 0x00008D, 0x000810,
-	0x280C3A, 0x000675, 0x010042, 0x08000A,
-	0x003815, 0x010924, 0x280502, 0x0B000D,
-	0x000820, 0x0002F5, 0x010040, 0x000606,
-	0x220007, 0x000464, 0x000464, 0x000606,
-	0x000007, 0x000134, 0x007F8D, 0x00093C,
-	0x281D12, 0x282512, 0x001F32, 0x0E0007,
-	0x00010D, 0x00037D, 0x000820, 0x018040,
-	0x05D2F4, 0x000007, 0x080007, 0x00037D,
-	0x018042, 0x08000A, 0x000904, 0x2D0286,
-	0x000007, 0x000606, 0x000007, 0x000007,
-	0x000012, 0x100007, 0x320007, 0x600007,
-	0x100080, 0x48001A, 0x004904, 0x2D6186,
-	0x000007, 0x001210, 0x58003A, 0x000145,
-	0x5C5D04, 0x000007, 0x000080, 0x48001A,
-	0x004904, 0x2DB186, 0x000007, 0x001210,
-	0x50003A, 0x005904, 0x2E0886, 0x000045,
-	0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524,
-	0x004224, 0x500102, 0x200502, 0x000082,
-	0x40001A, 0x004104, 0x2E3986, 0x000007,
-	0x003865, 0x40001A, 0x004020, 0x00104D,
-	0x04C184, 0x301B86, 0x000040, 0x040007,
-	0x000165, 0x000145, 0x004020, 0x000040,
-	0x000765, 0x080080, 0x40001A, 0x004104,
-	0x2EC986, 0x000007, 0x001210, 0x40003A,
-	0x004104, 0x2F2286, 0x00004D, 0x0000CD,
-	0x004810, 0x20043A, 0x000882, 0x40001A,
-	0x004104, 0x2F3186, 0x000007, 0x004820,
-	0x005904, 0x300886, 0x000040, 0x0007E5,
-	0x200480, 0x2816A0, 0x3216E0, 0x3A16E0,
-	0x4216E0, 0x021260, 0x000040, 0x000032,
-	0x400075, 0x00007D, 0x07D574, 0x200512,
-	0x000082, 0x40001A, 0x004104, 0x2FE186,
-	0x000007, 0x037206, 0x640007, 0x060007,
-	0x0000E5, 0x000020, 0x000040, 0x000A65,
-	0x000020, 0x020040, 0x020040, 0x000040,
-	0x000165, 0x000042, 0x70000A, 0x007104,
-	0x30A286, 0x000007, 0x018206, 0x640007,
-	0x050000, 0x007020, 0x000040, 0x037206,
-	0x640007, 0x000007, 0x00306D, 0x028860,
-	0x029060, 0x08000A, 0x028860, 0x008040,
-	0x100012, 0x00100D, 0x009184, 0x314186,
-	0x000E0D, 0x009184, 0x325186, 0x000007,
-	0x300007, 0x001020, 0x003B6D, 0x008040,
-	0x000080, 0x08001A, 0x000904, 0x316186,
-	0x000007, 0x001220, 0x000DED, 0x008040,
-	0x008042, 0x10000A, 0x40000D, 0x109544,
-	0x000007, 0x001020, 0x000DED, 0x008040,
-	0x008042, 0x20040A, 0x000082, 0x08001A,
-	0x000904, 0x31F186, 0x000007, 0x003B6D,
-	0x008042, 0x08000A, 0x000E15, 0x010984,
-	0x329B86, 0x600007, 0x08001A, 0x000C15,
-	0x010984, 0x328386, 0x000020, 0x1A0007,
-	0x0002ED, 0x008040, 0x620007, 0x00306D,
-	0x028042, 0x0A804A, 0x000820, 0x0A804A,
-	0x000606, 0x10804A, 0x000007, 0x282512,
-	0x001F32, 0x05D2F4, 0x54D104, 0x00735C,
-	0x000786, 0x000007, 0x0C0007, 0x0A0007,
-	0x1C0007, 0x003465, 0x020040, 0x004820,
-	0x025060, 0x40000A, 0x024060, 0x000040,
-	0x454944, 0x000007, 0x004020, 0x003AE5,
-	0x000040, 0x0028E5, 0x000042, 0x48000A,
-	0x004904, 0x386886, 0x002C65, 0x000042,
-	0x40000A, 0x0000D5, 0x454104, 0x000007,
-	0x000655, 0x054504, 0x34F286, 0x0001D5,
-	0x054504, 0x34F086, 0x002B65, 0x000042,
-	0x003AE5, 0x50004A, 0x40000A, 0x45C3D4,
-	0x000007, 0x454504, 0x000007, 0x0000CD,
-	0x444944, 0x000007, 0x454504, 0x000007,
-	0x00014D, 0x554944, 0x000007, 0x045144,
-	0x34E986, 0x002C65, 0x000042, 0x48000A,
-	0x4CD104, 0x000007, 0x04C144, 0x34F386,
-	0x000007, 0x160007, 0x002CE5, 0x040042,
-	0x40000A, 0x004020, 0x000040, 0x002965,
-	0x000042, 0x40000A, 0x004104, 0x356086,
-	0x000007, 0x002402, 0x36A206, 0x005C02,
-	0x0025E5, 0x000042, 0x40000A, 0x004274,
-	0x002AE5, 0x000042, 0x40000A, 0x004274,
-	0x500112, 0x0029E5, 0x000042, 0x40000A,
-	0x004234, 0x454104, 0x000007, 0x004020,
-	0x000040, 0x003EE5, 0x000020, 0x000040,
-	0x002DE5, 0x400152, 0x50000A, 0x045144,
-	0x364A86, 0x0000C5, 0x003EE5, 0x004020,
-	0x000040, 0x002BE5, 0x000042, 0x40000A,
-	0x404254, 0x000007, 0x002AE5, 0x004020,
-	0x000040, 0x500132, 0x040134, 0x005674,
-	0x0029E5, 0x020042, 0x42000A, 0x000042,
-	0x50000A, 0x05417C, 0x0028E5, 0x000042,
-	0x48000A, 0x0000C5, 0x4CC144, 0x371086,
-	0x0026E5, 0x0027E5, 0x020042, 0x40004A,
-	0x50000A, 0x00423C, 0x00567C, 0x0028E5,
-	0x004820, 0x000040, 0x281D12, 0x282512,
-	0x001F72, 0x002965, 0x000042, 0x40000A,
-	0x004104, 0x37AA86, 0x0E0007, 0x160007,
-	0x1E0007, 0x003EE5, 0x000042, 0x40000A,
-	0x004104, 0x37E886, 0x002D65, 0x000042,
-	0x28340A, 0x003465, 0x020042, 0x42004A,
-	0x004020, 0x4A004A, 0x50004A, 0x05D2F4,
-	0x54D104, 0x00735C, 0x385186, 0x000007,
-	0x000606, 0x080007, 0x0C0007, 0x080007,
-	0x0A0007, 0x0001E5, 0x020045, 0x004020,
-	0x000060, 0x000365, 0x000040, 0x002E65,
-	0x001A20, 0x0A1A60, 0x000040, 0x003465,
-	0x020042, 0x42004A, 0x004020, 0x4A004A,
-	0x000606, 0x50004A, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000
-};
-
-// --------------------------------------------
-//  DS-1E Controller InstructionRAM Code
-//	1999/06/21
-//	Buf441 slot is Enabled.
-// --------------------------------------------
-// 04/09?@creat
-// 04/12  stop nise fix
-// 06/21?@WorkingOff timming
-static unsigned long int	CntrlInst1E[] __initdata = {
-	0x000007, 0x240007, 0x0C0007, 0x1C0007,
-	0x060007, 0x700002, 0x000020, 0x030040,
-	0x007104, 0x004286, 0x030040, 0x000F0D,
-	0x000810, 0x20043A, 0x000282, 0x00020D,
-	0x000810, 0x20043A, 0x001282, 0x200E82,
-	0x00800D, 0x000810, 0x20043A, 0x001A82,
-	0x03460D, 0x000810, 0x10043A, 0x02EC0D,
-	0x000810, 0x18043A, 0x00010D, 0x020015,
-	0x0000FD, 0x000020, 0x038860, 0x039060,
-	0x038060, 0x038040, 0x038040, 0x038040,
-	0x018040, 0x000A7D, 0x038040, 0x038040,
-	0x018040, 0x200402, 0x000882, 0x08001A,
-	0x000904, 0x017186, 0x000007, 0x260007,
-	0x400007, 0x000007, 0x03258D, 0x000810,
-	0x18043A, 0x260007, 0x284402, 0x00087D,
-	0x018042, 0x00160A, 0x05A206, 0x000007,
-	0x440007, 0x00230D, 0x000810, 0x08043A,
-	0x22FA06, 0x000007, 0x0007FD, 0x018042,
-	0x08000A, 0x000904, 0x02AB86, 0x000195,
-	0x090D04, 0x000007, 0x000820, 0x0000F5,
-	0x000B7D, 0x01F060, 0x0000FD, 0x033A06,
-	0x018040, 0x000A7D, 0x038042, 0x13804A,
-	0x18000A, 0x001820, 0x059060, 0x058860,
-	0x018040, 0x0000FD, 0x018042, 0x70000A,
-	0x000115, 0x071144, 0x033B86, 0x030000,
-	0x007020, 0x036206, 0x018040, 0x00360D,
-	0x000810, 0x08043A, 0x232206, 0x000007,
-	0x02EC0D, 0x000810, 0x18043A, 0x019A06,
-	0x000007, 0x240007, 0x000F8D, 0x000810,
-	0x00163A, 0x002402, 0x005C02, 0x0028FD,
-	0x000020, 0x018040, 0x08000D, 0x000815,
-	0x510984, 0x000007, 0x00004D, 0x000E5D,
-	0x000E02, 0x00430D, 0x000810, 0x08043A,
-	0x2E1206, 0x000007, 0x00008D, 0x000924,
-	0x000F02, 0x00470D, 0x000810, 0x08043A,
-	0x2E1206, 0x000007, 0x480480, 0x001210,
-	0x28043A, 0x00778D, 0x000810, 0x280C3A,
-	0x00068D, 0x000810, 0x28143A, 0x284402,
-	0x03258D, 0x000810, 0x18043A, 0x07FF8D,
-	0x000820, 0x0002FD, 0x018040, 0x260007,
-	0x200007, 0x0002FD, 0x018042, 0x08000A,
-	0x000904, 0x051286, 0x000007, 0x240007,
-	0x02EC0D, 0x000810, 0x18043A, 0x00387D,
-	0x018042, 0x08000A, 0x001015, 0x010984,
-	0x019B86, 0x000007, 0x01B206, 0x000007,
-	0x0008FD, 0x018042, 0x18000A, 0x001904,
-	0x22B886, 0x280007, 0x001810, 0x28043A,
-	0x280C02, 0x00000D, 0x000810, 0x28143A,
-	0x08808D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00020D, 0x189904, 0x000007,
-	0x00402D, 0x0000BD, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x065A86, 0x000007,
-	0x000100, 0x000A20, 0x00047D, 0x018040,
-	0x018042, 0x20000A, 0x003015, 0x012144,
-	0x036186, 0x000007, 0x002104, 0x036186,
-	0x000007, 0x000F8D, 0x000810, 0x280C3A,
-	0x023944, 0x07C986, 0x000007, 0x001810,
-	0x28043A, 0x08810D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x002810, 0x78003A,
-	0x00788D, 0x000810, 0x08043A, 0x2A1206,
-	0x000007, 0x00400D, 0x001015, 0x189904,
-	0x292904, 0x393904, 0x000007, 0x070206,
-	0x000007, 0x0004F5, 0x00007D, 0x000020,
-	0x00008D, 0x010860, 0x018040, 0x00047D,
-	0x038042, 0x21804A, 0x18000A, 0x021944,
-	0x229086, 0x000007, 0x004075, 0x71F104,
-	0x000007, 0x010042, 0x28000A, 0x002904,
-	0x225886, 0x000007, 0x003C0D, 0x30A904,
-	0x000007, 0x00077D, 0x018042, 0x08000A,
-	0x000904, 0x08DA86, 0x00057D, 0x002820,
-	0x03B060, 0x08F206, 0x018040, 0x003020,
-	0x03A860, 0x018040, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x08FA86, 0x000007,
-	0x00057D, 0x018042, 0x28040A, 0x000E8D,
-	0x000810, 0x280C3A, 0x00000D, 0x000810,
-	0x28143A, 0x09000D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x003DFD, 0x000020,
-	0x018040, 0x00107D, 0x009D8D, 0x000810,
-	0x08043A, 0x2A1206, 0x000007, 0x000815,
-	0x08001A, 0x010984, 0x0A5186, 0x00137D,
-	0x200500, 0x280F20, 0x338F60, 0x3B8F60,
-	0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-	0x038A60, 0x018040, 0x00107D, 0x018042,
-	0x08000A, 0x000215, 0x010984, 0x3A8186,
-	0x000007, 0x007FBD, 0x383DC4, 0x000007,
-	0x001A7D, 0x001375, 0x018042, 0x09004A,
-	0x10000A, 0x0B8D04, 0x139504, 0x000007,
-	0x000820, 0x019060, 0x001104, 0x225886,
-	0x010040, 0x0017FD, 0x018042, 0x08000A,
-	0x000904, 0x225A86, 0x000007, 0x00197D,
-	0x038042, 0x09804A, 0x10000A, 0x000924,
-	0x001664, 0x0011FD, 0x038042, 0x2B804A,
-	0x19804A, 0x00008D, 0x218944, 0x000007,
-	0x002244, 0x0C1986, 0x000007, 0x001A64,
-	0x002A24, 0x00197D, 0x080102, 0x100122,
-	0x000820, 0x039060, 0x018040, 0x003DFD,
-	0x00008D, 0x000820, 0x018040, 0x001375,
-	0x001A7D, 0x010042, 0x09804A, 0x10000A,
-	0x00021D, 0x0189E4, 0x2992E4, 0x309144,
-	0x000007, 0x00060D, 0x000A15, 0x000C1D,
-	0x001025, 0x00A9E4, 0x012BE4, 0x000464,
-	0x01B3E4, 0x0232E4, 0x000464, 0x000464,
-	0x000464, 0x000464, 0x00040D, 0x08B1C4,
-	0x000007, 0x000820, 0x000BF5, 0x030040,
-	0x00197D, 0x038042, 0x09804A, 0x000A24,
-	0x08000A, 0x080E64, 0x000007, 0x100122,
-	0x000820, 0x031060, 0x010040, 0x0064AC,
-	0x00027D, 0x000020, 0x018040, 0x00107D,
-	0x018042, 0x0011FD, 0x3B804A, 0x09804A,
-	0x20000A, 0x000095, 0x1A1144, 0x00A144,
-	0x0E5886, 0x00040D, 0x00B984, 0x0E5986,
-	0x0018FD, 0x018042, 0x0010FD, 0x09804A,
-	0x28000A, 0x000095, 0x010924, 0x002A64,
-	0x0E4986, 0x000007, 0x002904, 0x0E5A86,
-	0x000007, 0x0E6206, 0x080002, 0x00008D,
-	0x00387D, 0x000820, 0x018040, 0x00127D,
-	0x018042, 0x10000A, 0x003904, 0x0F0986,
-	0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986,
-	0x000025, 0x0FB206, 0x00002D, 0x000015,
-	0x00082D, 0x02E00D, 0x000820, 0x0FFA06,
-	0x00000D, 0x7F8035, 0x00B984, 0x0FA986,
-	0x400025, 0x00008D, 0x110944, 0x000007,
-	0x00018D, 0x109504, 0x000007, 0x009164,
-	0x000424, 0x000424, 0x000424, 0x100102,
-	0x280002, 0x02DF0D, 0x000820, 0x0FFA06,
-	0x00018D, 0x00042D, 0x00008D, 0x109504,
-	0x000007, 0x00020D, 0x109184, 0x000007,
-	0x02DF8D, 0x000820, 0x00008D, 0x0038FD,
-	0x018040, 0x003BFD, 0x001020, 0x03A860,
-	0x000815, 0x313184, 0x212184, 0x000007,
-	0x03B060, 0x03A060, 0x018040, 0x0022FD,
-	0x000095, 0x010924, 0x000424, 0x000424,
-	0x001264, 0x100102, 0x000820, 0x039060,
-	0x018040, 0x001924, 0x010F0D, 0x00397D,
-	0x000820, 0x058040, 0x038042, 0x09844A,
-	0x000606, 0x08040A, 0x000424, 0x000424,
-	0x00117D, 0x018042, 0x08000A, 0x000A24,
-	0x280502, 0x280C02, 0x09800D, 0x000820,
-	0x0002FD, 0x018040, 0x200007, 0x0022FD,
-	0x018042, 0x08000A, 0x000095, 0x280DC4,
-	0x011924, 0x00197D, 0x018042, 0x0011FD,
-	0x09804A, 0x10000A, 0x0000B5, 0x113144,
-	0x0A8D04, 0x000007, 0x080A44, 0x129504,
-	0x000007, 0x0023FD, 0x001020, 0x038040,
-	0x101244, 0x000007, 0x000820, 0x039060,
-	0x018040, 0x0002FD, 0x018042, 0x08000A,
-	0x000904, 0x123286, 0x000007, 0x003BFD,
-	0x000100, 0x000A10, 0x0B807A, 0x13804A,
-	0x090984, 0x000007, 0x000095, 0x013D04,
-	0x12B886, 0x10000A, 0x100002, 0x090984,
-	0x000007, 0x038042, 0x11804A, 0x090D04,
-	0x000007, 0x10000A, 0x090D84, 0x000007,
-	0x00257D, 0x000820, 0x018040, 0x00010D,
-	0x000810, 0x28143A, 0x00127D, 0x018042,
-	0x20000A, 0x00197D, 0x018042, 0x00117D,
-	0x31804A, 0x10000A, 0x003124, 0x013B8D,
-	0x00397D, 0x000820, 0x058040, 0x038042,
-	0x09844A, 0x000606, 0x08040A, 0x300102,
-	0x003124, 0x000424, 0x000424, 0x001224,
-	0x280502, 0x001A4C, 0x143986, 0x700002,
-	0x00002D, 0x030000, 0x00387D, 0x018042,
-	0x10000A, 0x146206, 0x002124, 0x0000AD,
-	0x100002, 0x00010D, 0x000924, 0x006B24,
-	0x014A0D, 0x00397D, 0x000820, 0x058040,
-	0x038042, 0x09844A, 0x000606, 0x08040A,
-	0x003264, 0x00008D, 0x000A24, 0x001020,
-	0x00227D, 0x018040, 0x014F8D, 0x000810,
-	0x08043A, 0x2B5A06, 0x000007, 0x002820,
-	0x00207D, 0x018040, 0x00117D, 0x038042,
-	0x13804A, 0x33800A, 0x00387D, 0x018042,
-	0x08000A, 0x000904, 0x177286, 0x000007,
-	0x00008D, 0x030964, 0x015B0D, 0x00397D,
-	0x000820, 0x058040, 0x038042, 0x09844A,
-	0x000606, 0x08040A, 0x380102, 0x000424,
-	0x000424, 0x001224, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x15DA86, 0x000007,
-	0x280502, 0x001A4C, 0x177186, 0x000007,
-	0x032164, 0x00632C, 0x003DFD, 0x018042,
-	0x08000A, 0x000095, 0x090904, 0x000007,
-	0x000820, 0x001A4C, 0x169986, 0x018040,
-	0x030000, 0x16B206, 0x002124, 0x00010D,
-	0x000924, 0x006B24, 0x016F0D, 0x00397D,
-	0x000820, 0x058040, 0x038042, 0x09844A,
-	0x000606, 0x08040A, 0x003A64, 0x000095,
-	0x001224, 0x0002FD, 0x018042, 0x08000A,
-	0x000904, 0x171286, 0x000007, 0x01760D,
-	0x000810, 0x08043A, 0x2B5A06, 0x000007,
-	0x160A06, 0x000007, 0x007020, 0x08010A,
-	0x10012A, 0x0020FD, 0x038860, 0x039060,
-	0x018040, 0x00227D, 0x018042, 0x003DFD,
-	0x08000A, 0x31844A, 0x000904, 0x181086,
-	0x18008B, 0x00008D, 0x189904, 0x00312C,
-	0x18E206, 0x000007, 0x00324C, 0x186B86,
-	0x000007, 0x001904, 0x186886, 0x000007,
-	0x000095, 0x199144, 0x00222C, 0x003124,
-	0x00636C, 0x000E3D, 0x001375, 0x000BFD,
-	0x010042, 0x09804A, 0x10000A, 0x038AEC,
-	0x0393EC, 0x00224C, 0x18E186, 0x000007,
-	0x00008D, 0x189904, 0x00226C, 0x00322C,
-	0x30050A, 0x301DAB, 0x002083, 0x0018FD,
-	0x018042, 0x08000A, 0x018924, 0x300502,
-	0x001083, 0x001875, 0x010042, 0x10000A,
-	0x00008D, 0x010924, 0x001375, 0x330542,
-	0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB,
-	0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B,
-	0x006083, 0x0002F5, 0x010042, 0x08000A,
-	0x000904, 0x19B286, 0x000007, 0x001E2D,
-	0x0005FD, 0x018042, 0x08000A, 0x028924,
-	0x280502, 0x00060D, 0x000810, 0x280C3A,
-	0x00008D, 0x000810, 0x28143A, 0x0A808D,
-	0x000820, 0x0002F5, 0x010040, 0x220007,
-	0x001275, 0x030042, 0x21004A, 0x00008D,
-	0x1A0944, 0x000007, 0x01AB8D, 0x000810,
-	0x08043A, 0x2CAA06, 0x000007, 0x0001F5,
-	0x030042, 0x0D004A, 0x10000A, 0x089144,
-	0x000007, 0x000820, 0x010040, 0x0025F5,
-	0x0A3144, 0x000007, 0x000820, 0x032860,
-	0x030040, 0x00217D, 0x038042, 0x0B804A,
-	0x10000A, 0x000820, 0x031060, 0x030040,
-	0x00008D, 0x000124, 0x00012C, 0x000E64,
-	0x001A64, 0x00636C, 0x08010A, 0x10012A,
-	0x000820, 0x031060, 0x030040, 0x0020FD,
-	0x018042, 0x08000A, 0x00227D, 0x018042,
-	0x10000A, 0x000820, 0x031060, 0x030040,
-	0x00197D, 0x018042, 0x08000A, 0x0022FD,
-	0x038042, 0x10000A, 0x000820, 0x031060,
-	0x030040, 0x090D04, 0x000007, 0x000820,
-	0x030040, 0x038042, 0x0B804A, 0x10000A,
-	0x000820, 0x031060, 0x030040, 0x038042,
-	0x13804A, 0x19804A, 0x110D04, 0x198D04,
-	0x000007, 0x08000A, 0x001020, 0x031860,
-	0x030860, 0x030040, 0x00008D, 0x0B0944,
-	0x000007, 0x000820, 0x010040, 0x0005F5,
-	0x030042, 0x08000A, 0x000820, 0x010040,
-	0x0000F5, 0x010042, 0x08000A, 0x000904,
-	0x1D9886, 0x001E75, 0x030042, 0x01044A,
-	0x000C0A, 0x1DAA06, 0x000007, 0x000402,
-	0x000C02, 0x00177D, 0x001AF5, 0x018042,
-	0x03144A, 0x031C4A, 0x03244A, 0x032C4A,
-	0x03344A, 0x033C4A, 0x03444A, 0x004C0A,
-	0x00043D, 0x0013F5, 0x001AFD, 0x030042,
-	0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
-	0x089144, 0x19A144, 0x0389E4, 0x0399EC,
-	0x005502, 0x005D0A, 0x030042, 0x0B004A,
-	0x1B804A, 0x13804A, 0x20000A, 0x089144,
-	0x19A144, 0x0389E4, 0x0399EC, 0x006502,
-	0x006D0A, 0x030042, 0x0B004A, 0x19004A,
-	0x2B804A, 0x13804A, 0x21804A, 0x30000A,
-	0x089144, 0x19A144, 0x2AB144, 0x0389E4,
-	0x0399EC, 0x007502, 0x007D0A, 0x03A9E4,
-	0x000702, 0x00107D, 0x000415, 0x018042,
-	0x08000A, 0x0109E4, 0x000F02, 0x002AF5,
-	0x0019FD, 0x010042, 0x09804A, 0x10000A,
-	0x000934, 0x001674, 0x0029F5, 0x010042,
-	0x10000A, 0x00917C, 0x002075, 0x010042,
-	0x08000A, 0x000904, 0x200A86, 0x0026F5,
-	0x0027F5, 0x030042, 0x09004A, 0x10000A,
-	0x000A3C, 0x00167C, 0x001A75, 0x000BFD,
-	0x010042, 0x51804A, 0x48000A, 0x160007,
-	0x001075, 0x010042, 0x282C0A, 0x281D12,
-	0x282512, 0x001F32, 0x1E0007, 0x0E0007,
-	0x001975, 0x010042, 0x002DF5, 0x0D004A,
-	0x10000A, 0x009144, 0x20EA86, 0x010042,
-	0x28340A, 0x000E5D, 0x00008D, 0x000375,
-	0x000820, 0x010040, 0x05D2F4, 0x54D104,
-	0x00735C, 0x218B86, 0x000007, 0x0C0007,
-	0x080007, 0x0A0007, 0x02178D, 0x000810,
-	0x08043A, 0x34B206, 0x000007, 0x219206,
-	0x000007, 0x080007, 0x002275, 0x010042,
-	0x20000A, 0x002104, 0x225886, 0x001E2D,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x21CA86, 0x000007, 0x002010, 0x30043A,
-	0x00057D, 0x0180C3, 0x08000A, 0x028924,
-	0x280502, 0x280C02, 0x0A810D, 0x000820,
-	0x0002F5, 0x010040, 0x220007, 0x0004FD,
-	0x018042, 0x70000A, 0x030000, 0x007020,
-	0x07FA06, 0x018040, 0x022B8D, 0x000810,
-	0x08043A, 0x2CAA06, 0x000007, 0x0002FD,
-	0x018042, 0x08000A, 0x000904, 0x22C286,
-	0x000007, 0x020206, 0x000007, 0x000875,
-	0x0009FD, 0x00010D, 0x234206, 0x000295,
-	0x000B75, 0x00097D, 0x00000D, 0x000515,
-	0x010042, 0x18000A, 0x001904, 0x2A0086,
-	0x0006F5, 0x001020, 0x010040, 0x0004F5,
-	0x000820, 0x010040, 0x000775, 0x010042,
-	0x09804A, 0x10000A, 0x001124, 0x000904,
-	0x23F286, 0x000815, 0x080102, 0x101204,
-	0x241206, 0x000575, 0x081204, 0x000007,
-	0x100102, 0x000575, 0x000425, 0x021124,
-	0x100102, 0x000820, 0x031060, 0x010040,
-	0x001924, 0x2A0086, 0x00008D, 0x000464,
-	0x009D04, 0x291086, 0x180102, 0x000575,
-	0x010042, 0x28040A, 0x00018D, 0x000924,
-	0x280D02, 0x00000D, 0x000924, 0x281502,
-	0x10000D, 0x000820, 0x0002F5, 0x010040,
-	0x200007, 0x001175, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x24FA86, 0x000007,
-	0x000100, 0x080B20, 0x130B60, 0x1B0B60,
-	0x030A60, 0x010040, 0x050042, 0x3D004A,
-	0x35004A, 0x2D004A, 0x20000A, 0x0006F5,
-	0x010042, 0x28140A, 0x0004F5, 0x010042,
-	0x08000A, 0x000315, 0x010D04, 0x260286,
-	0x004015, 0x000095, 0x010D04, 0x25F086,
-	0x100022, 0x10002A, 0x261A06, 0x000007,
-	0x333104, 0x2AA904, 0x000007, 0x032124,
-	0x280502, 0x284402, 0x001124, 0x400102,
-	0x000424, 0x000424, 0x003224, 0x00292C,
-	0x00636C, 0x277386, 0x000007, 0x02B164,
-	0x000464, 0x000464, 0x00008D, 0x000A64,
-	0x280D02, 0x10008D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x00008D, 0x38B904,
-	0x000007, 0x03296C, 0x30010A, 0x0002F5,
-	0x010042, 0x08000A, 0x000904, 0x270286,
-	0x000007, 0x00212C, 0x28050A, 0x00316C,
-	0x00046C, 0x00046C, 0x28450A, 0x001124,
-	0x006B64, 0x100102, 0x00008D, 0x01096C,
-	0x280D0A, 0x10010D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x004124, 0x000424,
-	0x000424, 0x003224, 0x300102, 0x032944,
-	0x27FA86, 0x000007, 0x300002, 0x0004F5,
-	0x010042, 0x08000A, 0x000315, 0x010D04,
-	0x284086, 0x003124, 0x000464, 0x300102,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x284A86, 0x000007, 0x284402, 0x003124,
-	0x300502, 0x003924, 0x300583, 0x000883,
-	0x0005F5, 0x010042, 0x28040A, 0x00008D,
-	0x008124, 0x280D02, 0x00008D, 0x008124,
-	0x281502, 0x10018D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x001025, 0x000575,
-	0x030042, 0x09004A, 0x10000A, 0x0A0904,
-	0x121104, 0x000007, 0x001020, 0x050860,
-	0x050040, 0x0006FD, 0x018042, 0x09004A,
-	0x10000A, 0x0000A5, 0x0A0904, 0x121104,
-	0x000007, 0x000820, 0x019060, 0x010040,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x29CA86, 0x000007, 0x244206, 0x000007,
-	0x000606, 0x000007, 0x0002F5, 0x010042,
-	0x08000A, 0x000904, 0x2A1A86, 0x000007,
-	0x000100, 0x080B20, 0x138B60, 0x1B8B60,
-	0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60,
-	0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60,
-	0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60,
-	0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60,
-	0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60,
-	0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-	0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60,
-	0x038A60, 0x000606, 0x018040, 0x00008D,
-	0x000A64, 0x280D02, 0x000A24, 0x00027D,
-	0x018042, 0x10000A, 0x001224, 0x0003FD,
-	0x018042, 0x08000A, 0x000904, 0x2C0A86,
-	0x000007, 0x00018D, 0x000A24, 0x000464,
-	0x000464, 0x080102, 0x000924, 0x000424,
-	0x000424, 0x100102, 0x02000D, 0x009144,
-	0x2C6186, 0x000007, 0x0001FD, 0x018042,
-	0x08000A, 0x000A44, 0x2C4386, 0x018042,
-	0x0A000D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00027D, 0x001020, 0x000606,
-	0x018040, 0x0002F5, 0x010042, 0x08000A,
-	0x000904, 0x2CB286, 0x000007, 0x00037D,
-	0x018042, 0x08000A, 0x000904, 0x2CE286,
-	0x000007, 0x000075, 0x002E7D, 0x010042,
-	0x0B804A, 0x000020, 0x000904, 0x000686,
-	0x010040, 0x31844A, 0x30048B, 0x000883,
-	0x00008D, 0x000810, 0x28143A, 0x00008D,
-	0x000810, 0x280C3A, 0x000675, 0x010042,
-	0x08000A, 0x003815, 0x010924, 0x280502,
-	0x0B000D, 0x000820, 0x0002F5, 0x010040,
-	0x000606, 0x220007, 0x000464, 0x000464,
-	0x000606, 0x000007, 0x000134, 0x007F8D,
-	0x00093C, 0x281D12, 0x282512, 0x001F32,
-	0x0E0007, 0x00010D, 0x00037D, 0x000820,
-	0x018040, 0x05D2F4, 0x000007, 0x080007,
-	0x00037D, 0x018042, 0x08000A, 0x000904,
-	0x2E8A86, 0x000007, 0x000606, 0x000007,
-	0x000007, 0x000012, 0x100007, 0x320007,
-	0x600007, 0x460007, 0x100080, 0x48001A,
-	0x004904, 0x2EF186, 0x000007, 0x001210,
-	0x58003A, 0x000145, 0x5C5D04, 0x000007,
-	0x000080, 0x48001A, 0x004904, 0x2F4186,
-	0x000007, 0x001210, 0x50003A, 0x005904,
-	0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5,
-	0x7FFF7D, 0x07D524, 0x004224, 0x500102,
-	0x200502, 0x000082, 0x40001A, 0x004104,
-	0x2FC986, 0x000007, 0x003865, 0x40001A,
-	0x004020, 0x00104D, 0x04C184, 0x31AB86,
-	0x000040, 0x040007, 0x000165, 0x000145,
-	0x004020, 0x000040, 0x000765, 0x080080,
-	0x40001A, 0x004104, 0x305986, 0x000007,
-	0x001210, 0x40003A, 0x004104, 0x30B286,
-	0x00004D, 0x0000CD, 0x004810, 0x20043A,
-	0x000882, 0x40001A, 0x004104, 0x30C186,
-	0x000007, 0x004820, 0x005904, 0x319886,
-	0x000040, 0x0007E5, 0x200480, 0x2816A0,
-	0x3216E0, 0x3A16E0, 0x4216E0, 0x021260,
-	0x000040, 0x000032, 0x400075, 0x00007D,
-	0x07D574, 0x200512, 0x000082, 0x40001A,
-	0x004104, 0x317186, 0x000007, 0x038A06,
-	0x640007, 0x0000E5, 0x000020, 0x000040,
-	0x000A65, 0x000020, 0x020040, 0x020040,
-	0x000040, 0x000165, 0x000042, 0x70000A,
-	0x007104, 0x323286, 0x000007, 0x060007,
-	0x019A06, 0x640007, 0x050000, 0x007020,
-	0x000040, 0x038A06, 0x640007, 0x000007,
-	0x00306D, 0x028860, 0x029060, 0x08000A,
-	0x028860, 0x008040, 0x100012, 0x00100D,
-	0x009184, 0x32D186, 0x000E0D, 0x009184,
-	0x33E186, 0x000007, 0x300007, 0x001020,
-	0x003B6D, 0x008040, 0x000080, 0x08001A,
-	0x000904, 0x32F186, 0x000007, 0x001220,
-	0x000DED, 0x008040, 0x008042, 0x10000A,
-	0x40000D, 0x109544, 0x000007, 0x001020,
-	0x000DED, 0x008040, 0x008042, 0x20040A,
-	0x000082, 0x08001A, 0x000904, 0x338186,
-	0x000007, 0x003B6D, 0x008042, 0x08000A,
-	0x000E15, 0x010984, 0x342B86, 0x600007,
-	0x08001A, 0x000C15, 0x010984, 0x341386,
-	0x000020, 0x1A0007, 0x0002ED, 0x008040,
-	0x620007, 0x00306D, 0x028042, 0x0A804A,
-	0x000820, 0x0A804A, 0x000606, 0x10804A,
-	0x000007, 0x282512, 0x001F32, 0x05D2F4,
-	0x54D104, 0x00735C, 0x000786, 0x000007,
-	0x0C0007, 0x0A0007, 0x1C0007, 0x003465,
-	0x020040, 0x004820, 0x025060, 0x40000A,
-	0x024060, 0x000040, 0x454944, 0x000007,
-	0x004020, 0x003AE5, 0x000040, 0x0028E5,
-	0x000042, 0x48000A, 0x004904, 0x39F886,
-	0x002C65, 0x000042, 0x40000A, 0x0000D5,
-	0x454104, 0x000007, 0x000655, 0x054504,
-	0x368286, 0x0001D5, 0x054504, 0x368086,
-	0x002B65, 0x000042, 0x003AE5, 0x50004A,
-	0x40000A, 0x45C3D4, 0x000007, 0x454504,
-	0x000007, 0x0000CD, 0x444944, 0x000007,
-	0x454504, 0x000007, 0x00014D, 0x554944,
-	0x000007, 0x045144, 0x367986, 0x002C65,
-	0x000042, 0x48000A, 0x4CD104, 0x000007,
-	0x04C144, 0x368386, 0x000007, 0x160007,
-	0x002CE5, 0x040042, 0x40000A, 0x004020,
-	0x000040, 0x002965, 0x000042, 0x40000A,
-	0x004104, 0x36F086, 0x000007, 0x002402,
-	0x383206, 0x005C02, 0x0025E5, 0x000042,
-	0x40000A, 0x004274, 0x002AE5, 0x000042,
-	0x40000A, 0x004274, 0x500112, 0x0029E5,
-	0x000042, 0x40000A, 0x004234, 0x454104,
-	0x000007, 0x004020, 0x000040, 0x003EE5,
-	0x000020, 0x000040, 0x002DE5, 0x400152,
-	0x50000A, 0x045144, 0x37DA86, 0x0000C5,
-	0x003EE5, 0x004020, 0x000040, 0x002BE5,
-	0x000042, 0x40000A, 0x404254, 0x000007,
-	0x002AE5, 0x004020, 0x000040, 0x500132,
-	0x040134, 0x005674, 0x0029E5, 0x020042,
-	0x42000A, 0x000042, 0x50000A, 0x05417C,
-	0x0028E5, 0x000042, 0x48000A, 0x0000C5,
-	0x4CC144, 0x38A086, 0x0026E5, 0x0027E5,
-	0x020042, 0x40004A, 0x50000A, 0x00423C,
-	0x00567C, 0x0028E5, 0x004820, 0x000040,
-	0x281D12, 0x282512, 0x001F72, 0x002965,
-	0x000042, 0x40000A, 0x004104, 0x393A86,
-	0x0E0007, 0x160007, 0x1E0007, 0x003EE5,
-	0x000042, 0x40000A, 0x004104, 0x397886,
-	0x002D65, 0x000042, 0x28340A, 0x003465,
-	0x020042, 0x42004A, 0x004020, 0x4A004A,
-	0x50004A, 0x05D2F4, 0x54D104, 0x00735C,
-	0x39E186, 0x000007, 0x000606, 0x080007,
-	0x0C0007, 0x080007, 0x0A0007, 0x0001E5,
-	0x020045, 0x004020, 0x000060, 0x000365,
-	0x000040, 0x002E65, 0x001A20, 0x0A1A60,
-	0x000040, 0x003465, 0x020042, 0x42004A,
-	0x004020, 0x4A004A, 0x000606, 0x50004A,
-	0x0017FD, 0x018042, 0x08000A, 0x000904,
-	0x225A86, 0x000007, 0x00107D, 0x018042,
-	0x0011FD, 0x33804A, 0x19804A, 0x20000A,
-	0x000095, 0x2A1144, 0x01A144, 0x3B9086,
-	0x00040D, 0x00B184, 0x3B9186, 0x0018FD,
-	0x018042, 0x0010FD, 0x09804A, 0x38000A,
-	0x000095, 0x010924, 0x003A64, 0x3B8186,
-	0x000007, 0x003904, 0x3B9286, 0x000007,
-	0x3B9A06, 0x00000D, 0x00008D, 0x000820,
-	0x00387D, 0x018040, 0x700002, 0x00117D,
-	0x018042, 0x00197D, 0x29804A, 0x30000A,
-	0x380002, 0x003124, 0x000424, 0x000424,
-	0x002A24, 0x280502, 0x00068D, 0x000810,
-	0x28143A, 0x00750D, 0x00B124, 0x002264,
-	0x3D0386, 0x284402, 0x000810, 0x280C3A,
-	0x0B800D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00758D, 0x00B124, 0x100102,
-	0x012144, 0x3E4986, 0x001810, 0x10003A,
-	0x00387D, 0x018042, 0x08000A, 0x000904,
-	0x3E4886, 0x030000, 0x3E4A06, 0x0000BD,
-	0x00008D, 0x023164, 0x000A64, 0x280D02,
-	0x0B808D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00387D, 0x018042, 0x08000A,
-	0x000904, 0x3E3286, 0x030000, 0x0002FD,
-	0x018042, 0x08000A, 0x000904, 0x3D8286,
-	0x000007, 0x002810, 0x28043A, 0x00750D,
-	0x030924, 0x002264, 0x280D02, 0x02316C,
-	0x28450A, 0x0B810D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x00008D, 0x000A24,
-	0x3E4A06, 0x100102, 0x001810, 0x10003A,
-	0x0000BD, 0x003810, 0x30043A, 0x00187D,
-	0x018042, 0x0018FD, 0x09804A, 0x20000A,
-	0x0000AD, 0x028924, 0x07212C, 0x001010,
-	0x300583, 0x300D8B, 0x3014BB, 0x301C83,
-	0x002083, 0x00137D, 0x038042, 0x33844A,
-	0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB,
-	0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083,
-	0x001E0D, 0x0005FD, 0x018042, 0x20000A,
-	0x020924, 0x00068D, 0x00A96C, 0x00009D,
-	0x0002FD, 0x018042, 0x08000A, 0x000904,
-	0x3F6A86, 0x000007, 0x280502, 0x280D0A,
-	0x284402, 0x001810, 0x28143A, 0x0C008D,
-	0x000820, 0x0002FD, 0x018040, 0x220007,
-	0x003904, 0x225886, 0x001E0D, 0x00057D,
-	0x018042, 0x20000A, 0x020924, 0x0000A5,
-	0x0002FD, 0x018042, 0x08000A, 0x000904,
-	0x402A86, 0x000007, 0x280502, 0x280C02,
-	0x002010, 0x28143A, 0x0C010D, 0x000820,
-	0x0002FD, 0x018040, 0x225A06, 0x220007,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000
-};
-
-#endif	//_HWMCODE_
-
-
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/Hwmcode.h linux-2.4.27-rc4/drivers/sound/Hwmcode.h
--- linux-2.4.26/drivers/sound/Hwmcode.h	2000-06-20 14:52:36.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/Hwmcode.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,804 +0,0 @@
-//=============================================================================
-// Copyright (c) 1997	Yamaha Corporation.	All Rights Reserved.
-//
-//	Title:
-//		hwmcode.c
-//	Desc:
-//		micro-code for CTRL & DSP
-//	HISTORY:
-//		April 03, 1997:		1st try by M. Mukojima
-//=============================================================================
-#define	YDSXG_DSPLENGTH				0x0080
-#define	YDSXG_CTRLLENGTH			0x3000
-
-
-static unsigned long int	gdwDSPCode[YDSXG_DSPLENGTH >> 2] = {
-	0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
-	0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
-	0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
-	0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000
-};
-
-
-// --------------------------------------------
-//  DS-1E Controller InstructionRAM Code
-//	1999/06/21
-//	Buf441 slot is Enabled.
-// --------------------------------------------
-// 04/09?@creat
-// 04/12  stop nise fix
-// 06/21?@WorkingOff timming
-static unsigned long	gdwCtrl1eCode[YDSXG_CTRLLENGTH >> 2] = {
-	0x000007, 0x240007, 0x0C0007, 0x1C0007,
-	0x060007, 0x700002, 0x000020, 0x030040,
-	0x007104, 0x004286, 0x030040, 0x000F0D,
-	0x000810, 0x20043A, 0x000282, 0x00020D,
-	0x000810, 0x20043A, 0x001282, 0x200E82,
-	0x00800D, 0x000810, 0x20043A, 0x001A82,
-	0x03460D, 0x000810, 0x10043A, 0x02EC0D,
-	0x000810, 0x18043A, 0x00010D, 0x020015,
-	0x0000FD, 0x000020, 0x038860, 0x039060,
-	0x038060, 0x038040, 0x038040, 0x038040,
-	0x018040, 0x000A7D, 0x038040, 0x038040,
-	0x018040, 0x200402, 0x000882, 0x08001A,
-	0x000904, 0x017186, 0x000007, 0x260007,
-	0x400007, 0x000007, 0x03258D, 0x000810,
-	0x18043A, 0x260007, 0x284402, 0x00087D,
-	0x018042, 0x00160A, 0x05A206, 0x000007,
-	0x440007, 0x00230D, 0x000810, 0x08043A,
-	0x22FA06, 0x000007, 0x0007FD, 0x018042,
-	0x08000A, 0x000904, 0x02AB86, 0x000195,
-	0x090D04, 0x000007, 0x000820, 0x0000F5,
-	0x000B7D, 0x01F060, 0x0000FD, 0x033A06,
-	0x018040, 0x000A7D, 0x038042, 0x13804A,
-	0x18000A, 0x001820, 0x059060, 0x058860,
-	0x018040, 0x0000FD, 0x018042, 0x70000A,
-	0x000115, 0x071144, 0x033B86, 0x030000,
-	0x007020, 0x036206, 0x018040, 0x00360D,
-	0x000810, 0x08043A, 0x232206, 0x000007,
-	0x02EC0D, 0x000810, 0x18043A, 0x019A06,
-	0x000007, 0x240007, 0x000F8D, 0x000810,
-	0x00163A, 0x002402, 0x005C02, 0x0028FD,
-	0x000020, 0x018040, 0x08000D, 0x000815,
-	0x510984, 0x000007, 0x00004D, 0x000E5D,
-	0x000E02, 0x00430D, 0x000810, 0x08043A,
-	0x2E1206, 0x000007, 0x00008D, 0x000924,
-	0x000F02, 0x00470D, 0x000810, 0x08043A,
-	0x2E1206, 0x000007, 0x480480, 0x001210,
-	0x28043A, 0x00778D, 0x000810, 0x280C3A,
-	0x00068D, 0x000810, 0x28143A, 0x284402,
-	0x03258D, 0x000810, 0x18043A, 0x07FF8D,
-	0x000820, 0x0002FD, 0x018040, 0x260007,
-	0x200007, 0x0002FD, 0x018042, 0x08000A,
-	0x000904, 0x051286, 0x000007, 0x240007,
-	0x02EC0D, 0x000810, 0x18043A, 0x00387D,
-	0x018042, 0x08000A, 0x001015, 0x010984,
-	0x019B86, 0x000007, 0x01B206, 0x000007,
-	0x0008FD, 0x018042, 0x18000A, 0x001904,
-	0x22B886, 0x280007, 0x001810, 0x28043A,
-	0x280C02, 0x00000D, 0x000810, 0x28143A,
-	0x08808D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00020D, 0x189904, 0x000007,
-	0x00402D, 0x0000BD, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x065A86, 0x000007,
-	0x000100, 0x000A20, 0x00047D, 0x018040,
-	0x018042, 0x20000A, 0x003015, 0x012144,
-	0x036186, 0x000007, 0x002104, 0x036186,
-	0x000007, 0x000F8D, 0x000810, 0x280C3A,
-	0x023944, 0x07C986, 0x000007, 0x001810,
-	0x28043A, 0x08810D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x002810, 0x78003A,
-	0x00788D, 0x000810, 0x08043A, 0x2A1206,
-	0x000007, 0x00400D, 0x001015, 0x189904,
-	0x292904, 0x393904, 0x000007, 0x070206,
-	0x000007, 0x0004F5, 0x00007D, 0x000020,
-	0x00008D, 0x010860, 0x018040, 0x00047D,
-	0x038042, 0x21804A, 0x18000A, 0x021944,
-	0x229086, 0x000007, 0x004075, 0x71F104,
-	0x000007, 0x010042, 0x28000A, 0x002904,
-	0x225886, 0x000007, 0x003C0D, 0x30A904,
-	0x000007, 0x00077D, 0x018042, 0x08000A,
-	0x000904, 0x08DA86, 0x00057D, 0x002820,
-	0x03B060, 0x08F206, 0x018040, 0x003020,
-	0x03A860, 0x018040, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x08FA86, 0x000007,
-	0x00057D, 0x018042, 0x28040A, 0x000E8D,
-	0x000810, 0x280C3A, 0x00000D, 0x000810,
-	0x28143A, 0x09000D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x003DFD, 0x000020,
-	0x018040, 0x00107D, 0x009D8D, 0x000810,
-	0x08043A, 0x2A1206, 0x000007, 0x000815,
-	0x08001A, 0x010984, 0x0A5186, 0x00137D,
-	0x200500, 0x280F20, 0x338F60, 0x3B8F60,
-	0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-	0x038A60, 0x018040, 0x00107D, 0x018042,
-	0x08000A, 0x000215, 0x010984, 0x3A8186,
-	0x000007, 0x007FBD, 0x383DC4, 0x000007,
-	0x001A7D, 0x001375, 0x018042, 0x09004A,
-	0x10000A, 0x0B8D04, 0x139504, 0x000007,
-	0x000820, 0x019060, 0x001104, 0x225886,
-	0x010040, 0x0017FD, 0x018042, 0x08000A,
-	0x000904, 0x225A86, 0x000007, 0x00197D,
-	0x038042, 0x09804A, 0x10000A, 0x000924,
-	0x001664, 0x0011FD, 0x038042, 0x2B804A,
-	0x19804A, 0x00008D, 0x218944, 0x000007,
-	0x002244, 0x0C1986, 0x000007, 0x001A64,
-	0x002A24, 0x00197D, 0x080102, 0x100122,
-	0x000820, 0x039060, 0x018040, 0x003DFD,
-	0x00008D, 0x000820, 0x018040, 0x001375,
-	0x001A7D, 0x010042, 0x09804A, 0x10000A,
-	0x00021D, 0x0189E4, 0x2992E4, 0x309144,
-	0x000007, 0x00060D, 0x000A15, 0x000C1D,
-	0x001025, 0x00A9E4, 0x012BE4, 0x000464,
-	0x01B3E4, 0x0232E4, 0x000464, 0x000464,
-	0x000464, 0x000464, 0x00040D, 0x08B1C4,
-	0x000007, 0x000820, 0x000BF5, 0x030040,
-	0x00197D, 0x038042, 0x09804A, 0x000A24,
-	0x08000A, 0x080E64, 0x000007, 0x100122,
-	0x000820, 0x031060, 0x010040, 0x0064AC,
-	0x00027D, 0x000020, 0x018040, 0x00107D,
-	0x018042, 0x0011FD, 0x3B804A, 0x09804A,
-	0x20000A, 0x000095, 0x1A1144, 0x00A144,
-	0x0E5886, 0x00040D, 0x00B984, 0x0E5986,
-	0x0018FD, 0x018042, 0x0010FD, 0x09804A,
-	0x28000A, 0x000095, 0x010924, 0x002A64,
-	0x0E4986, 0x000007, 0x002904, 0x0E5A86,
-	0x000007, 0x0E6206, 0x080002, 0x00008D,
-	0x00387D, 0x000820, 0x018040, 0x00127D,
-	0x018042, 0x10000A, 0x003904, 0x0F0986,
-	0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986,
-	0x000025, 0x0FB206, 0x00002D, 0x000015,
-	0x00082D, 0x02E00D, 0x000820, 0x0FFA06,
-	0x00000D, 0x7F8035, 0x00B984, 0x0FA986,
-	0x400025, 0x00008D, 0x110944, 0x000007,
-	0x00018D, 0x109504, 0x000007, 0x009164,
-	0x000424, 0x000424, 0x000424, 0x100102,
-	0x280002, 0x02DF0D, 0x000820, 0x0FFA06,
-	0x00018D, 0x00042D, 0x00008D, 0x109504,
-	0x000007, 0x00020D, 0x109184, 0x000007,
-	0x02DF8D, 0x000820, 0x00008D, 0x0038FD,
-	0x018040, 0x003BFD, 0x001020, 0x03A860,
-	0x000815, 0x313184, 0x212184, 0x000007,
-	0x03B060, 0x03A060, 0x018040, 0x0022FD,
-	0x000095, 0x010924, 0x000424, 0x000424,
-	0x001264, 0x100102, 0x000820, 0x039060,
-	0x018040, 0x001924, 0x010F0D, 0x00397D,
-	0x000820, 0x058040, 0x038042, 0x09844A,
-	0x000606, 0x08040A, 0x000424, 0x000424,
-	0x00117D, 0x018042, 0x08000A, 0x000A24,
-	0x280502, 0x280C02, 0x09800D, 0x000820,
-	0x0002FD, 0x018040, 0x200007, 0x0022FD,
-	0x018042, 0x08000A, 0x000095, 0x280DC4,
-	0x011924, 0x00197D, 0x018042, 0x0011FD,
-	0x09804A, 0x10000A, 0x0000B5, 0x113144,
-	0x0A8D04, 0x000007, 0x080A44, 0x129504,
-	0x000007, 0x0023FD, 0x001020, 0x038040,
-	0x101244, 0x000007, 0x000820, 0x039060,
-	0x018040, 0x0002FD, 0x018042, 0x08000A,
-	0x000904, 0x123286, 0x000007, 0x003BFD,
-	0x000100, 0x000A10, 0x0B807A, 0x13804A,
-	0x090984, 0x000007, 0x000095, 0x013D04,
-	0x12B886, 0x10000A, 0x100002, 0x090984,
-	0x000007, 0x038042, 0x11804A, 0x090D04,
-	0x000007, 0x10000A, 0x090D84, 0x000007,
-	0x00257D, 0x000820, 0x018040, 0x00010D,
-	0x000810, 0x28143A, 0x00127D, 0x018042,
-	0x20000A, 0x00197D, 0x018042, 0x00117D,
-	0x31804A, 0x10000A, 0x003124, 0x013B8D,
-	0x00397D, 0x000820, 0x058040, 0x038042,
-	0x09844A, 0x000606, 0x08040A, 0x300102,
-	0x003124, 0x000424, 0x000424, 0x001224,
-	0x280502, 0x001A4C, 0x143986, 0x700002,
-	0x00002D, 0x030000, 0x00387D, 0x018042,
-	0x10000A, 0x146206, 0x002124, 0x0000AD,
-	0x100002, 0x00010D, 0x000924, 0x006B24,
-	0x014A0D, 0x00397D, 0x000820, 0x058040,
-	0x038042, 0x09844A, 0x000606, 0x08040A,
-	0x003264, 0x00008D, 0x000A24, 0x001020,
-	0x00227D, 0x018040, 0x014F8D, 0x000810,
-	0x08043A, 0x2B5A06, 0x000007, 0x002820,
-	0x00207D, 0x018040, 0x00117D, 0x038042,
-	0x13804A, 0x33800A, 0x00387D, 0x018042,
-	0x08000A, 0x000904, 0x177286, 0x000007,
-	0x00008D, 0x030964, 0x015B0D, 0x00397D,
-	0x000820, 0x058040, 0x038042, 0x09844A,
-	0x000606, 0x08040A, 0x380102, 0x000424,
-	0x000424, 0x001224, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x15DA86, 0x000007,
-	0x280502, 0x001A4C, 0x177186, 0x000007,
-	0x032164, 0x00632C, 0x003DFD, 0x018042,
-	0x08000A, 0x000095, 0x090904, 0x000007,
-	0x000820, 0x001A4C, 0x169986, 0x018040,
-	0x030000, 0x16B206, 0x002124, 0x00010D,
-	0x000924, 0x006B24, 0x016F0D, 0x00397D,
-	0x000820, 0x058040, 0x038042, 0x09844A,
-	0x000606, 0x08040A, 0x003A64, 0x000095,
-	0x001224, 0x0002FD, 0x018042, 0x08000A,
-	0x000904, 0x171286, 0x000007, 0x01760D,
-	0x000810, 0x08043A, 0x2B5A06, 0x000007,
-	0x160A06, 0x000007, 0x007020, 0x08010A,
-	0x10012A, 0x0020FD, 0x038860, 0x039060,
-	0x018040, 0x00227D, 0x018042, 0x003DFD,
-	0x08000A, 0x31844A, 0x000904, 0x181086,
-	0x18008B, 0x00008D, 0x189904, 0x00312C,
-	0x18E206, 0x000007, 0x00324C, 0x186B86,
-	0x000007, 0x001904, 0x186886, 0x000007,
-	0x000095, 0x199144, 0x00222C, 0x003124,
-	0x00636C, 0x000E3D, 0x001375, 0x000BFD,
-	0x010042, 0x09804A, 0x10000A, 0x038AEC,
-	0x0393EC, 0x00224C, 0x18E186, 0x000007,
-	0x00008D, 0x189904, 0x00226C, 0x00322C,
-	0x30050A, 0x301DAB, 0x002083, 0x0018FD,
-	0x018042, 0x08000A, 0x018924, 0x300502,
-	0x001083, 0x001875, 0x010042, 0x10000A,
-	0x00008D, 0x010924, 0x001375, 0x330542,
-	0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB,
-	0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B,
-	0x006083, 0x0002F5, 0x010042, 0x08000A,
-	0x000904, 0x19B286, 0x000007, 0x001E2D,
-	0x0005FD, 0x018042, 0x08000A, 0x028924,
-	0x280502, 0x00060D, 0x000810, 0x280C3A,
-	0x00008D, 0x000810, 0x28143A, 0x0A808D,
-	0x000820, 0x0002F5, 0x010040, 0x220007,
-	0x001275, 0x030042, 0x21004A, 0x00008D,
-	0x1A0944, 0x000007, 0x01AB8D, 0x000810,
-	0x08043A, 0x2CAA06, 0x000007, 0x0001F5,
-	0x030042, 0x0D004A, 0x10000A, 0x089144,
-	0x000007, 0x000820, 0x010040, 0x0025F5,
-	0x0A3144, 0x000007, 0x000820, 0x032860,
-	0x030040, 0x00217D, 0x038042, 0x0B804A,
-	0x10000A, 0x000820, 0x031060, 0x030040,
-	0x00008D, 0x000124, 0x00012C, 0x000E64,
-	0x001A64, 0x00636C, 0x08010A, 0x10012A,
-	0x000820, 0x031060, 0x030040, 0x0020FD,
-	0x018042, 0x08000A, 0x00227D, 0x018042,
-	0x10000A, 0x000820, 0x031060, 0x030040,
-	0x00197D, 0x018042, 0x08000A, 0x0022FD,
-	0x038042, 0x10000A, 0x000820, 0x031060,
-	0x030040, 0x090D04, 0x000007, 0x000820,
-	0x030040, 0x038042, 0x0B804A, 0x10000A,
-	0x000820, 0x031060, 0x030040, 0x038042,
-	0x13804A, 0x19804A, 0x110D04, 0x198D04,
-	0x000007, 0x08000A, 0x001020, 0x031860,
-	0x030860, 0x030040, 0x00008D, 0x0B0944,
-	0x000007, 0x000820, 0x010040, 0x0005F5,
-	0x030042, 0x08000A, 0x000820, 0x010040,
-	0x0000F5, 0x010042, 0x08000A, 0x000904,
-	0x1D9886, 0x001E75, 0x030042, 0x01044A,
-	0x000C0A, 0x1DAA06, 0x000007, 0x000402,
-	0x000C02, 0x00177D, 0x001AF5, 0x018042,
-	0x03144A, 0x031C4A, 0x03244A, 0x032C4A,
-	0x03344A, 0x033C4A, 0x03444A, 0x004C0A,
-	0x00043D, 0x0013F5, 0x001AFD, 0x030042,
-	0x0B004A, 0x1B804A, 0x13804A, 0x20000A,
-	0x089144, 0x19A144, 0x0389E4, 0x0399EC,
-	0x005502, 0x005D0A, 0x030042, 0x0B004A,
-	0x1B804A, 0x13804A, 0x20000A, 0x089144,
-	0x19A144, 0x0389E4, 0x0399EC, 0x006502,
-	0x006D0A, 0x030042, 0x0B004A, 0x19004A,
-	0x2B804A, 0x13804A, 0x21804A, 0x30000A,
-	0x089144, 0x19A144, 0x2AB144, 0x0389E4,
-	0x0399EC, 0x007502, 0x007D0A, 0x03A9E4,
-	0x000702, 0x00107D, 0x000415, 0x018042,
-	0x08000A, 0x0109E4, 0x000F02, 0x002AF5,
-	0x0019FD, 0x010042, 0x09804A, 0x10000A,
-	0x000934, 0x001674, 0x0029F5, 0x010042,
-	0x10000A, 0x00917C, 0x002075, 0x010042,
-	0x08000A, 0x000904, 0x200A86, 0x0026F5,
-	0x0027F5, 0x030042, 0x09004A, 0x10000A,
-	0x000A3C, 0x00167C, 0x001A75, 0x000BFD,
-	0x010042, 0x51804A, 0x48000A, 0x160007,
-	0x001075, 0x010042, 0x282C0A, 0x281D12,
-	0x282512, 0x001F32, 0x1E0007, 0x0E0007,
-	0x001975, 0x010042, 0x002DF5, 0x0D004A,
-	0x10000A, 0x009144, 0x20EA86, 0x010042,
-	0x28340A, 0x000E5D, 0x00008D, 0x000375,
-	0x000820, 0x010040, 0x05D2F4, 0x54D104,
-	0x00735C, 0x218B86, 0x000007, 0x0C0007,
-	0x080007, 0x0A0007, 0x02178D, 0x000810,
-	0x08043A, 0x34B206, 0x000007, 0x219206,
-	0x000007, 0x080007, 0x002275, 0x010042,
-	0x20000A, 0x002104, 0x225886, 0x001E2D,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x21CA86, 0x000007, 0x002010, 0x30043A,
-	0x00057D, 0x0180C3, 0x08000A, 0x028924,
-	0x280502, 0x280C02, 0x0A810D, 0x000820,
-	0x0002F5, 0x010040, 0x220007, 0x0004FD,
-	0x018042, 0x70000A, 0x030000, 0x007020,
-	0x07FA06, 0x018040, 0x022B8D, 0x000810,
-	0x08043A, 0x2CAA06, 0x000007, 0x0002FD,
-	0x018042, 0x08000A, 0x000904, 0x22C286,
-	0x000007, 0x020206, 0x000007, 0x000875,
-	0x0009FD, 0x00010D, 0x234206, 0x000295,
-	0x000B75, 0x00097D, 0x00000D, 0x000515,
-	0x010042, 0x18000A, 0x001904, 0x2A0086,
-	0x0006F5, 0x001020, 0x010040, 0x0004F5,
-	0x000820, 0x010040, 0x000775, 0x010042,
-	0x09804A, 0x10000A, 0x001124, 0x000904,
-	0x23F286, 0x000815, 0x080102, 0x101204,
-	0x241206, 0x000575, 0x081204, 0x000007,
-	0x100102, 0x000575, 0x000425, 0x021124,
-	0x100102, 0x000820, 0x031060, 0x010040,
-	0x001924, 0x2A0086, 0x00008D, 0x000464,
-	0x009D04, 0x291086, 0x180102, 0x000575,
-	0x010042, 0x28040A, 0x00018D, 0x000924,
-	0x280D02, 0x00000D, 0x000924, 0x281502,
-	0x10000D, 0x000820, 0x0002F5, 0x010040,
-	0x200007, 0x001175, 0x0002FD, 0x018042,
-	0x08000A, 0x000904, 0x24FA86, 0x000007,
-	0x000100, 0x080B20, 0x130B60, 0x1B0B60,
-	0x030A60, 0x010040, 0x050042, 0x3D004A,
-	0x35004A, 0x2D004A, 0x20000A, 0x0006F5,
-	0x010042, 0x28140A, 0x0004F5, 0x010042,
-	0x08000A, 0x000315, 0x010D04, 0x260286,
-	0x004015, 0x000095, 0x010D04, 0x25F086,
-	0x100022, 0x10002A, 0x261A06, 0x000007,
-	0x333104, 0x2AA904, 0x000007, 0x032124,
-	0x280502, 0x284402, 0x001124, 0x400102,
-	0x000424, 0x000424, 0x003224, 0x00292C,
-	0x00636C, 0x277386, 0x000007, 0x02B164,
-	0x000464, 0x000464, 0x00008D, 0x000A64,
-	0x280D02, 0x10008D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x00008D, 0x38B904,
-	0x000007, 0x03296C, 0x30010A, 0x0002F5,
-	0x010042, 0x08000A, 0x000904, 0x270286,
-	0x000007, 0x00212C, 0x28050A, 0x00316C,
-	0x00046C, 0x00046C, 0x28450A, 0x001124,
-	0x006B64, 0x100102, 0x00008D, 0x01096C,
-	0x280D0A, 0x10010D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x004124, 0x000424,
-	0x000424, 0x003224, 0x300102, 0x032944,
-	0x27FA86, 0x000007, 0x300002, 0x0004F5,
-	0x010042, 0x08000A, 0x000315, 0x010D04,
-	0x284086, 0x003124, 0x000464, 0x300102,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x284A86, 0x000007, 0x284402, 0x003124,
-	0x300502, 0x003924, 0x300583, 0x000883,
-	0x0005F5, 0x010042, 0x28040A, 0x00008D,
-	0x008124, 0x280D02, 0x00008D, 0x008124,
-	0x281502, 0x10018D, 0x000820, 0x0002F5,
-	0x010040, 0x220007, 0x001025, 0x000575,
-	0x030042, 0x09004A, 0x10000A, 0x0A0904,
-	0x121104, 0x000007, 0x001020, 0x050860,
-	0x050040, 0x0006FD, 0x018042, 0x09004A,
-	0x10000A, 0x0000A5, 0x0A0904, 0x121104,
-	0x000007, 0x000820, 0x019060, 0x010040,
-	0x0002F5, 0x010042, 0x08000A, 0x000904,
-	0x29CA86, 0x000007, 0x244206, 0x000007,
-	0x000606, 0x000007, 0x0002F5, 0x010042,
-	0x08000A, 0x000904, 0x2A1A86, 0x000007,
-	0x000100, 0x080B20, 0x138B60, 0x1B8B60,
-	0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60,
-	0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60,
-	0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60,
-	0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60,
-	0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60,
-	0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60,
-	0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60,
-	0x038A60, 0x000606, 0x018040, 0x00008D,
-	0x000A64, 0x280D02, 0x000A24, 0x00027D,
-	0x018042, 0x10000A, 0x001224, 0x0003FD,
-	0x018042, 0x08000A, 0x000904, 0x2C0A86,
-	0x000007, 0x00018D, 0x000A24, 0x000464,
-	0x000464, 0x080102, 0x000924, 0x000424,
-	0x000424, 0x100102, 0x02000D, 0x009144,
-	0x2C6186, 0x000007, 0x0001FD, 0x018042,
-	0x08000A, 0x000A44, 0x2C4386, 0x018042,
-	0x0A000D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00027D, 0x001020, 0x000606,
-	0x018040, 0x0002F5, 0x010042, 0x08000A,
-	0x000904, 0x2CB286, 0x000007, 0x00037D,
-	0x018042, 0x08000A, 0x000904, 0x2CE286,
-	0x000007, 0x000075, 0x002E7D, 0x010042,
-	0x0B804A, 0x000020, 0x000904, 0x000686,
-	0x010040, 0x31844A, 0x30048B, 0x000883,
-	0x00008D, 0x000810, 0x28143A, 0x00008D,
-	0x000810, 0x280C3A, 0x000675, 0x010042,
-	0x08000A, 0x003815, 0x010924, 0x280502,
-	0x0B000D, 0x000820, 0x0002F5, 0x010040,
-	0x000606, 0x220007, 0x000464, 0x000464,
-	0x000606, 0x000007, 0x000134, 0x007F8D,
-	0x00093C, 0x281D12, 0x282512, 0x001F32,
-	0x0E0007, 0x00010D, 0x00037D, 0x000820,
-	0x018040, 0x05D2F4, 0x000007, 0x080007,
-	0x00037D, 0x018042, 0x08000A, 0x000904,
-	0x2E8A86, 0x000007, 0x000606, 0x000007,
-	0x000007, 0x000012, 0x100007, 0x320007,
-	0x600007, 0x460007, 0x100080, 0x48001A,
-	0x004904, 0x2EF186, 0x000007, 0x001210,
-	0x58003A, 0x000145, 0x5C5D04, 0x000007,
-	0x000080, 0x48001A, 0x004904, 0x2F4186,
-	0x000007, 0x001210, 0x50003A, 0x005904,
-	0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5,
-	0x7FFF7D, 0x07D524, 0x004224, 0x500102,
-	0x200502, 0x000082, 0x40001A, 0x004104,
-	0x2FC986, 0x000007, 0x003865, 0x40001A,
-	0x004020, 0x00104D, 0x04C184, 0x31AB86,
-	0x000040, 0x040007, 0x000165, 0x000145,
-	0x004020, 0x000040, 0x000765, 0x080080,
-	0x40001A, 0x004104, 0x305986, 0x000007,
-	0x001210, 0x40003A, 0x004104, 0x30B286,
-	0x00004D, 0x0000CD, 0x004810, 0x20043A,
-	0x000882, 0x40001A, 0x004104, 0x30C186,
-	0x000007, 0x004820, 0x005904, 0x319886,
-	0x000040, 0x0007E5, 0x200480, 0x2816A0,
-	0x3216E0, 0x3A16E0, 0x4216E0, 0x021260,
-	0x000040, 0x000032, 0x400075, 0x00007D,
-	0x07D574, 0x200512, 0x000082, 0x40001A,
-	0x004104, 0x317186, 0x000007, 0x038A06,
-	0x640007, 0x0000E5, 0x000020, 0x000040,
-	0x000A65, 0x000020, 0x020040, 0x020040,
-	0x000040, 0x000165, 0x000042, 0x70000A,
-	0x007104, 0x323286, 0x000007, 0x060007,
-	0x019A06, 0x640007, 0x050000, 0x007020,
-	0x000040, 0x038A06, 0x640007, 0x000007,
-	0x00306D, 0x028860, 0x029060, 0x08000A,
-	0x028860, 0x008040, 0x100012, 0x00100D,
-	0x009184, 0x32D186, 0x000E0D, 0x009184,
-	0x33E186, 0x000007, 0x300007, 0x001020,
-	0x003B6D, 0x008040, 0x000080, 0x08001A,
-	0x000904, 0x32F186, 0x000007, 0x001220,
-	0x000DED, 0x008040, 0x008042, 0x10000A,
-	0x40000D, 0x109544, 0x000007, 0x001020,
-	0x000DED, 0x008040, 0x008042, 0x20040A,
-	0x000082, 0x08001A, 0x000904, 0x338186,
-	0x000007, 0x003B6D, 0x008042, 0x08000A,
-	0x000E15, 0x010984, 0x342B86, 0x600007,
-	0x08001A, 0x000C15, 0x010984, 0x341386,
-	0x000020, 0x1A0007, 0x0002ED, 0x008040,
-	0x620007, 0x00306D, 0x028042, 0x0A804A,
-	0x000820, 0x0A804A, 0x000606, 0x10804A,
-	0x000007, 0x282512, 0x001F32, 0x05D2F4,
-	0x54D104, 0x00735C, 0x000786, 0x000007,
-	0x0C0007, 0x0A0007, 0x1C0007, 0x003465,
-	0x020040, 0x004820, 0x025060, 0x40000A,
-	0x024060, 0x000040, 0x454944, 0x000007,
-	0x004020, 0x003AE5, 0x000040, 0x0028E5,
-	0x000042, 0x48000A, 0x004904, 0x39F886,
-	0x002C65, 0x000042, 0x40000A, 0x0000D5,
-	0x454104, 0x000007, 0x000655, 0x054504,
-	0x368286, 0x0001D5, 0x054504, 0x368086,
-	0x002B65, 0x000042, 0x003AE5, 0x50004A,
-	0x40000A, 0x45C3D4, 0x000007, 0x454504,
-	0x000007, 0x0000CD, 0x444944, 0x000007,
-	0x454504, 0x000007, 0x00014D, 0x554944,
-	0x000007, 0x045144, 0x367986, 0x002C65,
-	0x000042, 0x48000A, 0x4CD104, 0x000007,
-	0x04C144, 0x368386, 0x000007, 0x160007,
-	0x002CE5, 0x040042, 0x40000A, 0x004020,
-	0x000040, 0x002965, 0x000042, 0x40000A,
-	0x004104, 0x36F086, 0x000007, 0x002402,
-	0x383206, 0x005C02, 0x0025E5, 0x000042,
-	0x40000A, 0x004274, 0x002AE5, 0x000042,
-	0x40000A, 0x004274, 0x500112, 0x0029E5,
-	0x000042, 0x40000A, 0x004234, 0x454104,
-	0x000007, 0x004020, 0x000040, 0x003EE5,
-	0x000020, 0x000040, 0x002DE5, 0x400152,
-	0x50000A, 0x045144, 0x37DA86, 0x0000C5,
-	0x003EE5, 0x004020, 0x000040, 0x002BE5,
-	0x000042, 0x40000A, 0x404254, 0x000007,
-	0x002AE5, 0x004020, 0x000040, 0x500132,
-	0x040134, 0x005674, 0x0029E5, 0x020042,
-	0x42000A, 0x000042, 0x50000A, 0x05417C,
-	0x0028E5, 0x000042, 0x48000A, 0x0000C5,
-	0x4CC144, 0x38A086, 0x0026E5, 0x0027E5,
-	0x020042, 0x40004A, 0x50000A, 0x00423C,
-	0x00567C, 0x0028E5, 0x004820, 0x000040,
-	0x281D12, 0x282512, 0x001F72, 0x002965,
-	0x000042, 0x40000A, 0x004104, 0x393A86,
-	0x0E0007, 0x160007, 0x1E0007, 0x003EE5,
-	0x000042, 0x40000A, 0x004104, 0x397886,
-	0x002D65, 0x000042, 0x28340A, 0x003465,
-	0x020042, 0x42004A, 0x004020, 0x4A004A,
-	0x50004A, 0x05D2F4, 0x54D104, 0x00735C,
-	0x39E186, 0x000007, 0x000606, 0x080007,
-	0x0C0007, 0x080007, 0x0A0007, 0x0001E5,
-	0x020045, 0x004020, 0x000060, 0x000365,
-	0x000040, 0x002E65, 0x001A20, 0x0A1A60,
-	0x000040, 0x003465, 0x020042, 0x42004A,
-	0x004020, 0x4A004A, 0x000606, 0x50004A,
-	0x0017FD, 0x018042, 0x08000A, 0x000904,
-	0x225A86, 0x000007, 0x00107D, 0x018042,
-	0x0011FD, 0x33804A, 0x19804A, 0x20000A,
-	0x000095, 0x2A1144, 0x01A144, 0x3B9086,
-	0x00040D, 0x00B184, 0x3B9186, 0x0018FD,
-	0x018042, 0x0010FD, 0x09804A, 0x38000A,
-	0x000095, 0x010924, 0x003A64, 0x3B8186,
-	0x000007, 0x003904, 0x3B9286, 0x000007,
-	0x3B9A06, 0x00000D, 0x00008D, 0x000820,
-	0x00387D, 0x018040, 0x700002, 0x00117D,
-	0x018042, 0x00197D, 0x29804A, 0x30000A,
-	0x380002, 0x003124, 0x000424, 0x000424,
-	0x002A24, 0x280502, 0x00068D, 0x000810,
-	0x28143A, 0x00750D, 0x00B124, 0x002264,
-	0x3D0386, 0x284402, 0x000810, 0x280C3A,
-	0x0B800D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00758D, 0x00B124, 0x100102,
-	0x012144, 0x3E4986, 0x001810, 0x10003A,
-	0x00387D, 0x018042, 0x08000A, 0x000904,
-	0x3E4886, 0x030000, 0x3E4A06, 0x0000BD,
-	0x00008D, 0x023164, 0x000A64, 0x280D02,
-	0x0B808D, 0x000820, 0x0002FD, 0x018040,
-	0x200007, 0x00387D, 0x018042, 0x08000A,
-	0x000904, 0x3E3286, 0x030000, 0x0002FD,
-	0x018042, 0x08000A, 0x000904, 0x3D8286,
-	0x000007, 0x002810, 0x28043A, 0x00750D,
-	0x030924, 0x002264, 0x280D02, 0x02316C,
-	0x28450A, 0x0B810D, 0x000820, 0x0002FD,
-	0x018040, 0x200007, 0x00008D, 0x000A24,
-	0x3E4A06, 0x100102, 0x001810, 0x10003A,
-	0x0000BD, 0x003810, 0x30043A, 0x00187D,
-	0x018042, 0x0018FD, 0x09804A, 0x20000A,
-	0x0000AD, 0x028924, 0x07212C, 0x001010,
-	0x300583, 0x300D8B, 0x3014BB, 0x301C83,
-	0x002083, 0x00137D, 0x038042, 0x33844A,
-	0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB,
-	0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083,
-	0x001E0D, 0x0005FD, 0x018042, 0x20000A,
-	0x020924, 0x00068D, 0x00A96C, 0x00009D,
-	0x0002FD, 0x018042, 0x08000A, 0x000904,
-	0x3F6A86, 0x000007, 0x280502, 0x280D0A,
-	0x284402, 0x001810, 0x28143A, 0x0C008D,
-	0x000820, 0x0002FD, 0x018040, 0x220007,
-	0x003904, 0x225886, 0x001E0D, 0x00057D,
-	0x018042, 0x20000A, 0x020924, 0x0000A5,
-	0x0002FD, 0x018042, 0x08000A, 0x000904,
-	0x402A86, 0x000007, 0x280502, 0x280C02,
-	0x002010, 0x28143A, 0x0C010D, 0x000820,
-	0x0002FD, 0x018040, 0x225A06, 0x220007,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000,
-	0x000000, 0x000000, 0x000000, 0x000000
-};
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/ad1848.c linux-2.4.27-rc4/drivers/sound/ad1848.c
--- linux-2.4.26/drivers/sound/ad1848.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/ad1848.c	2004-07-30 16:29:25.000000000 +0000
@@ -636,6 +636,7 @@ static void ad1848_mixer_reset(ad1848_in
 			devc->supported_devices = MODE3_MIXER_DEVICES;
 			break;
 		case MD_4232:
+		case MD_4235:
 		case MD_4236:
 			devc->supported_devices = MODE3_MIXER_DEVICES;
 			break;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/cmpci.c linux-2.4.27-rc4/drivers/sound/cmpci.c
--- linux-2.4.26/drivers/sound/cmpci.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/cmpci.c	2004-07-30 16:24:25.000000000 +0000
@@ -3595,7 +3595,7 @@ MODULE_AUTHOR("ChenLi Tien, cltien@cmedi
 MODULE_DESCRIPTION("CM8x38 Audio Driver");
 MODULE_LICENSE("GPL");
 
-static void __devinit cm_remove(struct pci_dev *dev)
+static void __devexit cm_remove(struct pci_dev *dev)
 {
 	struct cm_state *s = pci_get_drvdata(dev);
 
@@ -3643,10 +3643,10 @@ static struct pci_device_id id_table[] _
 MODULE_DEVICE_TABLE(pci, id_table);
 
 static struct pci_driver cm_driver = {
-       name: "cmpci",
-       id_table: id_table,
-       probe: cm_probe,
-       remove: cm_remove
+	.name		= "cmpci",
+	.id_table	= id_table,
+	.probe		= cm_probe,
+	.remove		= __devexit_p(cm_remove)
 };
  
 static int __init init_cmpci(void)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/i810_audio.c linux-2.4.27-rc4/drivers/sound/i810_audio.c
--- linux-2.4.26/drivers/sound/i810_audio.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/i810_audio.c	2004-07-30 16:30:12.000000000 +0000
@@ -99,54 +99,14 @@
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
+#include <linux/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 
-#ifndef PCI_DEVICE_ID_INTEL_82801
-#define PCI_DEVICE_ID_INTEL_82801	0x2415
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901
-#define PCI_DEVICE_ID_INTEL_82901	0x2425
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH2
-#define PCI_DEVICE_ID_INTEL_ICH2	0x2445
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3
-#define PCI_DEVICE_ID_INTEL_ICH3	0x2485
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4
-#define PCI_DEVICE_ID_INTEL_ICH4	0x24c5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5
-#define PCI_DEVICE_ID_INTEL_ICH5	0x24d5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_3
-#define PCI_DEVICE_ID_INTEL_ICH6_3	0x266e
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX
-#define PCI_DEVICE_ID_INTEL_440MX	0x7195
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB_5
-#define PCI_DEVICE_ID_INTEL_ESB_5	0x25a6
-#endif
-#ifndef PCI_DEVICE_ID_SI_7012
-#define PCI_DEVICE_ID_SI_7012		0x7012
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO	0x01b1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO	0x006a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO	0x00da
-#endif
-#ifndef PCI_DEVICE_ID_AMD_768_AUDIO
-#define PCI_DEVICE_ID_AMD_768_AUDIO	0x7445
-#endif
-#ifndef PCI_DEVICE_ID_AMD_8111_AC97
-#define PCI_DEVICE_ID_AMD_8111_AC97	0x746d
-#endif
+#define DRIVER_VERSION "1.01"
+
+#define MODULOP2(a, b) ((a) & ((b) - 1))
+#define MASKP2(a, b) ((a) & ~((b) - 1))
 
 static int ftsodell;
 static int strict_clocking;
@@ -209,6 +169,7 @@ struct i810_channel 
 
 #define ENUM_ENGINE(PRE,DIG) 									\
 enum {												\
+	PRE##_BASE =	0x##DIG##0,		/* Base Address */				\
 	PRE##_BDBAR =	0x##DIG##0,		/* Buffer Descriptor list Base Address */	\
 	PRE##_CIV =	0x##DIG##4,		/* Current Index Value */			\
 	PRE##_LVI =	0x##DIG##5,		/* Last Valid Index */				\
@@ -256,8 +217,6 @@ enum {
 #define INT_GPI		(1<<0)
 #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
 
-#define DRIVER_VERSION "0.24"
-
 /* magic numbers to protect our data structures */
 #define I810_CARD_MAGIC		0x5072696E /* "Prin" */
 #define I810_STATE_MAGIC	0x63657373 /* "cess" */
@@ -323,19 +282,19 @@ static struct {
 };
 
 static struct pci_device_id i810_pci_tbl [] = {
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82901,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH2,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH3,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH4,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH5,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5},
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
@@ -345,13 +304,13 @@ static struct pci_device_id i810_pci_tbl
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
 	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768_AUDIO,
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
-	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AC97,
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
 	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_3,
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
 
 	{0,}
@@ -491,8 +450,12 @@ struct i810_card {
 /* extract register offset from codec struct */
 #define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
 
+#define GET_CIV(port) MODULOP2(inb((port) + OFF_CIV), SG_LEN)
+#define GET_LVI(port) MODULOP2(inb((port) + OFF_LVI), SG_LEN)
+
 /* set LVI from CIV */
-#define CIV_TO_LVI(port, off) outb((inb(port+OFF_CIV)+off) & 31, port+OFF_LVI)
+#define CIV_TO_LVI(port, off) \
+	outb(MODULOP2(GET_CIV((port)) + (off), SG_LEN), (port) + OFF_LVI)
 
 static struct i810_card *devs = NULL;
 
@@ -762,7 +725,7 @@ static inline unsigned i810_get_dma_addr
 		port_picb = port + OFF_PICB;
 
 	do {
-		civ = inb(port+OFF_CIV) & 31;
+		civ = GET_CIV(port);
 		offset = inw(port_picb);
 		/* Must have a delay here! */ 
 		if(offset == 0)
@@ -782,7 +745,7 @@ static inline unsigned i810_get_dma_addr
 		 * that we won't have to worry about the chip still being
 		 * out of sync with reality ;-)
 		 */
-	} while (civ != (inb(port+OFF_CIV) & 31) || offset != inw(port_picb));
+	} while (civ != GET_CIV(port) || offset != inw(port_picb));
 		 
 	return (((civ + 1) * dmabuf->fragsize - (bytes * offset))
 		% dmabuf->dmasize);
@@ -992,6 +955,7 @@ static int prog_dmabuf(struct i810_state
 	dmabuf->numfrag = SG_LEN;
 	dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag;
 	dmabuf->fragsamples = dmabuf->fragsize >> 1;
+	dmabuf->fragshift = ffs(dmabuf->fragsize) - 1;
 	dmabuf->userfragsize = dmabuf->ossfragsize;
 	dmabuf->userfrags = dmabuf->dmasize/dmabuf->ossfragsize;
 
@@ -999,16 +963,12 @@ static int prog_dmabuf(struct i810_state
 
 	if(dmabuf->ossmaxfrags == 4) {
 		fragint = 8;
-		dmabuf->fragshift = 2;
 	} else if (dmabuf->ossmaxfrags == 8) {
 		fragint = 4;
-		dmabuf->fragshift = 3;
 	} else if (dmabuf->ossmaxfrags == 16) {
 		fragint = 2;
-		dmabuf->fragshift = 4;
 	} else {
 		fragint = 1;
-		dmabuf->fragshift = 5;
 	}
 	/*
 	 *	Now set up the ring 
@@ -1072,41 +1032,41 @@ static void __i810_update_lvi(struct i81
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
 	int x, port;
-	
+	int trigger;
+	int count, fragsize;
+	void (*start)(struct i810_state *);
+
+	count = dmabuf->count;
 	port = state->card->iobase;
-	if(rec)
+	if (rec) {
 		port += dmabuf->read_channel->port;
-	else
+		trigger = PCM_ENABLE_INPUT;
+		start = __start_adc;
+		count = dmabuf->dmasize - count;
+	} else {
 		port += dmabuf->write_channel->port;
+		trigger = PCM_ENABLE_OUTPUT;
+		start = __start_dac;
+	}
+
+	/* Do not process partial fragments. */
+	fragsize = dmabuf->fragsize;
+	if (count < fragsize)
+		return;
 
-	/* if we are currently stopped, then our CIV is actually set to our
-	 * *last* sg segment and we are ready to wrap to the next.  However,
-	 * if we set our LVI to the last sg segment, then it won't wrap to
-	 * the next sg segment, it won't even get a start.  So, instead, when
-	 * we are stopped, we set both the LVI value and also we increment
-	 * the CIV value to the next sg segment to be played so that when
-	 * we call start_{dac,adc}, things will operate properly
-	 */
 	if (!dmabuf->enable && dmabuf->ready) {
-		if(rec && dmabuf->count < dmabuf->dmasize &&
-		   (dmabuf->trigger & PCM_ENABLE_INPUT))
-		{
-			CIV_TO_LVI(port, 1);
-			__start_adc(state);
-			while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
-		} else if (!rec && dmabuf->count &&
-			   (dmabuf->trigger & PCM_ENABLE_OUTPUT))
-		{
-			CIV_TO_LVI(port, 1);
-			__start_dac(state);
-			while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
-		}
+		if (!(dmabuf->trigger & trigger))
+			return;
+
+		start(state);
+		while (!(inb(port + OFF_CR) & ((1<<4) | (1<<2))))
+			;
 	}
 
-	/* swptr - 1 is the tail of our transfer */
-	x = (dmabuf->dmasize + dmabuf->swptr - 1) % dmabuf->dmasize;
-	x /= dmabuf->fragsize;
-	outb(x, port+OFF_LVI);
+	/* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */
+	x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize);
+	x >>= dmabuf->fragshift;
+	outb(x, port + OFF_LVI);
 }
 
 static void i810_update_lvi(struct i810_state *state, int rec)
@@ -1126,13 +1086,17 @@ static void i810_update_ptr(struct i810_
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
 	unsigned hwptr;
+	unsigned fragmask, dmamask;
 	int diff;
 
-	/* error handling and process wake up for DAC */
+	fragmask = MASKP2(~0, dmabuf->fragsize);
+	dmamask = MODULOP2(~0, dmabuf->dmasize);
+
+	/* error handling and process wake up for ADC */
 	if (dmabuf->enable == ADC_RUNNING) {
 		/* update hardware pointer */
-		hwptr = i810_get_dma_addr(state, 1);
-		diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+		hwptr = i810_get_dma_addr(state, 1) & fragmask;
+		diff = (hwptr - dmabuf->hwptr) & dmamask;
 #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
 		printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
 #endif
@@ -1144,20 +1108,20 @@ static void i810_update_ptr(struct i810_
 			/* this is normal for the end of a read */
 			/* only give an error if we went past the */
 			/* last valid sg entry */
-			if((inb(state->card->iobase + PI_CIV) & 31) !=
-			   (inb(state->card->iobase + PI_LVI) & 31)) {
+			if (GET_CIV(state->card->iobase + PI_BASE) !=
+			    GET_LVI(state->card->iobase + PI_BASE)) {
 				printk(KERN_WARNING "i810_audio: DMA overrun on read\n");
 				dmabuf->error++;
 			}
 		}
-		if (dmabuf->count > dmabuf->userfragsize)
+		if (diff)
 			wake_up(&dmabuf->wait);
 	}
 	/* error handling and process wake up for DAC */
 	if (dmabuf->enable == DAC_RUNNING) {
 		/* update hardware pointer */
-		hwptr = i810_get_dma_addr(state, 0);
-		diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+		hwptr = i810_get_dma_addr(state, 0) & fragmask;
+		diff = (hwptr - dmabuf->hwptr) & dmamask;
 #if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
 		printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
 #endif
@@ -1169,18 +1133,18 @@ static void i810_update_ptr(struct i810_
 			/* this is normal for the end of a write */
 			/* only give an error if we went past the */
 			/* last valid sg entry */
-			if((inb(state->card->iobase + PO_CIV) & 31) !=
-			   (inb(state->card->iobase + PO_LVI) & 31)) {
+			if (GET_CIV(state->card->iobase + PO_BASE) !=
+			    GET_LVI(state->card->iobase + PO_BASE)) {
 				printk(KERN_WARNING "i810_audio: DMA overrun on write\n");
 				printk("i810_audio: CIV %d, LVI %d, hwptr %x, "
 					"count %d\n",
-					inb(state->card->iobase + PO_CIV) & 31,
-					inb(state->card->iobase + PO_LVI) & 31,
+					GET_CIV(state->card->iobase + PO_BASE),
+					GET_LVI(state->card->iobase + PO_BASE),
 					dmabuf->hwptr, dmabuf->count);
 				dmabuf->error++;
 			}
 		}
-		if (dmabuf->count < (dmabuf->dmasize-dmabuf->userfragsize))
+		if (diff)
 			wake_up(&dmabuf->wait);
 	}
 }
@@ -1197,7 +1161,6 @@ static inline int i810_get_free_write_sp
 		dmabuf->swptr = dmabuf->hwptr;
 	}
 	free = dmabuf->dmasize - dmabuf->count;
-	free -= (dmabuf->hwptr % dmabuf->fragsize);
 	if(free < 0)
 		return(0);
 	return(free);
@@ -1215,12 +1178,27 @@ static inline int i810_get_available_rea
 		dmabuf->swptr = dmabuf->hwptr;
 	}
 	avail = dmabuf->count;
-	avail -= (dmabuf->hwptr % dmabuf->fragsize);
 	if(avail < 0)
 		return(0);
 	return(avail);
 }
 
+static inline void fill_partial_frag(struct dmabuf *dmabuf)
+{
+	unsigned fragsize;
+	unsigned swptr, len;
+
+	fragsize = dmabuf->fragsize;
+	swptr = dmabuf->swptr;
+	len = fragsize - MODULOP2(dmabuf->swptr, fragsize);
+	if (len == fragsize)
+		return;
+
+	memset(dmabuf->rawbuf + swptr, '\0', len);
+	dmabuf->swptr = MODULOP2(swptr + len, dmabuf->dmasize);
+	dmabuf->count += len;
+}
+
 static int drain_dac(struct i810_state *state, int signals_allowed)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -1235,30 +1213,28 @@ static int drain_dac(struct i810_state *
 		stop_dac(state);
 		return 0;
 	}
+
+	spin_lock_irqsave(&state->card->lock, flags);
+
+	fill_partial_frag(dmabuf);
+
+	/* 
+	 * This will make sure that our LVI is correct, that our
+	 * pointer is updated, and that the DAC is running.  We
+	 * have to force the setting of dmabuf->trigger to avoid
+	 * any possible deadlocks.
+	 */
+	dmabuf->trigger = PCM_ENABLE_OUTPUT;
+	__i810_update_lvi(state, 0);
+
+	spin_unlock_irqrestore(&state->card->lock, flags);
+
 	add_wait_queue(&dmabuf->wait, &wait);
 	for (;;) {
 
 		spin_lock_irqsave(&state->card->lock, flags);
 		i810_update_ptr(state);
 		count = dmabuf->count;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (count <= 0)
-			break;
-
-		/* 
-		 * This will make sure that our LVI is correct, that our
-		 * pointer is updated, and that the DAC is running.  We
-		 * have to force the setting of dmabuf->trigger to avoid
-		 * any possible deadlocks.
-		 */
-		if(!dmabuf->enable) {
-			dmabuf->trigger = PCM_ENABLE_OUTPUT;
-			i810_update_lvi(state,0);
-		}
-                if (signal_pending(current) && signals_allowed) {
-                        break;
-                }
 
 		/* It seems that we have to set the current state to
 		 * TASK_INTERRUPTIBLE every time to make the process
@@ -1269,7 +1245,17 @@ static int drain_dac(struct i810_state *
 		 * instead of actually sleeping and waiting for an
 		 * interrupt to wake us up!
 		 */
-		set_current_state(TASK_INTERRUPTIBLE);
+		__set_current_state(signals_allowed ?
+				    TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		spin_unlock_irqrestore(&state->card->lock, flags);
+
+		if (count <= 0)
+			break;
+
+                if (signal_pending(current) && signals_allowed) {
+                        break;
+                }
+
 		/*
 		 * set the timeout to significantly longer than it *should*
 		 * take for the DAC to drain the DMA buffer
@@ -1350,11 +1336,10 @@ static void i810_channel_interrupt(struc
 			if(status & DMA_INT_DCH)
 				printk("DCH -");
 #endif
-			if(dmabuf->enable & DAC_RUNNING)
-				count = dmabuf->count;
-			else
-				count = dmabuf->dmasize - dmabuf->count;
-			if(count > 0) {
+			count = dmabuf->count;
+			if(dmabuf->enable & ADC_RUNNING)
+				count = dmabuf->dmasize - count;
+			if (count >= (int)dmabuf->fragsize) {
 				outb(inb(port+OFF_CR) | 1, port+OFF_CR);
 #ifdef DEBUG_INTERRUPTS
 				printk(" CONTINUE ");
@@ -1417,6 +1402,7 @@ static ssize_t i810_read(struct file *fi
 	unsigned long flags;
 	unsigned int swptr;
 	int cnt;
+	int pending;
         DECLARE_WAITQUEUE(waita, current);
 
 #ifdef DEBUG2
@@ -1442,6 +1428,8 @@ static ssize_t i810_read(struct file *fi
 		return -EFAULT;
 	ret = 0;
 
+	pending = 0;
+
         add_wait_queue(&dmabuf->wait, &waita);
 	while (count > 0) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1455,8 +1443,8 @@ static ssize_t i810_read(struct file *fi
                         }
                         continue;
                 }
-		swptr = dmabuf->swptr;
 		cnt = i810_get_available_read_data(state);
+		swptr = dmabuf->swptr;
 		// this is to make the copy_to_user simpler below
 		if(cnt > (dmabuf->dmasize - swptr))
 			cnt = dmabuf->dmasize - swptr;
@@ -1464,15 +1452,6 @@ static ssize_t i810_read(struct file *fi
 
 		if (cnt > count)
 			cnt = count;
-		/* Lop off the last two bits to force the code to always
-		 * write in full samples.  This keeps software that sets
-		 * O_NONBLOCK but doesn't check the return value of the
-		 * write call from getting things out of state where they
-		 * think a full 4 byte sample was written when really only
-		 * a portion was, resulting in odd sound and stereo
-		 * hysteresis.
-		 */
-		cnt &= ~0x3;
 		if (cnt <= 0) {
 			unsigned long tmo;
 			/*
@@ -1526,7 +1505,7 @@ static ssize_t i810_read(struct file *fi
 			goto done;
 		}
 
-		swptr = (swptr + cnt) % dmabuf->dmasize;
+		swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
 
 		spin_lock_irqsave(&card->lock, flags);
 
@@ -1535,7 +1514,7 @@ static ssize_t i810_read(struct file *fi
                         continue;
                 }
 		dmabuf->swptr = swptr;
-		dmabuf->count -= cnt;
+		pending = dmabuf->count -= cnt;
 		spin_unlock_irqrestore(&card->lock, flags);
 
 		count -= cnt;
@@ -1543,7 +1522,9 @@ static ssize_t i810_read(struct file *fi
 		ret += cnt;
 	}
  done:
-	i810_update_lvi(state,1);
+	pending = dmabuf->dmasize - pending;
+	if (dmabuf->enable || pending >= dmabuf->userfragsize)
+		i810_update_lvi(state, 1);
         set_current_state(TASK_RUNNING);
         remove_wait_queue(&dmabuf->wait, &waita);
 
@@ -1560,7 +1541,8 @@ static ssize_t i810_write(struct file *f
 	ssize_t ret;
 	unsigned long flags;
 	unsigned int swptr = 0;
-	int cnt, x;
+	int pending;
+	int cnt;
         DECLARE_WAITQUEUE(waita, current);
 
 #ifdef DEBUG2
@@ -1585,6 +1567,8 @@ static ssize_t i810_write(struct file *f
 		return -EFAULT;
 	ret = 0;
 
+	pending = 0;
+
         add_wait_queue(&dmabuf->wait, &waita);
 	while (count > 0) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1599,8 +1583,8 @@ static ssize_t i810_write(struct file *f
                         continue;
                 }
 
-		swptr = dmabuf->swptr;
 		cnt = i810_get_free_write_space(state);
+		swptr = dmabuf->swptr;
 		/* Bound the maximum size to how much we can copy to the
 		 * dma buffer before we hit the end.  If we have more to
 		 * copy then it will get done in a second pass of this
@@ -1615,15 +1599,6 @@ static ssize_t i810_write(struct file *f
 #endif
 		if (cnt > count)
 			cnt = count;
-		/* Lop off the last two bits to force the code to always
-		 * write in full samples.  This keeps software that sets
-		 * O_NONBLOCK but doesn't check the return value of the
-		 * write call from getting things out of state where they
-		 * think a full 4 byte sample was written when really only
-		 * a portion was, resulting in odd sound and stereo
-		 * hysteresis.
-		 */
-		cnt &= ~0x3;
 		if (cnt <= 0) {
 			unsigned long tmo;
 			// There is data waiting to be played
@@ -1668,7 +1643,7 @@ static ssize_t i810_write(struct file *f
 			goto ret;
 		}
 
-		swptr = (swptr + cnt) % dmabuf->dmasize;
+		swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
 
 		spin_lock_irqsave(&state->card->lock, flags);
                 if (PM_SUSPENDED(card)) {
@@ -1677,19 +1652,16 @@ static ssize_t i810_write(struct file *f
                 }
 
 		dmabuf->swptr = swptr;
-		dmabuf->count += cnt;
+		pending = dmabuf->count += cnt;
 
 		count -= cnt;
 		buffer += cnt;
 		ret += cnt;
 		spin_unlock_irqrestore(&state->card->lock, flags);
 	}
-	if (swptr % dmabuf->fragsize) {
-		x = dmabuf->fragsize - (swptr % dmabuf->fragsize);
-		memset(dmabuf->rawbuf + swptr, '\0', x);
-	}
 ret:
-	i810_update_lvi(state,0);
+	if (dmabuf->enable || pending >= dmabuf->userfragsize)
+		i810_update_lvi(state, 0);
         set_current_state(TASK_RUNNING);
         remove_wait_queue(&dmabuf->wait, &waita);
 
@@ -1938,8 +1910,8 @@ static int i810_ioctl(struct inode *inod
 		}
 
 		/* ICH and ICH0 only support 2 channels */
-		if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801 
-		     || state->card->pci_id == PCI_DEVICE_ID_INTEL_82901) 
+		if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AA_5
+		     || state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AB_5) 
 			return put_user(2, (int *)arg);
 	
 		/* Multi-channel support was added with ICH2. Bits in */
@@ -2179,6 +2151,13 @@ static int i810_ioctl(struct inode *inod
 #if defined(DEBUG) || defined(DEBUG_MMAP)
 		printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);
 #endif
+		/* silently ignore invalid PCM_ENABLE_xxx bits,
+		 * like the other drivers do
+		 */
+		if (!(file->f_mode & FMODE_READ ))
+			val &= ~PCM_ENABLE_INPUT;
+		if (!(file->f_mode & FMODE_WRITE ))
+			val &= ~PCM_ENABLE_OUTPUT;
 		if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
 			stop_adc(state);
 		}
@@ -2186,7 +2165,7 @@ static int i810_ioctl(struct inode *inod
 			stop_dac(state);
 		}
 		dmabuf->trigger = val;
-		if((file->f_mode & FMODE_WRITE) && (val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
+		if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
 			if (!dmabuf->write_channel) {
 				dmabuf->ready = 0;
 				dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);
@@ -2202,12 +2181,12 @@ static int i810_ioctl(struct inode *inod
 				dmabuf->swptr = dmabuf->hwptr;
 				dmabuf->count = i810_get_free_write_space(state);
 				dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize;
-				__i810_update_lvi(state, 0);
 				spin_unlock_irqrestore(&state->card->lock, flags);
-			} else
-				start_dac(state);
+			}
+			i810_update_lvi(state, 0);
+			start_dac(state);
 		}
-		if((file->f_mode & FMODE_READ) && (val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
+		if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
 			if (!dmabuf->read_channel) {
 				dmabuf->ready = 0;
 				dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);
@@ -2471,7 +2450,7 @@ found_virt:
 	if(file->f_mode & FMODE_READ) {
 		if((dmabuf->read_channel = card->alloc_rec_pcm_channel(card)) == NULL) {
 			kfree (card->states[i]);
-			card->states[i] = NULL;;
+			card->states[i] = NULL;
 			return -EBUSY;
 		}
 		dmabuf->trigger |= PCM_ENABLE_INPUT;
@@ -2483,7 +2462,7 @@ found_virt:
 			if(file->f_mode & FMODE_READ)
 				card->free_pcm_channel(card,dmabuf->read_channel->num);
 			kfree (card->states[i]);
-			card->states[i] = NULL;;
+			card->states[i] = NULL;
 			return -EBUSY;
 		}
 		/* Initialize to 8kHz?  What if we don't support 8kHz? */
@@ -2747,6 +2726,26 @@ static int i810_ac97_probe_and_powerup(s
 	return i;
 }
 
+static int is_new_ich(u16 pci_id)
+{
+	switch (pci_id) {
+	case PCI_DEVICE_ID_INTEL_82801DB_5:
+	case PCI_DEVICE_ID_INTEL_82801EB_5:
+	case PCI_DEVICE_ID_INTEL_ESB_5:
+	case PCI_DEVICE_ID_INTEL_ICH6_18:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static inline int ich_use_mmio(struct i810_card *card)
+{
+	return is_new_ich(card->pci_id) && card->use_mmio;
+}
+
 /**
  *	i810_ac97_power_up_bus	-	bring up AC97 link
  *	@card : ICH audio device to power up
@@ -2796,9 +2795,7 @@ static int i810_ac97_power_up_bus(struct
 	 */	
 	/* see i810_ac97_init for the next 7 lines (jsaw) */
 	inw(card->ac97base);
-	if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5 ||
-	     card->pci_id == PCI_DEVICE_ID_INTEL_ESB_5 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH6_3)
-	    && (card->use_mmio)) {
+	if (ich_use_mmio(card)) {
 		primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
 		       primary_codec_id);
@@ -2819,7 +2816,7 @@ static int i810_ac97_power_up_bus(struct
 	return 1;
 }
 
-static int __init i810_ac97_init(struct i810_card *card)
+static int __devinit i810_ac97_init(struct i810_card *card)
 {
 	int num_ac97 = 0;
 	int ac97_id;
@@ -2867,9 +2864,7 @@ static int __init i810_ac97_init(struct 
 		   possible IO channels. Bit 0:1 of SDM then holds the 
 		   last codec ID spoken to. 
 		*/
-		if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH5 ||
-		     card->pci_id == PCI_DEVICE_ID_INTEL_ESB_5 || card->pci_id == PCI_DEVICE_ID_INTEL_ICH6_3)
-		    && (card->use_mmio)) {
+		if (ich_use_mmio(card)) {
 			ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
 			printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
 			       num_ac97, ac97_id);
@@ -3024,7 +3019,7 @@ static int __init i810_ac97_init(struct 
 	return num_ac97;
 }
 
-static void __init i810_configure_clocking (void)
+static void __devinit i810_configure_clocking (void)
 {
 	struct i810_card *card;
 	struct i810_state *state;
@@ -3065,15 +3060,14 @@ static void __init i810_configure_clocki
 			goto config_out;
 		}
 		dmabuf->count = dmabuf->dmasize;
-		CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, 31);
-		save_flags(flags);
-		cli();
+		CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, -1);
+		local_irq_save(flags);
 		start_dac(state);
 		offset = i810_get_dma_addr(state, 0);
 		mdelay(50);
 		new_offset = i810_get_dma_addr(state, 0);
 		stop_dac(state);
-		restore_flags(flags);
+		local_irq_restore(flags);
 		i = new_offset - offset;
 #ifdef DEBUG_INTERRUPTS
 		printk("i810_audio: %d bytes in 50 milliseconds\n", i);
@@ -3097,7 +3091,7 @@ config_out_nodmabuf:
 /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
    until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
    
-static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
+static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
 {
 	struct i810_card *card;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/kahlua.c linux-2.4.27-rc4/drivers/sound/kahlua.c
--- linux-2.4.26/drivers/sound/kahlua.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/kahlua.c	2004-07-30 16:30:59.000000000 +0000
@@ -37,6 +37,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <asm/delay.h>
 
 #include "sound_config.h"
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/mpu401.c linux-2.4.27-rc4/drivers/sound/mpu401.c
--- linux-2.4.26/drivers/sound/mpu401.c	2003-06-13 14:51:36.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/mpu401.c	2004-07-30 16:31:28.000000000 +0000
@@ -1513,14 +1513,16 @@ static unsigned long mpu_timer_get_time(
 static int mpu_timer_ioctl(int dev, unsigned int command, caddr_t arg)
 {
 	int midi_dev = sound_timer_devs[dev]->devlink;
+	int *p = (int *)arg;
 
 	switch (command)
 	{
 		case SNDCTL_TMR_SOURCE:
 			{
 				int parm;
-	
-				parm = *(int *) arg;
+
+				if (get_user(parm, p))
+					return -EFAULT;
 				parm &= timer_caps;
 
 				if (parm != 0)
@@ -1532,7 +1534,9 @@ static int mpu_timer_ioctl(int dev, unsi
 					else if (timer_mode & TMR_MODE_SMPTE)
 						mpu_cmd(midi_dev, 0x3d, 0);		/* Use SMPTE sync */
 				}
-				return (*(int *) arg = timer_mode);
+				if (put_user(timer_mode, p))
+					return -EFAULT;
+				return timer_mode;
 			}
 			break;
 
@@ -1557,10 +1561,13 @@ static int mpu_timer_ioctl(int dev, unsi
 			{
 				int val;
 
-				val = *(int *) arg;
+				if (get_user(val, p))
+					return -EFAULT;
 				if (val)
 					set_timebase(midi_dev, val);
-				return (*(int *) arg = curr_timebase);
+				if (put_user(curr_timebase, p))
+					return -EFAULT;
+				return curr_timebase;
 			}
 			break;
 
@@ -1569,7 +1576,8 @@ static int mpu_timer_ioctl(int dev, unsi
 				int val;
 				int ret;
 
-				val = *(int *) arg;
+				if (get_user(val, p))
+					return -EFAULT;
 
 				if (val)
 				{
@@ -1584,7 +1592,9 @@ static int mpu_timer_ioctl(int dev, unsi
 					}
 					curr_tempo = val;
 				}
-				return (*(int *) arg = curr_tempo);
+				if (put_user(curr_tempo, p))
+					return -EFAULT;
+				return curr_tempo;
 			}
 			break;
 
@@ -1592,18 +1602,25 @@ static int mpu_timer_ioctl(int dev, unsi
 			{
 				int val;
 
-				val = *(int *) arg;
+				if (get_user(val, p))
+					return -EFAULT;
 				if (val != 0)		/* Can't change */
 					return -EINVAL;
-				return (*(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60);
+				val = (curr_tempo * curr_timebase + 30) / 60;
+				if (put_user(val, p))
+					return -EFAULT;
+				return val;
 			}
 			break;
 
 		case SNDCTL_SEQ_GETTIME:
-			return (*(int *) arg = curr_ticks);
+			if (put_user(curr_ticks, p))
+				return -EFAULT;
+			return curr_ticks;
 
 		case SNDCTL_TMR_METRONOME:
-			metronome_mode = *(int *) arg;
+			if (get_user(metronome_mode, p))
+				return -EFAULT;
 			setup_metronome(midi_dev);
 			return 0;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/msnd.c linux-2.4.27-rc4/drivers/sound/msnd.c
--- linux-2.4.26/drivers/sound/msnd.c	2001-09-30 19:26:08.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/msnd.c	2004-07-30 16:27:15.000000000 +0000
@@ -155,13 +155,10 @@ void msnd_fifo_make_empty(msnd_fifo *f)
 	f->len = f->tail = f->head = 0;
 }
 
-int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user)
+int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len)
 {
 	int count = 0;
 
-	if (f->len == f->n)
-		return 0;
-
 	while ((count < len) && (f->len != f->n)) {
 
 		int nwritten;
@@ -177,11 +174,7 @@ int msnd_fifo_write(msnd_fifo *f, const 
 				nwritten = len - count;
 		}
 
-		if (user) {
-			if (copy_from_user(f->data + f->tail, buf, nwritten))
-				return -EFAULT;
-		} else
-			isa_memcpy_fromio(f->data + f->tail, (unsigned long) buf, nwritten);
+		isa_memcpy_fromio(f->data + f->tail, (unsigned long) buf, nwritten);
 
 		count += nwritten;
 		buf += nwritten;
@@ -193,13 +186,10 @@ int msnd_fifo_write(msnd_fifo *f, const 
 	return count;
 }
 
-int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user)
+int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len)
 {
 	int count = 0;
 
-	if (f->len == 0)
-		return f->len;
-
 	while ((count < len) && (f->len > 0)) {
 
 		int nread;
@@ -215,11 +205,7 @@ int msnd_fifo_read(msnd_fifo *f, char *b
 				nread = len - count;
 		}
 
-		if (user) {
-			if (copy_to_user(buf, f->data + f->head, nread))
-				return -EFAULT;
-		} else
-			isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread);
+		isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread);
 
 		count += nread;
 		buf += nread;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/msnd.h linux-2.4.27-rc4/drivers/sound/msnd.h
--- linux-2.4.26/drivers/sound/msnd.h	2000-07-13 04:58:43.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/msnd.h	2004-07-30 16:29:04.000000000 +0000
@@ -266,8 +266,8 @@ void				msnd_fifo_init(msnd_fifo *f);
 void				msnd_fifo_free(msnd_fifo *f);
 int				msnd_fifo_alloc(msnd_fifo *f, size_t n);
 void				msnd_fifo_make_empty(msnd_fifo *f);
-int				msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user);
-int				msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user);
+int				msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len);
+int				msnd_fifo_read(msnd_fifo *f, char *buf, size_t len);
 
 int				msnd_wait_TXDE(multisound_dev_t *dev);
 int				msnd_wait_HC0(multisound_dev_t *dev);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/msnd_pinnacle.c linux-2.4.27-rc4/drivers/sound/msnd_pinnacle.c
--- linux-2.4.26/drivers/sound/msnd_pinnacle.c	2002-08-03 00:39:44.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/msnd_pinnacle.c	2004-07-30 16:29:25.000000000 +0000
@@ -804,7 +804,7 @@ static int dev_release(struct inode *ino
 
 static __inline__ int pack_DARQ_to_DARF(register int bank)
 {
-	register int size, n, timeout = 3;
+	register int size, timeout = 3;
 	register WORD wTmp;
 	LPDAQD DAQD;
 
@@ -825,13 +825,10 @@ static __inline__ int pack_DARQ_to_DARF(
 	/* Read data from the head (unprotected bank 1 access okay
            since this is only called inside an interrupt) */
 	outb(HPBLKSEL_1, dev.io + HP_BLKS);
-	if ((n = msnd_fifo_write(
+	msnd_fifo_write(
 		&dev.DARF,
 		(char *)(dev.base + bank * DAR_BUFF_SIZE),
-		size, 0)) <= 0) {
-		outb(HPBLKSEL_0, dev.io + HP_BLKS);
-		return n;
-	}
+		size);
 	outb(HPBLKSEL_0, dev.io + HP_BLKS);
 
 	return 1;
@@ -853,21 +850,16 @@ static __inline__ int pack_DAPF_to_DAPQ(
 		if (protect) {
 			/* Critical section: protect fifo in non-interrupt */
 			spin_lock_irqsave(&dev.lock, flags);
-			if ((n = msnd_fifo_read(
+			n = msnd_fifo_read(
 				&dev.DAPF,
 				(char *)(dev.base + bank_num * DAP_BUFF_SIZE),
-				DAP_BUFF_SIZE, 0)) < 0) {
-				spin_unlock_irqrestore(&dev.lock, flags);
-				return n;
-			}
+				DAP_BUFF_SIZE);
 			spin_unlock_irqrestore(&dev.lock, flags);
 		} else {
-			if ((n = msnd_fifo_read(
+			n = msnd_fifo_read(
 				&dev.DAPF,
 				(char *)(dev.base + bank_num * DAP_BUFF_SIZE),
-				DAP_BUFF_SIZE, 0)) < 0) {
-				return n;
-			}
+				DAP_BUFF_SIZE);
 		}
 		if (!n)
 			break;
@@ -894,30 +886,43 @@ static __inline__ int pack_DAPF_to_DAPQ(
 static int dsp_read(char *buf, size_t len)
 {
 	int count = len;
+	char *page = (char *)__get_free_page(PAGE_SIZE);
+
+	if (!page)
+		return -ENOMEM;
 
 	while (count > 0) {
-		int n;
+		int n, k;
 		unsigned long flags;
 
+		k = PAGE_SIZE;
+		if (k > count)
+			k = count;
+
 		/* Critical section: protect fifo in non-interrupt */
 		spin_lock_irqsave(&dev.lock, flags);
-		if ((n = msnd_fifo_read(&dev.DARF, buf, count, 1)) < 0) {
-			printk(KERN_WARNING LOGNAME ": FIFO read error\n");
-			spin_unlock_irqrestore(&dev.lock, flags);
-			return n;
-		}
+		n = msnd_fifo_read(&dev.DARF, page, k);
 		spin_unlock_irqrestore(&dev.lock, flags);
+		if (copy_to_user(buf, page, n)) {
+			free_page((unsigned long)page);
+			return -EFAULT;
+		}
 		buf += n;
 		count -= n;
 
+		if (n == k && count)
+			continue;
+
 		if (!test_bit(F_READING, &dev.flags) && dev.mode & FMODE_READ) {
 			dev.last_recbank = -1;
 			if (chk_send_dsp_cmd(&dev, HDEX_RECORD_START) == 0)
 				set_bit(F_READING, &dev.flags);
 		}
 
-		if (dev.rec_ndelay)
+		if (dev.rec_ndelay) {
+			free_page((unsigned long)page);
 			return count == len ? -EAGAIN : len - count;
+		}
 
 		if (count > 0) {
 			set_bit(F_READBLOCK, &dev.flags);
@@ -926,41 +931,57 @@ static int dsp_read(char *buf, size_t le
 				get_rec_delay_jiffies(DAR_BUFF_SIZE)))
 				clear_bit(F_READING, &dev.flags);
 			clear_bit(F_READBLOCK, &dev.flags);
-			if (signal_pending(current))
+			if (signal_pending(current)) {
+				free_page((unsigned long)page);
 				return -EINTR;
+			}
 		}
 	}
-
+	free_page((unsigned long)page);
 	return len - count;
 }
 
 static int dsp_write(const char *buf, size_t len)
 {
 	int count = len;
+	char *page = (char *)__get_free_page(GFP_KERNEL);
+
+	if (!page)
+		return -ENOMEM;
 
 	while (count > 0) {
-		int n;
+		int n, k;
 		unsigned long flags;
 
+		k = PAGE_SIZE;
+		if (k > count)
+			k = count;
+
+		if (copy_from_user(page, buf, k)) {
+			free_page((unsigned long)page);
+			return -EFAULT;
+		}
+
 		/* Critical section: protect fifo in non-interrupt */
 		spin_lock_irqsave(&dev.lock, flags);
-		if ((n = msnd_fifo_write(&dev.DAPF, buf, count, 1)) < 0) {
-			printk(KERN_WARNING LOGNAME ": FIFO write error\n");
-			spin_unlock_irqrestore(&dev.lock, flags);
-			return n;
-		}
+		n = msnd_fifo_write(&dev.DAPF, page, k);
 		spin_unlock_irqrestore(&dev.lock, flags);
 		buf += n;
 		count -= n;
 
+		if (count && n == k)
+			continue;
+
 		if (!test_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) {
 			dev.last_playbank = -1;
 			if (pack_DAPF_to_DAPQ(1) > 0)
 				set_bit(F_WRITING, &dev.flags);
 		}
 
-		if (dev.play_ndelay)
+		if (dev.play_ndelay) {
+			free_page((unsigned long)page);
 			return count == len ? -EAGAIN : len - count;
+		}
 
 		if (count > 0) {
 			set_bit(F_WRITEBLOCK, &dev.flags);
@@ -968,11 +989,14 @@ static int dsp_write(const char *buf, si
 				&dev.writeblock,
 				get_play_delay_jiffies(DAP_BUFF_SIZE));
 			clear_bit(F_WRITEBLOCK, &dev.flags);
-			if (signal_pending(current))
+			if (signal_pending(current)) {
+				free_page((unsigned long)page);
 				return -EINTR;
+			}
 		}
 	}
 
+	free_page((unsigned long)page);
 	return len - count;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/sound/pss.c linux-2.4.27-rc4/drivers/sound/pss.c
--- linux-2.4.26/drivers/sound/pss.c	2002-11-28 23:53:14.000000000 +0000
+++ linux-2.4.27-rc4/drivers/sound/pss.c	2004-07-30 16:32:15.000000000 +0000
@@ -450,20 +450,36 @@ static void pss_mixer_reset(pss_confdata
 	}
 }
 
-static void arg_to_volume_mono(unsigned int volume, int *aleft)
+static int set_volume_mono(caddr_t p, int *aleft)
 {
 	int left;
+	unsigned volume;
+	if (get_user(volume, (unsigned *)p))
+		return -EFAULT;
 	
-	left = volume & 0x00ff;
+	left = volume & 0xff;
 	if (left > 100)
 		left = 100;
 	*aleft = left;
+	return 0;
 }
 
-static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright)
+static int set_volume_stereo(caddr_t p, int *aleft, int *aright)
 {
-	arg_to_volume_mono(volume, aleft);
-	arg_to_volume_mono(volume >> 8, aright);
+	int left, right;
+	unsigned volume;
+	if (get_user(volume, (unsigned *)p))
+		return -EFAULT;
+
+	left = volume & 0xff;
+	if (left > 100)
+		left = 100;
+	right = (volume >> 8) & 0xff;
+	if (right > 100)
+		right = 100;
+	*aleft = left;
+	*aright = right;
+	return 0;
 }
 
 static int ret_vol_mono(int left)
@@ -510,33 +526,38 @@ static int pss_mixer_ioctl (int dev, uns
 					return call_ad_mixer(devc, cmd, arg);
 				else
 				{
-					if (*(int *)arg != 0)
+					int v;
+					if (get_user(v, (int *)arg))
+						return -EFAULT;
+					if (v != 0)
 						return -EINVAL;
 					return 0;
 				}
 			case SOUND_MIXER_VOLUME:
-				arg_to_volume_stereo(*(unsigned int *)arg, &devc->mixer.volume_l,
-					&devc->mixer.volume_r); 
+				if (set_volume_stereo(arg,
+					&devc->mixer.volume_l,
+					&devc->mixer.volume_r))
+					return -EFAULT;
 				set_master_volume(devc, devc->mixer.volume_l,
 					devc->mixer.volume_r);
 				return ret_vol_stereo(devc->mixer.volume_l,
 					devc->mixer.volume_r);
 		  
 			case SOUND_MIXER_BASS:
-				arg_to_volume_mono(*(unsigned int *)arg,
-					&devc->mixer.bass);
+				if (set_volume_mono(arg, &devc->mixer.bass))
+					return -EFAULT;
 				set_bass(devc, devc->mixer.bass);
 				return ret_vol_mono(devc->mixer.bass);
 		  
 			case SOUND_MIXER_TREBLE:
-				arg_to_volume_mono(*(unsigned int *)arg,
-					&devc->mixer.treble);
+				if (set_volume_mono(arg, &devc->mixer.treble))
+					return -EFAULT;
 				set_treble(devc, devc->mixer.treble);
 				return ret_vol_mono(devc->mixer.treble);
 		  
 			case SOUND_MIXER_SYNTH:
-				arg_to_volume_mono(*(unsigned int *)arg,
-					&devc->mixer.synth);
+				if (set_volume_mono(arg, &devc->mixer.synth))
+					return -EFAULT;
 				set_synth_volume(devc, devc->mixer.synth);
 				return ret_vol_mono(devc->mixer.synth);
 		  
@@ -546,54 +567,67 @@ static int pss_mixer_ioctl (int dev, uns
 	}
 	else			
 	{
+		int val, and_mask = 0, or_mask = 0;
 		/*
 		 * Return parameters
 		 */
 		switch (cmdf)
 		{
-
 			case SOUND_MIXER_DEVMASK:
 				if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
-					*(int *)arg = 0; /* no mixer devices */
-				return (*(int *)arg |= SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH);
+					break;
+				and_mask = ~0;
+				or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH;
+				break;
 		  
 			case SOUND_MIXER_STEREODEVS:
 				if (call_ad_mixer(devc, cmd, arg) == -EINVAL)
-					*(int *)arg = 0; /* no stereo devices */
-				return (*(int *)arg |= SOUND_MASK_VOLUME);
+					break;
+				and_mask = ~0;
+				or_mask = SOUND_MASK_VOLUME;
+				break;
 		  
 			case SOUND_MIXER_RECMASK:
 				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 					return call_ad_mixer(devc, cmd, arg);
-				else
-					return (*(int *)arg = 0); /* no record devices */
+				break;
 
 			case SOUND_MIXER_CAPS:
 				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 					return call_ad_mixer(devc, cmd, arg);
-				else
-					return (*(int *)arg = SOUND_CAP_EXCL_INPUT);
+				or_mask = SOUND_CAP_EXCL_INPUT;
+				break;
 
 			case SOUND_MIXER_RECSRC:
 				if (devc->ad_mixer_dev != NO_WSS_MIXER)
 					return call_ad_mixer(devc, cmd, arg);
-				else
-					return (*(int *)arg = 0); /* no record source */
+				break;
 
 			case SOUND_MIXER_VOLUME:
-				return (*(int *)arg = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r));
+				or_mask =  ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r);
+				break;
 			  
 			case SOUND_MIXER_BASS:
-				return (*(int *)arg = ret_vol_mono(devc->mixer.bass));
+				or_mask =  ret_vol_mono(devc->mixer.bass);
+				break;
 			  
 			case SOUND_MIXER_TREBLE:
-				return (*(int *)arg = ret_vol_mono(devc->mixer.treble));
+				or_mask = ret_vol_mono(devc->mixer.treble);
+				break;
 			  
 			case SOUND_MIXER_SYNTH:
-				return (*(int *)arg = ret_vol_mono(devc->mixer.synth));
+				or_mask = ret_vol_mono(devc->mixer.synth);
+				break;
 			default:
 				return -EINVAL;
 		}
+		if (get_user(val, (int *)arg))
+			return -EFAULT;
+		val &= and_mask;
+		val |= or_mask;
+		if (put_user(val, (int *)arg))
+			return -EFAULT;
+		return val;
 	}
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/audio.c linux-2.4.27-rc4/drivers/usb/audio.c
--- linux-2.4.26/drivers/usb/audio.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/audio.c	2004-07-30 16:31:52.000000000 +0000
@@ -2141,6 +2141,8 @@ static int usb_audio_ioctl_mixdev(struct
   
 	if (cmd == SOUND_MIXER_INFO) {
 		mixer_info info;
+
+		memset(&info, 0, sizeof(info));
 		strncpy(info.id, "USB_AUDIO", sizeof(info.id));
 		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));
 		info.modify_counter = ms->modcnt;
@@ -2150,6 +2152,8 @@ static int usb_audio_ioctl_mixdev(struct
 	}
 	if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
+
+		memset(&info, 0, sizeof(info));
 		strncpy(info.id, "USB_AUDIO", sizeof(info.id));
 		strncpy(info.name, "USB Audio Class Driver", sizeof(info.name));
 		if (copy_to_user((void *)arg, &info, sizeof(info)))
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/auermain.c linux-2.4.27-rc4/drivers/usb/auermain.c
--- linux-2.4.26/drivers/usb/auermain.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/auermain.c	2004-07-30 16:28:12.000000000 +0000
@@ -55,7 +55,7 @@ do {			\
 
 /*-------------------------------------------------------------------*/
 /* Version Information */
-#define DRIVER_VERSION "1.2.6"
+#define DRIVER_VERSION "1.2.7"
 #define DRIVER_AUTHOR  "Wolfgang Mües <wolfgang@iksw-muees.de>"
 #define DRIVER_DESC    "Auerswald PBX/System Telephone usb driver"
 
@@ -110,8 +110,8 @@ static int auerswald_status_retry(int st
 	case 0:
 	case -ETIMEDOUT:
 	case -EOVERFLOW:
+	case -EFBIG:
 	case -EAGAIN:
-	case -EPIPE:
 	case -EPROTO:
 	case -EILSEQ:
 	case -ENOSR:
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/brlvger.c linux-2.4.27-rc4/drivers/usb/brlvger.c
--- linux-2.4.26/drivers/usb/brlvger.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/brlvger.c	2004-07-30 16:27:22.000000000 +0000
@@ -743,6 +743,7 @@ brlvger_ioctl(struct inode *inode, struc
 	case BRLVGER_GET_INFO: {
 		struct brlvger_info vi;
 
+		memset(&vi, 0, sizeof(vi));
 		strncpy(vi.driver_version, DRIVER_VERSION,
 			sizeof(vi.driver_version));
 		vi.driver_version[sizeof(vi.driver_version)-1] = 0;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/Config.in linux-2.4.27-rc4/drivers/usb/gadget/Config.in
--- linux-2.4.26/drivers/usb/gadget/Config.in	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/Config.in	2004-07-30 16:28:22.000000000 +0000
@@ -53,6 +53,9 @@ if [ "$CONFIG_USB_GADGET" = "y" -o "$CON
 
   dep_tristate '  Gadget Zero (DEVELOPMENT)' CONFIG_USB_ZERO $CONFIG_USB_GADGET_CONTROLLER
   dep_tristate '  Ethernet Gadget (EXPERIMENTAL)' CONFIG_USB_ETH $CONFIG_USB_GADGET_CONTROLLER $CONFIG_NET
+  if [ "$CONFIG_USB_ETH" = "y" -o "$CONFIG_USB_ETH" = "m" ] ; then
+    bool       '    RNDIS support (EXPERIMENTAL)' CONFIG_USB_ETH_RNDIS
+  fi
   dep_tristate '  File-backed Storage Gadget (DEVELOPMENT)' CONFIG_USB_FILE_STORAGE $CONFIG_USB_GADGET_CONTROLLER
   dep_mbool '    File-backed Storage Gadget test mode' CONFIG_USB_FILE_STORAGE_TEST $CONFIG_USB_FILE_STORAGE
   
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/Makefile linux-2.4.27-rc4/drivers/usb/gadget/Makefile
--- linux-2.4.26/drivers/usb/gadget/Makefile	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/Makefile	2004-07-30 16:27:08.000000000 +0000
@@ -16,13 +16,17 @@ controller-$(CONFIG_USB_NET2280)	+= net2
 controller-$(CONFIG_USB_GOKU)		+= goku_udc.o
 
 # ... and only one of these, too; kbuild/kconfig don't help though.
-g_zero-objs			:= zero.o usbstring.o config.o
+g_zero-objs			:= zero.o usbstring.o config.o epautoconf.o
 obj-$(CONFIG_USB_ZERO)		+= g_zero.o
 
-g_ether-objs			:= ether.o usbstring.o config.o
+g_ether-objs			:= ether.o usbstring.o config.o epautoconf.o
+ifeq ($(CONFIG_USB_ETH_RNDIS),y)
+	g_ether-objs            += rndis.o
+endif
 obj-$(CONFIG_USB_ETH)		+= g_ether.o
 
-g_file_storage-objs		:= file_storage.o usbstring.o
+g_file_storage-objs		:= file_storage.o usbstring.o config.o \
+						epautoconf.o
 obj-$(CONFIG_USB_FILE_STORAGE)	+= g_file_storage.o
 
 export-objs :=			$(controller-y) $(controller-m)
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/config.c linux-2.4.27-rc4/drivers/usb/gadget/config.c
--- linux-2.4.26/drivers/usb/gadget/config.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/config.c	2004-07-30 16:26:40.000000000 +0000
@@ -51,7 +51,7 @@ usb_descriptor_fillbuf(void *buf, unsign
 	for (; 0 != *src; src++) {
 		unsigned		len = (*src)->bLength;
 
-		if (len > buflen);
+		if (len > buflen)
 			return -EINVAL;
 		memcpy(dest, *src, len);
 		buflen -= len;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/epautoconf.c linux-2.4.27-rc4/drivers/usb/gadget/epautoconf.c
--- linux-2.4.26/drivers/usb/gadget/epautoconf.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/epautoconf.c	2004-07-30 16:29:05.000000000 +0000
@@ -0,0 +1,308 @@
+/*
+ * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers
+ *
+ * Copyright (C) 2004 David Brownell
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+
+#include <asm/byteorder.h>
+
+#include "gadget_chips.h"
+
+
+/* we must assign addresses for configurable endpoints (like net2280) */
+static __initdata unsigned epnum;
+
+// #define MANY_ENDPOINTS
+#ifdef MANY_ENDPOINTS
+/* more than 15 configurable endpoints */
+static __initdata unsigned in_epnum;
+#endif
+
+
+/*
+ * This should work with endpoints from controller drivers sharing the
+ * same endpoint naming convention.  By example:
+ *
+ *	- ep1, ep2, ... address is fixed, not direction or type
+ *	- ep1in, ep2out, ... address and direction are fixed, not type
+ *	- ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
+ *	- ep1in-bulk, ep2out-iso, ... all three are fixed
+ *	- ep-* ... no functionality restrictions
+ *
+ * Type suffixes are "-bulk", "-iso", or "-int".  Numbers are decimal.
+ * Less common restrictions are implied by gadget_is_*().
+ */
+static int __init
+ep_matches (
+	struct usb_gadget		*gadget,
+	struct usb_ep			*ep,
+	struct usb_endpoint_descriptor	*desc
+)
+{
+	u8		type;
+	const char	*tmp;
+	u16		max;
+
+	/* endpoint already claimed? */
+	if (0 != ep->driver_data)
+		return 0;
+		
+	/* only support ep0 for portable CONTROL traffic */
+	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	if (USB_ENDPOINT_XFER_CONTROL == type)
+		return 0;
+
+	/* some other naming convention */
+	if ('e' != ep->name[0])
+		return 0;
+
+	/* type-restriction:  "-iso", "-bulk", or "-int".
+	 * direction-restriction:  "in", "out".
+	 */
+	if ('-' != ep->name[2]) {
+		tmp = strrchr (ep->name, '-');
+		if (tmp) {
+			switch (type) {
+			case USB_ENDPOINT_XFER_INT:
+				/* bulk endpoints handle interrupt transfers,
+				 * except the toggle-quirky iso-synch kind
+				 */
+				if ('s' == tmp[2])	// == "-iso"
+					return 0;
+				/* for now, avoid PXA "interrupt-in";
+				 * it's documented as never using DATA1.
+				 */
+				if (gadget_is_pxa (gadget)
+						&& 'i' == tmp [1])
+					return 0;
+				break;
+			case USB_ENDPOINT_XFER_BULK:
+				if ('b' != tmp[1])	// != "-bulk"
+					return 0;
+				break;
+			case USB_ENDPOINT_XFER_ISOC:
+				if ('s' != tmp[2])	// != "-iso"
+					return 0;
+			}
+		} else {
+			tmp = ep->name + strlen (ep->name);
+		}
+
+		/* direction-restriction:  "..in-..", "out-.." */
+		tmp--;
+		if (!isdigit (*tmp)) {
+			if (desc->bEndpointAddress & USB_DIR_IN) {
+				if ('n' != *tmp)
+					return 0;
+			} else {
+				if ('t' != *tmp)
+					return 0;
+			}
+		}
+	}
+
+	/* endpoint maxpacket size is an input parameter, except for bulk
+	 * where it's an output parameter representing the full speed limit.
+	 * the usb spec fixes high speed bulk maxpacket at 512 bytes.
+	 */
+	max = 0x7ff & le16_to_cpup (&desc->wMaxPacketSize);
+	switch (type) {
+	case USB_ENDPOINT_XFER_INT:
+		/* INT:  limit 64 bytes full speed, 1024 high speed */
+		if (!gadget->is_dualspeed && max > 64)
+			return 0;
+		/* FALLTHROUGH */
+
+	case USB_ENDPOINT_XFER_ISOC:
+		/* ISO:  limit 1023 bytes full speed, 1024 high speed */
+		if (ep->maxpacket < max)
+			return 0;
+		if (!gadget->is_dualspeed && max > 1023)
+			return 0;
+
+		/* BOTH:  "high bandwidth" works only at high speed */
+		if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) {
+			if (!gadget->is_dualspeed)
+				return 0;
+			/* configure your hardware with enough buffering!! */
+		}
+		break;
+	}
+
+	/* MATCH!! */
+
+	/* report address */
+	if (isdigit (ep->name [2])) {
+		u8	num = simple_strtol (&ep->name [2], NULL, 10);
+		desc->bEndpointAddress |= num;
+#ifdef	MANY_ENDPOINTS
+	} else if (desc->bEndpointAddress & USB_DIR_IN) {
+		if (++in_epnum > 15)
+			return 0;
+		desc->bEndpointAddress = USB_DIR_IN | in_epnum;
+#endif
+	} else {
+		if (++epnum > 15)
+			return 0;
+		desc->bEndpointAddress |= epnum;
+	}
+
+	/* report (variable) full speed bulk maxpacket */
+	if (USB_ENDPOINT_XFER_BULK == type) {
+		int size = ep->maxpacket;
+
+		/* min() doesn't work on bitfields with gcc-3.5 */
+		if (size > 64)
+			size = 64;
+		desc->wMaxPacketSize = cpu_to_le16(size);
+	}
+	return 1;
+}
+
+static struct usb_ep * __init
+find_ep (struct usb_gadget *gadget, const char *name)
+{
+	struct usb_ep	*ep;
+
+	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
+		if (0 == strcmp (ep->name, name))
+			return ep;
+	}
+	return 0;
+}
+
+/**
+ * usb_ep_autoconfig - choose an endpoint matching the descriptor
+ * @gadget: The device to which the endpoint must belong.
+ * @desc: Endpoint descriptor, with endpoint direction and transfer mode
+ *	initialized.  For periodic transfers, the maximum packet
+ *	size must also be initialized.  This is modified on success.
+ *
+ * By choosing an endpoint to use with the specified descriptor, this
+ * routine simplifies writing gadget drivers that work with multiple
+ * USB device controllers.  The endpoint would be passed later to
+ * usb_ep_enable(), along with some descriptor.
+ *
+ * That second descriptor won't always be the same as the first one.
+ * For example, isochronous endpoints can be autoconfigured for high
+ * bandwidth, and then used in several lower bandwidth altsettings.
+ * Also, high and full speed descriptors will be different.
+ *
+ * Be sure to examine and test the results of autoconfiguration on your
+ * hardware.  This code may not make the best choices about how to use the
+ * USB controller, and it can't know all the restrictions that may apply.
+ * Some combinations of driver and hardware won't be able to autoconfigure.
+ *
+ * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
+ * is initialized as if the endpoint were used at full speed.  To prevent
+ * the endpoint from being returned by a later autoconfig call, claim it
+ * by assigning ep->driver_data to some non-null value.
+ *
+ * On failure, this returns a null endpoint descriptor.
+ */
+struct usb_ep * __init usb_ep_autoconfig (
+	struct usb_gadget		*gadget,
+	struct usb_endpoint_descriptor	*desc
+)
+{
+	struct usb_ep	*ep;
+	u8		type;
+
+	type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+
+	/* First, apply chip-specific "best usage" knowledge.
+	 * This might make a good usb_gadget_ops hook ...
+	 */
+	if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) {
+		/* ep-e, ep-f are PIO with only 64 byte fifos */
+		ep = find_ep (gadget, "ep-e");
+		if (ep && ep_matches (gadget, ep, desc))
+			return ep;
+		ep = find_ep (gadget, "ep-f");
+		if (ep && ep_matches (gadget, ep, desc))
+			return ep;
+
+	} else if (gadget_is_goku (gadget)) {
+		if (USB_ENDPOINT_XFER_INT == type) {
+			/* single buffering is enough */
+			ep = find_ep (gadget, "ep3-bulk");
+			if (ep && ep_matches (gadget, ep, desc))
+				return ep;
+		} else if (USB_ENDPOINT_XFER_BULK == type
+				&& (USB_DIR_IN & desc->bEndpointAddress)) {
+			/* DMA may be available */
+			ep = find_ep (gadget, "ep2-bulk");
+			if (ep && ep_matches (gadget, ep, desc))
+				return ep;
+		}
+
+	} else if (gadget_is_sh (gadget) && USB_ENDPOINT_XFER_INT == type) {
+		/* single buffering is enough; maybe 8 byte fifo is too */
+		ep = find_ep (gadget, "ep3in-bulk");
+		if (ep && ep_matches (gadget, ep, desc))
+			return ep;
+
+	} else if (gadget_is_mq11xx (gadget) && USB_ENDPOINT_XFER_INT == type) {
+		ep = find_ep (gadget, "ep1-bulk");
+		if (ep && ep_matches (gadget, ep, desc))
+			return ep;
+	}
+
+	/* Second, look at endpoints until an unclaimed one looks usable */ 
+	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
+		if (ep_matches (gadget, ep, desc))
+			return ep;
+	}
+
+	/* Fail */
+	return 0;
+}
+
+/**
+ * usb_ep_autoconfig_reset - reset endpoint autoconfig state
+ * @gadget: device for which autoconfig state will be reset
+ *
+ * Use this for devices where one configuration may need to assign
+ * endpoint resources very differently from the next one.  It clears
+ * state such as ep->driver_data and the record of assigned endpoints
+ * used by usb_ep_autoconfig().
+ */
+void __init usb_ep_autoconfig_reset (struct usb_gadget *gadget)
+{
+	struct usb_ep	*ep;
+
+	list_for_each_entry (ep, &gadget->ep_list, ep_list) {
+		ep->driver_data = 0;
+	}
+#ifdef	MANY_ENDPOINTS
+	in_epnum = 0;
+#endif
+	epnum = 0;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/ether.c linux-2.4.27-rc4/drivers/usb/gadget/ether.c
--- linux-2.4.26/drivers/usb/gadget/ether.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/ether.c	2004-07-30 16:25:02.000000000 +0000
@@ -1,7 +1,8 @@
 /*
  * ether.c -- Ethernet gadget driver, with CDC and non-CDC options
  *
- * Copyright (C) 2003 David Brownell
+ * Copyright (C) 2003-2004 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  *
  * 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
@@ -23,8 +24,8 @@
 // #define VERBOSE
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
@@ -37,6 +38,8 @@
 #include <linux/interrupt.h>
 #include <linux/uts.h>
 #include <linux/version.h>
+#include <linux/moduleparam.h>
+#include <linux/ctype.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -53,6 +56,8 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 
+#include "gadget_chips.h"
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -60,39 +65,54 @@
  *
  * CDC Ethernet is the standard USB solution for sending Ethernet frames
  * using USB.  Real hardware tends to use the same framing protocol but look
- * different for control features.  And Microsoft pushes their own approach
- * (RNDIS) instead of the standard.
+ * different for control features.  This driver strongly prefers to use
+ * this USB-IF standard as its open-systems interoperability solution;
+ * most host side USB stacks (except from Microsoft) support it.
  *
  * There's some hardware that can't talk CDC.  We make that hardware
  * implement a "minimalist" vendor-agnostic CDC core:  same framing, but
  * link-level setup only requires activating the configuration.
+ * Linux supports it, but other host operating systems may not.
+ * (This is a subset of CDC Ethernet.)
+ *
+ * A third option is also in use.  Rather than CDC Ethernet, or something
+ * simpler, Microsoft pushes their own approach: RNDIS.  The published
+ * RNDIS specs are ambiguous and appear to be incomplete, and are also
+ * needlessly complex.
  */
 
 #define DRIVER_DESC		"Ethernet Gadget"
-#define DRIVER_VERSION		"Bastille Day 2003"
+#define DRIVER_VERSION		"St Patrick's Day 2004"
 
 static const char shortname [] = "ether";
 static const char driver_desc [] = DRIVER_DESC;
 
-#define MIN_PACKET	sizeof(struct ethhdr)
-#define	MAX_PACKET	ETH_DATA_LEN	/* biggest packet we'll rx/tx */
 #define RX_EXTRA	20		/* guard against rx overflows */
 
-/* FIXME allow high speed jumbograms */
-
-/*-------------------------------------------------------------------------*/
+#ifdef	CONFIG_USB_ETH_RNDIS
+#include "rndis.h"
+#else
+#define rndis_init() 0
+#define rndis_exit() do{}while(0)
+#endif
 
+/* 2.6-compat */
 #ifndef container_of
-#define container_of		list_entry
+#define container_of	list_entry
 #endif
 
-/* 2.5 modified and renamed these */
-#ifndef	INIT_WORK
-#define work_struct		tq_struct
-#define INIT_WORK		INIT_TQUEUE
+#include <linux/tqueue.h>
+#define	work_struct		tq_struct
+#define	INIT_WORK		INIT_TQUEUE
 #define schedule_work		schedule_task
 #define	flush_scheduled_work	flush_scheduled_tasks
-#endif
+
+static void random_ether_addr (u8 *addr)
+{
+	get_random_bytes (addr, ETH_ALEN);
+	addr [0] &= 0xfe;	// clear multicast bit
+	addr [0] |= 0x02;	// set local assignment bit (IEEE802)
+}
 
 /*-------------------------------------------------------------------------*/
 
@@ -112,219 +132,147 @@ struct eth_dev {
 	atomic_t		tx_qlen;
 
 	struct work_struct	work;
+	unsigned		zlp:1;
+	unsigned		cdc:1;
+	unsigned		rndis:1;
+	unsigned		suspended:1;
+	u16			cdc_filter;
 	unsigned long		todo;
 #define	WORK_RX_MEMORY		0
+	int			rndis_config;
+	u8			host_mac [ETH_ALEN];
 };
 
+/* This version autoconfigures as much as possible at run-time.
+ *
+ * It also ASSUMES a self-powered device, without remote wakeup,
+ * although remote wakeup support would make sense.
+ */
+static const char *EP_IN_NAME;
+static const char *EP_OUT_NAME;
+static const char *EP_STATUS_NAME;
+
 /*-------------------------------------------------------------------------*/
 
-/* Thanks to NetChip Technologies for donating this product ID.
- *
- * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+/* DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
  * Instead:  allocate your own, using normal USB-IF procedures.
  */
-#define DRIVER_VENDOR_NUM	0x0525		/* NetChip */
-#define DRIVER_PRODUCT_NUM	0xa4a1		/* Linux-USB Ethernet Gadget */
 
-/*-------------------------------------------------------------------------*/
+/* Thanks to NetChip Technologies for donating this product ID.
+ * It's for devices with only CDC Ethernet configurations.
+ */
+#define CDC_VENDOR_NUM	0x0525		/* NetChip */
+#define CDC_PRODUCT_NUM	0xa4a1		/* Linux-USB Ethernet Gadget */
 
-/*
- * hardware-specific configuration, controlled by which device
- * controller driver was configured.
- *
- * CHIP ... hardware identifier
- * DRIVER_VERSION_NUM ... alerts the host side driver to differences
- * EP_*_NAME ... which endpoints do we use for which purpose?
- * EP_*_NUM ... numbers for them (often limited by hardware)
- * WAKEUP ... if hardware supports remote wakeup AND we will issue the
- * 	usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
- *
- * hw_optimize(gadget) ... for any hardware tweaks we want to kick in
- * 	before we enable our endpoints
+/* For hardware that can't talk CDC, we use the same vendor ID that
+ * ARM Linux has used for ethernet-over-usb, both with sa1100 and
+ * with pxa250.  We're protocol-compatible, if the host-side drivers
+ * use the endpoint descriptors.  bcdDevice (version) is nonzero, so
+ * drivers that need to hard-wire endpoint numbers have a hook.
  *
- * add other defines for other portability issues, like hardware that
- * for some reason doesn't handle full speed bulk maxpacket of 64.
+ * The protocol is a minimal subset of CDC Ether, which works on any bulk
+ * hardware that's not deeply broken ... even on hardware that can't talk
+ * RNDIS (like SA-1100, with no interrupt endpoint, or anything that
+ * doesn't handle control-OUT).
  */
+#define	SIMPLE_VENDOR_NUM	0x049f
+#define	SIMPLE_PRODUCT_NUM	0x505a
 
-#define DEV_CONFIG_VALUE	3	/* some hardware cares */
-
-/* #undef on hardware that can't implement CDC */
-#define	DEV_CONFIG_CDC
+/* For hardware that can talk RNDIS and either of the above protocols,
+ * use this ID ... the windows INF files will know it.  Unless it's
+ * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose
+ * the non-RNDIS configuration.
+ */
+#define RNDIS_VENDOR_NUM	0x0525	/* NetChip */
+#define RNDIS_PRODUCT_NUM	0xa4a2	/* Ethernet/RNDIS Gadget */
 
-/* undef on bus-powered hardware, and #define MAX_USB_POWER */
-#define SELFPOWER
 
-/*
- * NetChip 2280, PCI based.
- *
- * use DMA with fat fifos for all data traffic, PIO for the status channel
- * where its 64 byte maxpacket ceiling is no issue.
- *
- * performance note:  only PIO needs per-usb-packet IRQs (ep0, ep-e, ep-f)
- * otherwise IRQs are per-Ethernet-packet unless TX_DELAY and chaining help.
+/* Some systems will want different product identifers published in the
+ * device descriptor, either numbers or strings or both.  These string
+ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
  */
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP			"net2280"
-#define DEFAULT_QLEN		4		/* has dma chaining */
-#define DRIVER_VERSION_NUM	0x0111
-static const char EP_OUT_NAME [] = "ep-a";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep-b";
-#define EP_IN_NUM	2
-static const char EP_STATUS_NAME [] = "ep-f";
-#define EP_STATUS_NUM	3
-/* supports remote wakeup, but this driver doesn't */
 
-extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
+static ushort __initdata idVendor;
+module_param(idVendor, ushort, 0);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
 
-static inline void hw_optimize (struct usb_gadget *gadget)
-{
-	/* we can have bigger ep-a/ep-b fifos (2KB each, 4 USB packets
-	 * for highspeed bulk) because we're not using ep-c/ep-d.
-	 */
-	net2280_set_fifo_mode (gadget, 1);
-}
-#endif
+static ushort __initdata idProduct;
+module_param(idProduct, ushort, 0);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
 
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable ARM PDAs
- * and other products.  The IXP-42x UDC is register-compatible.
- *
- * multiple interfaces (or altsettings) aren't usable.  so this hardware
- * can't implement CDC, which needs both capabilities.
- */
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#undef	DEV_CONFIG_CDC
-#define CHIP			"pxa2xx"
-#define DRIVER_VERSION_NUM	0x0113
-static const char EP_OUT_NAME [] = "ep2out-bulk";
-#define EP_OUT_NUM	2
-static const char EP_IN_NAME [] = "ep1in-bulk";
-#define EP_IN_NUM	1
-/* supports remote wakeup, but this driver doesn't */
+static ushort __initdata bcdDevice;
+module_param(bcdDevice, ushort, 0);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
 
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0)
-#endif
+static char *__initdata iManufacturer;
+MODULE_PARM(iManufacturer, "s");
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
 
-/*
- * SA-1100 UDC:  widely used in first gen Linux-capable PDAs.
- *
- * can't have a notification endpoint, since there are only the two
- * bulk-capable ones.  the CDC spec allows that.
- */
-#ifdef	CONFIG_USB_GADGET_SA1100
-#define CHIP			"sa1100"
-#define DRIVER_VERSION_NUM	0x0115
-static const char EP_OUT_NAME [] = "ep1out-bulk";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep2in-bulk";
-#define EP_IN_NUM	2
-// EP_STATUS_NUM is undefined
-/* doesn't support remote wakeup? */
+static char *__initdata iProduct;
+MODULE_PARM(iProduct, "s");
+MODULE_PARM_DESC(iProduct, "USB Product string");
 
-/* no hw optimizations to apply */
-#define hw_optimize(g) do {} while (0)
-#endif
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *__initdata dev_addr;
+MODULE_PARM(dev_addr, "s");
+MODULE_PARM_DESC(dev_addr, "Device Ethernet Address");
 
-/*
- * Toshiba TC86C001 ("Goku-S") UDC
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- */
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP			"goku"
-#define DRIVER_VERSION_NUM	0x0116
-static const char EP_OUT_NAME [] = "ep1-bulk";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep2-bulk";
-#define EP_IN_NUM	2
-static const char EP_STATUS_NAME [] = "ep3-bulk";
-#define EP_STATUS_NUM	3
-/* doesn't support remote wakeup */
+/* this address is invisible to ifconfig */
+static char *__initdata host_addr;
+MODULE_PARM(host_addr, "s");
+MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
+
+
+/*-------------------------------------------------------------------------*/
 
-#define hw_optimize(g) do {} while (0)
+/* Include CDC support if we could run on CDC-capable hardware. */
+
+#ifdef CONFIG_USB_GADGET_NET2280
+#define	DEV_CONFIG_CDC
 #endif
 
-/*
- * SuperH UDC:  UDC built-in to some Renesas SH processors.
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- *
- * Only one configuration and interface is supported.  So this hardware
- * can't implement CDC.
- */
-#ifdef	CONFIG_USB_GADGET_SUPERH
-#undef	DEV_CONFIG_CDC
-#define CHIP			"superh"
-#define DRIVER_VERSION_NUM	0x0117
-static const char EP_OUT_NAME[] = "ep1out-bulk";
-#define EP_OUT_NUM		1
-static const char EP_IN_NAME[] = "ep2in-bulk";
-#define EP_IN_NUM		2
+#ifdef CONFIG_USB_GADGET_DUMMY_HCD
+#define	DEV_CONFIG_CDC
+#endif
 
-#define hw_optimize(g) do {} while (0)
+#ifdef CONFIG_USB_GADGET_GOKU
+#define	DEV_CONFIG_CDC
 #endif
 
-/*-------------------------------------------------------------------------*/
+#ifdef CONFIG_USB_GADGET_MQ11XX
+#define	DEV_CONFIG_CDC
+#endif
 
-#ifndef CHIP
-#	error Configure some USB peripheral controller driver!
+#ifdef CONFIG_USB_GADGET_OMAP
+#define	DEV_CONFIG_CDC
 #endif
 
-/* We normally expect hardware that can talk CDC.  That involves
- * using multiple interfaces and altsettings, and maybe a status
- * interrupt.  Driver binding to be done according to USB-IF class,
- * though you can use different VENDOR and PRODUCT numbers if you
- * want (and they're officially assigned).
- * 
- * For hardware that can't talk CDC, we use the same vendor ID that
- * ARM Linux has used for ethernet-over-usb, both with sa1100 and
- * with pxa250.  We're protocol-compatible, if the host-side drivers
- * use the endpoint descriptors.  DRIVER_VERSION_NUM is nonzero, so
- * drivers that need to hard-wire endpoint numbers have a hook.
+
+/* For CDC-incapable hardware, choose the simple cdc subset.
+ * Anything that talks bulk (without notable bugs) can do this.
  */
-#ifdef	DEV_CONFIG_CDC
-#define	DEV_CONFIG_CLASS	USB_CLASS_COMM
-#else	
-#define	DEV_CONFIG_CLASS	USB_CLASS_VENDOR_SPEC
-#undef	EP_STATUS_NUM
-#undef	DRIVER_VENDOR_NUM
-#undef	DRIVER_PRODUCT_NUM
-#define	DRIVER_VENDOR_NUM	0x049f
-#define	DRIVER_PRODUCT_NUM	0x505a
-#endif /* CONFIG_CDC_ETHER */
-
-/* power usage is config specific.
- * hardware that supports remote wakeup defaults to disabling it.
- */
-
-#ifndef	MAX_USB_POWER
-#ifdef	SELFPOWER
-/* some hosts are confused by 0mA  */
-#define MAX_USB_POWER	2	/* mA */
-#else
-/* bus powered */
-#error	Define your bus power consumption!
+#ifdef CONFIG_USB_GADGET_PXA2XX
+#define	DEV_CONFIG_SUBSET
+#endif
+
+#ifdef CONFIG_USB_GADGET_SH
+#define	DEV_CONFIG_SUBSET
 #endif
-#endif	/* MAX_USB_POWER */
 
-#ifndef	WAKEUP
-/* default: this driver won't do remote wakeup */
-#define WAKEUP		0
-/* else value must be USB_CONFIG_ATT_WAKEUP */
+#ifdef CONFIG_USB_GADGET_SA1100
+/* use non-CDC for backwards compatibility */
+#define	DEV_CONFIG_SUBSET
 #endif
 
+
 /*-------------------------------------------------------------------------*/
 
-#ifndef DEFAULT_QLEN
 #define DEFAULT_QLEN	2	/* double buffering by default */
-#endif
 
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 
 static unsigned qmult = 5;
-MODULE_PARM (qmult, "i");
+module_param (qmult, uint, 0);
 
 
 /* for dual-speed hardware, use deeper queues at highspeed */
@@ -332,10 +280,14 @@ MODULE_PARM (qmult, "i");
 	(DEFAULT_QLEN*((gadget->speed == USB_SPEED_HIGH) ? qmult : 1))
 
 /* also defer IRQs on highspeed TX */
-#define TX_DELAY	DEFAULT_QLEN
+#define TX_DELAY	qmult
+
+#define	BITRATE(g) ((g->speed == USB_SPEED_HIGH) ? 4800000 : 120000)
 
 #else	/* full speed (low speed doesn't do bulk) */
 #define qlen(gadget) DEFAULT_QLEN
+
+#define	BITRATE(g)	(12000)
 #endif
 
 
@@ -376,8 +328,13 @@ MODULE_PARM (qmult, "i");
 
 /*
  * DESCRIPTORS ... most are static, but strings and (full) configuration
- * descriptors are built on demand.  Notice how most of the cdc descriptors
- * aren't needed in the "minimalist" mode.
+ * descriptors are built on demand.  For now we do either full CDC, or
+ * our simple subset, with RNDIS as an optional second configuration.
+ *
+ * RNDIS includes some CDC ACM descriptors ... like CDC Ethernet.  But
+ * the class descriptors match a modem (they're ignored; it's really just
+ * Ethernet functionality), they don't need the NOP altsetting, and the
+ * status transfer endpoint isn't optional.
  */
 
 #define STRING_MANUFACTURER		1
@@ -385,12 +342,24 @@ MODULE_PARM (qmult, "i");
 #define STRING_ETHADDR			3
 #define STRING_DATA			4
 #define STRING_CONTROL			5
+#define STRING_RNDIS_CONTROL		6
+#define STRING_CDC			7
+#define STRING_SUBSET			8
+#define STRING_RNDIS			9
 
 #define USB_BUFSIZ	256		/* holds our biggest descriptor */
 
 /*
- * This device advertises one configuration.
+ * This device advertises one configuration, eth_config, unless RNDIS
+ * is enabled (rndis_config) on hardware supporting at least two configs.
+ *
+ * NOTE:  Controllers like superh_udc should probably be able to use
+ * an RNDIS-only configuration.
  */
+
+#define DEV_CONFIG_VALUE	1	/* cdc or subset */
+#define DEV_RNDIS_CONFIG_VALUE	2	/* rndis; optional */
+
 static struct usb_device_descriptor
 device_desc = {
 	.bLength =		sizeof device_desc,
@@ -398,13 +367,12 @@ device_desc = {
 
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
 
-	.bDeviceClass =		DEV_CONFIG_CLASS,
+	.bDeviceClass =		USB_CLASS_COMM,
 	.bDeviceSubClass =	0,
 	.bDeviceProtocol =	0,
 
-	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
-	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
-	.bcdDevice =		__constant_cpu_to_le16 (DRIVER_VERSION_NUM),
+	.idVendor =		__constant_cpu_to_le16 (CDC_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16 (CDC_PRODUCT_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.bNumConfigurations =	1,
@@ -416,44 +384,70 @@ eth_config = {
 	.bDescriptorType =	USB_DT_CONFIG,
 
 	/* compute wTotalLength on the fly */
-#ifdef	DEV_CONFIG_CDC
 	.bNumInterfaces =	2,
-#else
-	.bNumInterfaces =	1,
-#endif
 	.bConfigurationValue =	DEV_CONFIG_VALUE,
-	.iConfiguration =	STRING_PRODUCT,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | WAKEUP,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.iConfiguration =	STRING_CDC,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,
 };
 
-#ifdef	DEV_CONFIG_CDC
+#ifdef	CONFIG_USB_ETH_RNDIS
+static const struct usb_config_descriptor 
+rndis_config = {
+	.bLength =              sizeof rndis_config,
+	.bDescriptorType =      USB_DT_CONFIG,
+
+	/* compute wTotalLength on the fly */
+	.bNumInterfaces =       2,
+	.bConfigurationValue =  DEV_RNDIS_CONFIG_VALUE,
+	.iConfiguration =       STRING_RNDIS,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =            1,
+};
+#endif
 
 /*
- * Compared to the "minimalist" non-CDC model, the CDC model adds
- * three class descriptors, two interface descrioptors, and a status
+ * Compared to the simple CDC subset, the full CDC Ethernet model adds
+ * three class descriptors, two interface descriptors, optional status
  * endpoint.  Both have a "data" interface and two bulk endpoints.
  * There are also differences in how control requests are handled.
+ *
+ * RNDIS shares a lot with CDC-Ethernet, since it's a variant of
+ * the CDC-ACM (modem) spec.
  */
 
-/* master comm interface optionally has a status notification endpoint */
-
-static const struct usb_interface_descriptor
+#ifdef	DEV_CONFIG_CDC
+static struct usb_interface_descriptor
 control_intf = {
 	.bLength =		sizeof control_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
 	.bInterfaceNumber =	0,
-#ifdef	EP_STATUS_NUM
+	/* status endpoint is optional; this may be patched later */
 	.bNumEndpoints =	1,
-#else
-	.bNumEndpoints =	0,
-#endif
 	.bInterfaceClass =	USB_CLASS_COMM,
 	.bInterfaceSubClass =	6,	/* ethernet control model */
 	.bInterfaceProtocol =	0,
 	.iInterface =		STRING_CONTROL,
 };
+#endif
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+static const struct usb_interface_descriptor
+rndis_control_intf = {
+	.bLength =              sizeof rndis_control_intf,
+	.bDescriptorType =      USB_DT_INTERFACE,
+	  
+	.bInterfaceNumber =     0,
+	.bNumEndpoints =        1,
+	.bInterfaceClass =      USB_CLASS_COMM,
+	.bInterfaceSubClass =   2,	/* abstract control model */
+	.bInterfaceProtocol =   0xff,	/* vendor specific */
+	.iInterface =           STRING_RNDIS_CONTROL,
+};
+#endif
+
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct header_desc {
@@ -466,13 +460,13 @@ struct header_desc {
 
 static const struct header_desc header_desc = {
 	.bLength =		sizeof header_desc,
-	.bDescriptorType =	0x24,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	0,
 
 	.bcdCDC =		__constant_cpu_to_le16 (0x0110),
 };
 
-/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
+/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
 struct union_desc {
 	u8	bLength;
 	u8	bDescriptorType;
@@ -485,13 +479,58 @@ struct union_desc {
 
 static const struct union_desc union_desc = {
 	.bLength =		sizeof union_desc,
-	.bDescriptorType =	0x24,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	6,
 
 	.bMasterInterface0 =	0,	/* index of control interface */
 	.bSlaveInterface0 =	1,	/* index of DATA interface */
 };
 
+#endif	/* CDC || RNDIS */
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+
+/* "Call Management Descriptor" from CDC spec  5.2.3.3 */
+struct call_mgmt_descriptor {
+	u8  bLength;
+	u8  bDescriptorType;
+	u8  bDescriptorSubType;
+
+	u8  bmCapabilities;
+	u8  bDataInterface;
+} __attribute__ ((packed));
+
+static const struct call_mgmt_descriptor call_mgmt_descriptor = {
+	.bLength =  		sizeof call_mgmt_descriptor,
+	.bDescriptorType = 	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType = 	0x01,
+
+	.bmCapabilities = 	0x00,
+	.bDataInterface = 	0x01,
+};
+
+
+/* "Abstract Control Management Descriptor" from CDC spec  5.2.3.4 */
+struct acm_descriptor {
+	u8  bLength;
+	u8  bDescriptorType;
+	u8  bDescriptorSubType;
+
+	u8  bmCapabilities;
+} __attribute__ ((packed));
+
+static struct acm_descriptor acm_descriptor = {
+	.bLength =  		sizeof acm_descriptor,
+	.bDescriptorType = 	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType = 	0x02,
+
+	.bmCapabilities = 	0X00,
+};
+
+#endif
+
+#ifdef	DEV_CONFIG_CDC
+
 /* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
 struct ether_desc {
 	u8	bLength;
@@ -507,41 +546,53 @@ struct ether_desc {
 
 static const struct ether_desc ether_desc = {
 	.bLength =		sizeof ether_desc,
-	.bDescriptorType =	0x24,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubType =	0x0f,
 
 	/* this descriptor actually adds value, surprise! */
 	.iMACAddress =		STRING_ETHADDR,
 	.bmEthernetStatistics =	__constant_cpu_to_le32 (0), /* no statistics */
-	.wMaxSegmentSize =	__constant_cpu_to_le16 (MAX_PACKET + ETH_HLEN),
+	.wMaxSegmentSize =	__constant_cpu_to_le16 (ETH_FRAME_LEN),
 	.wNumberMCFilters =	__constant_cpu_to_le16 (0),
 	.bNumberPowerFilters =	0,
 };
 
-#ifdef	EP_STATUS_NUM
+#endif
 
-/* include the status endpoint if we can, even though it's optional.
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+
+/* include the status endpoint if we can, even where it's optional.
+ * use small wMaxPacketSize, since many "interrupt" endpoints have
+ * very small fifos and it's no big deal if CDC_NOTIFY_SPEED_CHANGE
+ * takes two packets.  also default to a big transfer interval, to
+ * waste less bandwidth.
  *
- * some drivers (like current Linux cdc-ether!) "need" it to exist even
+ * some drivers (like Linux 2.4 cdc-ether!) "need" it to exist even
  * if they ignore the connect/disconnect notifications that real aether
  * can provide.  more advanced cdc configurations might want to support
  * encapsulated commands (vendor-specific, using control-OUT).
+ *
+ * RNDIS requires the status endpoint, since it uses that encapsulation
+ * mechanism for its funky RPC scheme.
  */
  
-#define LOG2_STATUS_INTERVAL_MSEC	6
-#define STATUS_BYTECOUNT		16	/* 8 byte header + data */
-static const struct usb_endpoint_descriptor
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define STATUS_BYTECOUNT		8	/* 8 byte header + data */
+
+static struct usb_endpoint_descriptor
 fs_status_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_STATUS_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
 	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
 };
 #endif
 
+#ifdef	DEV_CONFIG_CDC
+
 /* the default data interface has no endpoints ... */
 
 static const struct usb_interface_descriptor
@@ -555,10 +606,9 @@ data_nop_intf = {
 	.bInterfaceClass =	USB_CLASS_CDC_DATA,
 	.bInterfaceSubClass =	0,
 	.bInterfaceProtocol =	0,
-	.iInterface =		STRING_DATA,
 };
 
-/* ... but the "real" data interface has two full speed bulk endpoints */
+/* ... but the "real" data interface has two bulk endpoints */
 
 static const struct usb_interface_descriptor
 data_intf = {
@@ -573,16 +623,39 @@ data_intf = {
 	.bInterfaceProtocol =	0,
 	.iInterface =		STRING_DATA,
 };
-#else
+
+#endif
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+
+/* RNDIS doesn't activate by changing to the "real" altsetting */
+
+static const struct usb_interface_descriptor
+rndis_data_intf = {
+	.bLength =		sizeof rndis_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	.bInterfaceNumber =	1,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	USB_CLASS_CDC_DATA,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	.iInterface =		STRING_DATA,
+};
+
+#endif
+
+#ifdef DEV_CONFIG_SUBSET
 
 /*
- * "Minimalist" non-CDC option is a simple vendor-neutral model that most
+ * "Simple" CDC-subset option is a simple vendor-neutral model that most
  * full speed controllers can handle:  one interface, two bulk endpoints.
  */
 
 static const struct usb_interface_descriptor
-data_intf = {
-	.bLength =		sizeof data_intf,
+subset_data_intf = {
+	.bLength =		sizeof subset_data_intf,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
 	.bInterfaceNumber =	0,
@@ -594,47 +667,73 @@ data_intf = {
 	.iInterface =		STRING_DATA,
 };
 
-#endif	/* DEV_CONFIG_CDC */
+#endif	/* SUBSET */
 
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_OUT_NUM,
+	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-static const struct usb_descriptor_header *fs_function [] = {
+static const struct usb_descriptor_header *fs_eth_function [10] = {
 #ifdef DEV_CONFIG_CDC
 	/* "cdc" mode descriptors */
 	(struct usb_descriptor_header *) &control_intf,
 	(struct usb_descriptor_header *) &header_desc,
 	(struct usb_descriptor_header *) &union_desc,
 	(struct usb_descriptor_header *) &ether_desc,
-#ifdef	EP_STATUS_NUM
+	/* NOTE: status endpoint may need to be removed */
 	(struct usb_descriptor_header *) &fs_status_desc,
-#endif
+	/* data interface, with altsetting */
 	(struct usb_descriptor_header *) &data_nop_intf,
-#endif /* DEV_CONFIG_CDC */
-	/* minimalist core */
 	(struct usb_descriptor_header *) &data_intf,
 	(struct usb_descriptor_header *) &fs_source_desc,
 	(struct usb_descriptor_header *) &fs_sink_desc,
 	0,
+#endif /* DEV_CONFIG_CDC */
+};
+
+static inline void __init fs_subset_descriptors(void)
+{
+#ifdef DEV_CONFIG_SUBSET
+	fs_eth_function[0] = (struct usb_descriptor_header *) &subset_data_intf;
+	fs_eth_function[1] = (struct usb_descriptor_header *) &fs_source_desc;
+	fs_eth_function[2] = (struct usb_descriptor_header *) &fs_sink_desc;
+	fs_eth_function[3] = 0;
+#else
+	fs_eth_function[0] = 0;
+#endif
+}
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+static const struct usb_descriptor_header *fs_rndis_function [] = {
+	/* control interface matches ACM, not Ethernet */
+	(struct usb_descriptor_header *) &rndis_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &union_desc,
+	(struct usb_descriptor_header *) &fs_status_desc,
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &fs_source_desc,
+	(struct usb_descriptor_header *) &fs_sink_desc,
+	0,
 };
+#endif
 
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
 
@@ -643,39 +742,34 @@ static const struct usb_descriptor_heade
  * descriptors, unless they only run at full speed.
  */
 
-#ifdef	EP_STATUS_NUM
-static const struct usb_endpoint_descriptor
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+static struct usb_endpoint_descriptor
 hs_status_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_STATUS_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (STATUS_BYTECOUNT),
-	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 3,
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
 };
-#endif
+#endif /* DEV_CONFIG_CDC */
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-	.bInterval =		1,
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_OUT_NUM,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16 (512),
-	.bInterval =		1,
 };
 
 static struct usb_qualifier_descriptor
@@ -684,29 +778,57 @@ dev_qualifier = {
 	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
 
 	.bcdUSB =		__constant_cpu_to_le16 (0x0200),
-	.bDeviceClass =		DEV_CONFIG_CLASS,
+	.bDeviceClass =		USB_CLASS_COMM,
 
 	.bNumConfigurations =	1,
 };
 
-static const struct usb_descriptor_header *hs_function [] = {
+static const struct usb_descriptor_header *hs_eth_function [10] = {
 #ifdef DEV_CONFIG_CDC
 	/* "cdc" mode descriptors */
 	(struct usb_descriptor_header *) &control_intf,
 	(struct usb_descriptor_header *) &header_desc,
 	(struct usb_descriptor_header *) &union_desc,
 	(struct usb_descriptor_header *) &ether_desc,
-#ifdef	EP_STATUS_NUM
+	/* NOTE: status endpoint may need to be removed */
 	(struct usb_descriptor_header *) &hs_status_desc,
-#endif
+	/* data interface, with altsetting */
 	(struct usb_descriptor_header *) &data_nop_intf,
-#endif /* DEV_CONFIG_CDC */
-	/* minimalist core */
 	(struct usb_descriptor_header *) &data_intf,
 	(struct usb_descriptor_header *) &hs_source_desc,
 	(struct usb_descriptor_header *) &hs_sink_desc,
 	0,
+#endif /* DEV_CONFIG_CDC */
+};
+
+static inline void __init hs_subset_descriptors(void)
+{
+#ifdef DEV_CONFIG_SUBSET
+	hs_eth_function[0] = (struct usb_descriptor_header *) &subset_data_intf;
+	hs_eth_function[1] = (struct usb_descriptor_header *) &fs_source_desc;
+	hs_eth_function[2] = (struct usb_descriptor_header *) &fs_sink_desc;
+	hs_eth_function[3] = 0;
+#else
+	hs_eth_function[0] = 0;
+#endif
+}
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+static const struct usb_descriptor_header *hs_rndis_function [] = {
+	/* control interface matches ACM, not Ethernet */
+	(struct usb_descriptor_header *) &rndis_control_intf,
+	(struct usb_descriptor_header *) &header_desc,
+	(struct usb_descriptor_header *) &call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &acm_descriptor,
+	(struct usb_descriptor_header *) &union_desc,
+	(struct usb_descriptor_header *) &hs_status_desc,
+	/* data interface has no altsetting */
+	(struct usb_descriptor_header *) &rndis_data_intf,
+	(struct usb_descriptor_header *) &hs_source_desc,
+	(struct usb_descriptor_header *) &hs_sink_desc,
+	0,
 };
+#endif
 
 
 /* maxpacket and other transfer characteristics vary by speed. */
@@ -717,12 +839,19 @@ static const struct usb_descriptor_heade
 /* if there's no high speed support, maxpacket doesn't change. */
 #define ep_desc(g,hs,fs) fs
 
+static inline void __init hs_subset_descriptors(void)
+{
+}
+
 #endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
 /*-------------------------------------------------------------------------*/
 
 /* descriptors that are built on-demand */
 
+static char				manufacturer [40];
+static char				product_desc [40] = DRIVER_DESC;
+
 #ifdef	DEV_CONFIG_CDC
 /* address that the host will use ... usually assigned at random */
 static char				ethaddr [2 * ETH_ALEN + 1];
@@ -730,13 +859,21 @@ static char				ethaddr [2 * ETH_ALEN + 1
 
 /* static strings, in iso 8859/1 */
 static struct usb_string		strings [] = {
-	{ STRING_MANUFACTURER,	UTS_SYSNAME " " UTS_RELEASE "/" CHIP, },
-	{ STRING_PRODUCT,	driver_desc, },
+	{ STRING_MANUFACTURER,	manufacturer, },
+	{ STRING_PRODUCT,	product_desc, },
+	{ STRING_DATA,		"Ethernet Data", },
 #ifdef	DEV_CONFIG_CDC
+	{ STRING_CDC,		"CDC Ethernet", },
 	{ STRING_ETHADDR,	ethaddr, },
 	{ STRING_CONTROL,	"CDC Communications Control", },
 #endif
-	{ STRING_DATA,		"Ethernet Data", },
+#ifdef	DEV_CONFIG_SUBSET
+	{ STRING_SUBSET,	"CDC Ethernet Subset", },
+#endif
+#ifdef	CONFIG_USB_ETH_RNDIS
+	{ STRING_RNDIS,		"RNDIS", },
+	{ STRING_RNDIS_CONTROL,	"RNDIS Communications Control", },
+#endif
 	{  }		/* end of list */
 };
 
@@ -753,20 +890,34 @@ static int
 config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
 {
 	int				len;
-	const struct usb_descriptor_header **function = fs_function;
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 	int				hs = (speed == USB_SPEED_HIGH);
 
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
 		hs = !hs;
-	if (hs)
-		function = hs_function;
+#define which_config(t)	(hs ? & t ## _config   : & t ## _config)
+#define which_fn(t)	(hs ? & hs_ ## t ## _function : & fs_ ## t ## _function)
+#else
+#define	which_config(t)	(& t ## _config)
+#define	which_fn(t)	(& fs_ ## t ## _function)
 #endif
 
-	/* a single configuration must always be index 0 */
-	if (index > 0)
+	if (index >= device_desc.bNumConfigurations)
 		return -EINVAL;
-	len = usb_gadget_config_buf (&eth_config, buf, USB_BUFSIZ, function);
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+	/* list the RNDIS config first, to make Microsoft's drivers
+	 * happy. DOCSIS 1.0 needs this too.
+	 */
+	if (device_desc.bNumConfigurations == 2 && index == 0)
+		len = usb_gadget_config_buf (which_config (rndis), buf,
+			USB_BUFSIZ, (const struct usb_descriptor_header **)
+				which_fn (rndis));
+	else
+#endif
+		len = usb_gadget_config_buf (which_config (eth), buf,
+			USB_BUFSIZ, (const struct usb_descriptor_header **)
+				which_fn (eth));
 	if (len < 0)
 		return len;
 	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
@@ -778,6 +929,91 @@ config_buf (enum usb_device_speed speed,
 static void eth_start (struct eth_dev *dev, int gfp_flags);
 static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags);
 
+#ifdef	DEV_CONFIG_CDC
+static inline int ether_alt_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
+{
+	const struct usb_endpoint_descriptor	*d;
+
+	/* With CDC,  the host isn't allowed to use these two data
+	 * endpoints in the default altsetting for the interface.
+	 * so we don't activate them yet.  Reset from SET_INTERFACE.
+	 *
+	 * Strictly speaking RNDIS should work the same: activation is
+	 * a side effect of setting a packet filter.  Deactivation is
+	 * from REMOTE_NDIS_HALT_MSG, reset from REMOTE_NDIS_RESET_MSG.
+	 */
+
+	/* one endpoint writes data back IN to the host */
+	if (strcmp (ep->name, EP_IN_NAME) == 0) {
+		d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
+		ep->driver_data = dev;
+		dev->in_ep = ep;
+		dev->in = d;
+
+	/* one endpoint just reads OUT packets */
+	} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
+		d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
+		ep->driver_data = dev;
+		dev->out_ep = ep;
+		dev->out = d;
+
+	/* optional status/notification endpoint */
+	} else if (EP_STATUS_NAME &&
+			strcmp (ep->name, EP_STATUS_NAME) == 0) {
+		int			result;
+
+		d = ep_desc (dev->gadget, &hs_status_desc, &fs_status_desc);
+		result = usb_ep_enable (ep, d);
+		if (result < 0)
+			return result;
+
+		ep->driver_data = dev;
+		dev->status_ep = ep;
+		dev->status = d;
+	}
+	return 0;
+}
+#endif
+
+#if	defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
+static inline int ether_ep_setup (struct eth_dev *dev, struct usb_ep *ep)
+{
+	int					result;
+	const struct usb_endpoint_descriptor	*d;
+
+	/* CDC subset is simpler:  if the device is there,
+	 * it's live with rx and tx endpoints.
+	 *
+	 * Do this as a shortcut for RNDIS too.
+	 */
+
+	/* one endpoint writes data back IN to the host */
+	if (strcmp (ep->name, EP_IN_NAME) == 0) {
+		d = ep_desc (dev->gadget, &hs_source_desc, &fs_source_desc);
+		result = usb_ep_enable (ep, d);
+		if (result < 0)
+			return result;
+
+		ep->driver_data = dev;
+		dev->in_ep = ep;
+		dev->in = d;
+
+	/* one endpoint just reads OUT packets */
+	} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
+		d = ep_desc (dev->gadget, &hs_sink_desc, &fs_sink_desc);
+		result = usb_ep_enable (ep, d);
+		if (result < 0)
+			return result;
+
+		ep->driver_data = dev;
+		dev->out_ep = ep;
+		dev->out = d;
+	}
+
+	return 0;
+}
+#endif
+
 static int
 set_ether_config (struct eth_dev *dev, int gfp_flags)
 {
@@ -786,34 +1022,17 @@ set_ether_config (struct eth_dev *dev, i
 	struct usb_gadget	*gadget = dev->gadget;
 
 	gadget_for_each_ep (ep, gadget) {
-		const struct usb_endpoint_descriptor	*d;
-
 #ifdef	DEV_CONFIG_CDC
-		/* With CDC,  the host isn't allowed to use these two data
-		 * endpoints in the default altsetting for the interface.
-		 * so we don't activate them yet.
-		 */
+		if (!dev->rndis && dev->cdc) {
+			result = ether_alt_ep_setup (dev, ep);
+			if (result == 0)
+				continue;
+		}
+#endif
 
-		/* one endpoint writes data back IN to the host */
-		if (strcmp (ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
-			ep->driver_data = dev;
-			dev->in_ep = ep;
-			dev->in = d;
-			continue;
-
-		/* one endpoint just reads OUT packets */
-		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
-			ep->driver_data = dev;
-			dev->out_ep = ep;
-			dev->out = d;
-			continue;
-		}
-
-#ifdef	EP_STATUS_NUM
-		/* optional status/notification endpoint */
-		else if (strcmp (ep->name, EP_STATUS_NAME) == 0) {
+#ifdef	CONFIG_USB_ETH_RNDIS
+		if (dev->rndis && strcmp (ep->name, EP_STATUS_NAME) == 0) {
+			const struct usb_endpoint_descriptor	*d;
 			d = ep_desc (gadget, &hs_status_desc, &fs_status_desc);
 			result = usb_ep_enable (ep, d);
 			if (result == 0) {
@@ -822,43 +1041,17 @@ set_ether_config (struct eth_dev *dev, i
 				dev->status = d;
 				continue;
 			}
-		}
+		} else
 #endif
 
-#else	/* !CONFIG_CDC_ETHER */
-
-		/* non-CDC is simpler:  if the device is there,
-		 * it's live with rx and tx endpoints.
-		 */
-		/* one endpoint writes data back IN to the host */
-		if (strcmp (ep->name, EP_IN_NAME) == 0) {
-			d = ep_desc (gadget, &hs_source_desc, &fs_source_desc);
-			result = usb_ep_enable (ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->in_ep = ep;
-				dev->in = d;
+		{
+#if	defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
+			result = ether_ep_setup (dev, ep);
+			if (result == 0)
 				continue;
-			}
-
-		/* one endpoint just reads OUT packets */
-		} else if (strcmp (ep->name, EP_OUT_NAME) == 0) {
-			d = ep_desc (gadget, &hs_sink_desc, &fs_sink_desc);
-			result = usb_ep_enable (ep, d);
-			if (result == 0) {
-				ep->driver_data = dev;
-				dev->out_ep = ep;
-				dev->out = d;
-				continue;
-			}
+#endif
 		}
 
-#endif /* !CONFIG_CDC_ETHER */
-
-		/* ignore any other endpoints */
-		else
-			continue;
-
 		/* stop on error */
 		ERROR (dev, "can't enable %s, result %d\n", ep->name, result);
 		break;
@@ -869,23 +1062,41 @@ set_ether_config (struct eth_dev *dev, i
 	if (result == 0)
 		result = alloc_requests (dev, qlen (gadget), gfp_flags);
 
-#ifndef	DEV_CONFIG_CDC
-	if (result == 0) {
+	/* on error, disable any endpoints  */
+	if (result < 0) {
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+		if (dev->status_ep)
+			(void) usb_ep_disable (dev->status_ep);
+#endif
+		dev->status_ep = 0;
+		dev->status = 0;
+#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
+		if (dev->rndis || !dev->cdc) {
+			if (dev->in_ep)
+				(void) usb_ep_disable (dev->in_ep);
+			if (dev->out_ep)
+				(void) usb_ep_disable (dev->out_ep);
+		}
+#endif
+		dev->in_ep = 0;
+		dev->in = 0;
+		dev->out_ep = 0;
+		dev->out = 0;
+	} else
+
+	/* activate non-CDC configs right away
+	 * this isn't strictly according to the RNDIS spec
+	 */
+#if defined(DEV_CONFIG_SUBSET) || defined(CONFIG_USB_ETH_RNDIS)
+	if (dev->rndis || !dev->cdc) {
 		netif_carrier_on (dev->net);
 		if (netif_running (dev->net)) {
 			spin_unlock (&dev->lock);
 			eth_start (dev, GFP_ATOMIC);
 			spin_lock (&dev->lock);
 		}
-	} else {
-		(void) usb_ep_disable (dev->in_ep);
-		dev->in_ep = 0;
-		dev->in = 0;
-		(void) usb_ep_disable (dev->out_ep);
-		dev->out_ep = 0;
-		dev->out = 0;
 	}
-#endif /* !CONFIG_CDC_ETHER */
+#endif
 
 	if (result == 0)
 		DEBUG (dev, "qlen %d\n", qlen (gadget));
@@ -930,12 +1141,10 @@ static void eth_reset_config (struct eth
 		dev->out_ep = 0;
 	}
 
-#ifdef	EP_STATUS_NUM
 	if (dev->status_ep) {
 		usb_ep_disable (dev->status_ep);
 		dev->status_ep = 0;
 	}
-#endif
 	dev->config = 0;
 }
 
@@ -951,20 +1160,29 @@ eth_set_config (struct eth_dev *dev, uns
 	if (number == dev->config)
 		return 0;
 
-#ifdef CONFIG_USB_GADGET_SA1100
-	if (dev->config && atomic_read (&dev->tx_qlen) != 0) {
+	if (gadget_is_sa1100 (gadget)
+			&& dev->config
+			&& atomic_read (&dev->tx_qlen) != 0) {
 		/* tx fifo is full, but we can't clear it...*/
 		INFO (dev, "can't change configurations\n");
 		return -ESPIPE;
 	}
-#endif
 	eth_reset_config (dev);
-	hw_optimize (gadget);
+
+	/* default:  pass all packets, no multicast filtering */
+	dev->cdc_filter = 0x000f;
 
 	switch (number) {
 	case DEV_CONFIG_VALUE:
+		dev->rndis = 0;
+		result = set_ether_config (dev, gfp_flags);
+		break;
+#ifdef	CONFIG_USB_ETH_RNDIS
+	case DEV_RNDIS_CONFIG_VALUE:
+		dev->rndis = 1;
 		result = set_ether_config (dev, gfp_flags);
 		break;
+#endif
 	default:
 		result = -EINVAL;
 		/* FALL THROUGH */
@@ -986,21 +1204,29 @@ eth_set_config (struct eth_dev *dev, uns
 		}
 
 		dev->config = number;
-		INFO (dev, "%s speed config #%d: %s\n", speed, number,
-				driver_desc);
+		INFO (dev, "%s speed config #%d: %s, using %s\n",
+				speed, number, driver_desc,
+				dev->rndis
+					? "RNDIS"
+					: (dev->cdc
+						? "CDC Ethernet"
+						: "CDC Ethernet Subset"));
 	}
 	return result;
 }
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef	EP_STATUS_NUM
-
-/* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications */
+/* section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
+ * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
+ * and RNDIS also defines its own bit-incompatible notifications
+ */
 #define CDC_NOTIFY_NETWORK_CONNECTION	0x00	/* required; 6.3.1 */
 #define CDC_NOTIFY_RESPONSE_AVAILABLE	0x01	/* optional; 6.3.2 */
 #define CDC_NOTIFY_SPEED_CHANGE		0x2a	/* required; 6.3.8 */
 
+#ifdef	DEV_CONFIG_CDC
+
 struct cdc_notification {
 	u8	bmRequestType;
 	u8	bNotificationType;
@@ -1115,19 +1341,58 @@ static void eth_setup_complete (struct u
 
 /* see section 3.8.2 table 10 of the CDC spec for more ethernet
  * requests, mostly for filters (multicast, pm) and statistics
+ * section 3.6.2.1 table 4 has ACM requests; RNDIS requires the
+ * encapsulated command mechanism.
  */
-#define CDC_SEND_ENCAPSULATED_REQUEST	0x00	/* optional */
-#define CDC_GET_ENCAPSULATED_RESPONSE	0x01	/* optional */
-#define CDC_SET_ETHERNET_PACKET_FILTER	0x43	/* required */
+#define CDC_SEND_ENCAPSULATED_COMMAND		0x00	/* optional */
+#define CDC_GET_ENCAPSULATED_RESPONSE		0x01	/* optional */
+#define CDC_SET_ETHERNET_MULTICAST_FILTERS	0x40	/* optional */
+#define CDC_SET_ETHERNET_PM_PATTERN_FILTER	0x41	/* optional */
+#define CDC_GET_ETHERNET_PM_PATTERN_FILTER	0x42	/* optional */
+#define CDC_SET_ETHERNET_PACKET_FILTER		0x43	/* required */
+#define CDC_GET_ETHERNET_STATISTIC		0x44	/* optional */
+
+/* table 62; bits in cdc_filter */
+#define	CDC_PACKET_TYPE_PROMISCUOUS		(1 << 0)
+#define	CDC_PACKET_TYPE_ALL_MULTICAST		(1 << 1) /* no filter */
+#define	CDC_PACKET_TYPE_DIRECTED		(1 << 2)
+#define	CDC_PACKET_TYPE_BROADCAST		(1 << 3)
+#define	CDC_PACKET_TYPE_MULTICAST		(1 << 4) /* filtered */
+
+#ifdef CONFIG_USB_ETH_RNDIS
+
+static void rndis_response_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DEBUG (dev, "rndis response complete --> %d, %d/%d\n",
+		       req->status, req->actual, req->length);
+
+	/* done sending after CDC_GET_ENCAPSULATED_RESPONSE */
+}
+
+static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	struct eth_dev          *dev = ep->driver_data;
+	int			status;
+	
+	/* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
+	spin_lock(&dev->lock);
+	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
+	if (status < 0)
+		ERROR(dev, "%s: rndis parse error %d\n", __FUNCTION__, status);
+	spin_unlock(&dev->lock);
+}
+
+#endif	/* RNDIS */
 
 /*
  * The setup() callback implements all the ep0 functionality that's not
  * handled lower down.  CDC has a number of less-common features:
  *
  *  - two interfaces:  control, and ethernet data
- *  - data interface has two altsettings:  default, and active
+ *  - Ethernet data interface has two altsettings:  default, and active
  *  - class-specific descriptors for the control interface
- *  - a mandatory class-specific control request
+ *  - class-specific control requests
  */
 static int
 eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
@@ -1187,17 +1452,6 @@ eth_setup (struct usb_gadget *gadget, co
 		value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
 		spin_unlock (&dev->lock);
 		break;
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-	/* PXA UDC prevents us from using SET_INTERFACE in normal ways.
-	 * And it hides GET_CONFIGURATION and GET_INTERFACE too.
-	 */
-	case USB_REQ_SET_INTERFACE:
-		spin_lock (&dev->lock);
-		value = eth_set_config (dev, DEV_CONFIG_VALUE, GFP_ATOMIC);
-		spin_unlock (&dev->lock);
-		break;
-
-#else	/* hardware that that stays out of our way */
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			break;
@@ -1210,17 +1464,28 @@ eth_setup (struct usb_gadget *gadget, co
 				|| !dev->config
 				|| ctrl->wIndex > 1)
 			break;
+		if (!dev->cdc && ctrl->wIndex != 0)
+			break;
 		spin_lock (&dev->lock);
+
+		/* PXA hardware partially handles SET_INTERFACE;
+		 * we need to kluge around that interference.
+		 */
+		if (gadget_is_pxa (gadget)) {
+			value = eth_set_config (dev, DEV_CONFIG_VALUE,
+						GFP_ATOMIC);
+			goto done_set_intf;
+		}
+
+#ifdef DEV_CONFIG_CDC
 		switch (ctrl->wIndex) {
 		case 0:		/* control/master intf */
 			if (ctrl->wValue != 0)
 				break;
-#ifdef	EP_STATUS_NUM
 			if (dev->status_ep) {
 				usb_ep_disable (dev->status_ep);
 				usb_ep_enable (dev->status_ep, dev->status);
 			}
-#endif
 			value = 0;
 			break;
 		case 1:		/* data intf */
@@ -1237,9 +1502,8 @@ eth_setup (struct usb_gadget *gadget, co
 				usb_ep_enable (dev->in_ep, dev->in);
 				usb_ep_enable (dev->out_ep, dev->out);
 				netif_carrier_on (dev->net);
-#ifdef	EP_STATUS_NUM
-				issue_start_status (dev);
-#endif
+				if (dev->status_ep)
+					issue_start_status (dev);
 				if (netif_running (dev->net)) {
 					spin_unlock (&dev->lock);
 					eth_start (dev, GFP_ATOMIC);
@@ -1252,6 +1516,14 @@ eth_setup (struct usb_gadget *gadget, co
 			value = 0;
 			break;
 		}
+#else
+		/* FIXME this is wrong, as is the assumption that
+		 * all non-PXA hardware talks real CDC ...
+		 */
+		dev_warn (&gadget->dev, "set_interface ignored!\n");
+#endif /* DEV_CONFIG_CDC */
+
+done_set_intf:
 		spin_unlock (&dev->lock);
 		break;
 	case USB_REQ_GET_INTERFACE:
@@ -1259,15 +1531,16 @@ eth_setup (struct usb_gadget *gadget, co
 				|| !dev->config
 				|| ctrl->wIndex > 1)
 			break;
+		if (!(dev->cdc || dev->rndis) && ctrl->wIndex != 0)
+			break;
 
-		/* if carrier is on, data interface is active. */
-		*(u8 *)req->buf =
-			((ctrl->wIndex == 1) && netif_carrier_ok (dev->net))
-				? 1
-				: 0,
+		/* for CDC, iff carrier is on, data interface is active. */
+		if (dev->rndis || ctrl->wIndex != 1)
+			*(u8 *)req->buf = 0;
+		else
+			*(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
 		value = min (ctrl->wLength, (u16) 1);
 		break;
-#endif
 
 #ifdef DEV_CONFIG_CDC
 	case CDC_SET_ETHERNET_PACKET_FILTER:
@@ -1275,17 +1548,62 @@ eth_setup (struct usb_gadget *gadget, co
 		 * wValue = packet filter bitmap
 		 */
 		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
+				|| !dev->cdc
+				|| dev->rndis
 				|| ctrl->wLength != 0
 				|| ctrl->wIndex > 1)
+			break;
 		DEBUG (dev, "NOP packet filter %04x\n", ctrl->wValue);
 		/* NOTE: table 62 has 5 filter bits to reduce traffic,
 		 * and we "must" support multicast and promiscuous.
-		 * this NOP implements a bad filter...
+		 * this NOP implements a bad filter (always promisc)
 		 */
+		dev->cdc_filter = ctrl->wValue;
 		value = 0;
 		break;
 #endif /* DEV_CONFIG_CDC */
 
+#ifdef CONFIG_USB_ETH_RNDIS		
+	/* RNDIS uses the CDC command encapsulation mechanism to implement
+	 * an RPC scheme, with much getting/setting of attributes by OID.
+	 */
+	case CDC_SEND_ENCAPSULATED_COMMAND:
+		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
+				|| !dev->rndis
+				|| ctrl->wLength > USB_BUFSIZ
+				|| ctrl->wValue
+				|| rndis_control_intf.bInterfaceNumber
+					!= ctrl->wIndex)
+			break;
+		/* read the request, then process it */
+		value = ctrl->wLength;
+		req->complete = rndis_command_complete;
+		/* later, rndis_control_ack () sends a notification */
+		break;
+		
+	case CDC_GET_ENCAPSULATED_RESPONSE:
+		if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
+					== ctrl->bRequestType
+				&& dev->rndis
+				// && ctrl->wLength >= 0x0400
+				&& !ctrl->wValue
+				&& rndis_control_intf.bInterfaceNumber
+					== ctrl->wIndex) {
+			u8 *buf;
+
+			/* return the result */
+			buf = rndis_get_next_response (dev->rndis_config,
+						       &value);
+			if (buf) {
+				memcpy (req->buf, buf, value);
+				req->complete = rndis_response_complete;
+				rndis_free_response(dev->rndis_config, buf);
+			}
+			/* else stalls ... spec says to avoid that */
+		}
+		break;
+#endif	/* RNDIS */
+
 	default:
 		VDEBUG (dev,
 			"unknown control req%02x.%02x v%04x i%04x l%d\n",
@@ -1320,6 +1638,8 @@ eth_disconnect (struct usb_gadget *gadge
 	eth_reset_config (dev);
 	spin_unlock_irqrestore (&dev->lock, flags);
 
+	/* FIXME RNDIS should enter RNDIS_UNINITIALIZED */
+
 	/* next we may get setup() calls to enumerate new connections;
 	 * or an unbind() during shutdown (including removing module).
 	 */
@@ -1333,7 +1653,9 @@ static int eth_change_mtu (struct net_de
 {
 	struct eth_dev	*dev = (struct eth_dev *) net->priv;
 
-	if (new_mtu <= MIN_PACKET || new_mtu > MAX_PACKET)
+	// FIXME if rndis, don't change while link's live
+
+	if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
 		return -ERANGE;
 	/* no zero-length packet read wanted after mtu-sized packets */
 	if (((new_mtu + sizeof (struct ethhdr)) % dev->in_ep->maxpacket) == 0)
@@ -1347,12 +1669,12 @@ static struct net_device_stats *eth_get_
 	return &((struct eth_dev *) net->priv)->stats;
 }
 
-static int eth_ethtool_ioctl (struct net_device *net, void *useraddr)
+static int eth_ethtool_ioctl (struct net_device *net, void __user *useraddr)
 {
 	struct eth_dev	*dev = (struct eth_dev *) net->priv;
 	u32		cmd;
 
-	if (get_user (cmd, (u32 *)useraddr))
+	if (get_user (cmd, (u32 __user *)useraddr))
 		return -EFAULT;
 	switch (cmd) {
 
@@ -1363,7 +1685,8 @@ static int eth_ethtool_ioctl (struct net
 		info.cmd = ETHTOOL_GDRVINFO;
 		strncpy (info.driver, shortname, sizeof info.driver);
 		strncpy (info.version, DRIVER_VERSION, sizeof info.version);
-		strncpy (info.fw_version, CHIP, sizeof info.fw_version);
+		strncpy (info.fw_version, dev->gadget->name,
+			sizeof info.fw_version);
 		strncpy (info.bus_info, dev->gadget->dev.bus_id,
 			sizeof info.bus_info);
 		if (copy_to_user (useraddr, &info, sizeof (info)))
@@ -1389,7 +1712,7 @@ static int eth_ioctl (struct net_device 
 {
 	switch (cmd) {
 	case SIOCETHTOOL:
-		return eth_ethtool_ioctl (net, (void *)rq->ifr_data);
+		return eth_ethtool_ioctl(net, rq->ifr_data);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -1414,7 +1737,27 @@ rx_submit (struct eth_dev *dev, struct u
 	int			retval = -ENOMEM;
 	size_t			size;
 
+	/* Padding up to RX_EXTRA handles minor disagreements with host.
+	 * Normally we use the USB "terminate on short read" convention;
+	 * so allow up to (N*maxpacket)-1, since that memory is normally
+	 * already allocated.  Major loss of synch means -EOVERFLOW; any
+	 * obviously corrupted packets will automatically be discarded. 
+	 *
+	 * RNDIS uses internal framing, and explicitly allows senders to
+	 * pad to end-of-packet.  That's potentially nice for speed,
+	 * but means receivers can't recover synch on their own.
+	 */
 	size = (sizeof (struct ethhdr) + dev->net->mtu + RX_EXTRA);
+	size += dev->out_ep->maxpacket - 1;
+#ifdef CONFIG_USB_ETH_RNDIS
+	if (dev->rndis)
+		size += sizeof (struct rndis_packet_msg_type);
+#endif	
+	size -= size % dev->out_ep->maxpacket;
+#ifdef CONFIG_USB_ETH_RNDIS
+	if (!dev->rndis)
+#endif	
+		size--;
 
 	if ((skb = alloc_skb (size, gfp_flags)) == 0) {
 		DEBUG (dev, "no rx skb\n");
@@ -1451,8 +1794,12 @@ static void rx_complete (struct usb_ep *
 	/* normal completion */
 	case 0:
 		skb_put (skb, req->actual);
-		if (MIN_PACKET > skb->len
-				|| skb->len > (MAX_PACKET + ETH_HLEN)) {
+#ifdef CONFIG_USB_ETH_RNDIS
+		/* we know MaxPacketsPerTransfer == 1 here */
+		if (dev->rndis)
+			rndis_rm_hdr (req->buf, &(skb->len));
+#endif
+		if (ETH_HLEN > skb->len || skb->len > ETH_FRAME_LEN) {
 			dev->stats.rx_errors++;
 			dev->stats.rx_length_errors++;
 			DEBUG (dev, "rx length %d\n", skb->len);
@@ -1640,6 +1987,11 @@ static int eth_start_xmit (struct sk_buf
 	struct usb_request	*req = 0;
 	unsigned long		flags;
 
+	/* FIXME check dev->cdc_filter to decide whether to send this,
+	 * instead of acting as if CDC_PACKET_TYPE_PROMISCUOUS were
+	 * always set.  RNDIS has the same kind of outgoing filter.
+	 */
+
 	spin_lock_irqsave (&dev->lock, flags);
 	req = container_of (dev->tx_reqs.next, struct usb_request, list);
 	list_del (&req->list);
@@ -1649,21 +2001,35 @@ static int eth_start_xmit (struct sk_buf
 
 	/* no buffer copies needed, unless the network stack did it
 	 * or the hardware can't use skb buffers.
+	 * or there's not enough space for any RNDIS headers we need
 	 */
+#ifdef CONFIG_USB_ETH_RNDIS
+	if (dev->rndis) {
+		struct sk_buff	*skb_rndis;
+
+		skb_rndis = skb_realloc_headroom (skb,
+				sizeof (struct rndis_packet_msg_type));
+		if (!skb_rndis)
+			goto drop;
+	
+		dev_kfree_skb_any (skb);
+		skb = skb_rndis;
+		rndis_add_hdr (skb);
+		length = skb->len;
+	}
+#endif
 	req->buf = skb->data;
 	req->context = skb;
 	req->complete = tx_complete;
 
-#ifdef	CONFIG_USB_GADGET_SA1100
-	/* don't demand zlp (req->zero) support from all hardware */
-	if ((length % dev->in_ep->maxpacket) == 0)
-		length++;
-#else
 	/* use zlp framing on tx for strict CDC-Ether conformance,
 	 * though any robust network rx path ignores extra padding.
+	 * and some hardware doesn't like to write zlps.
 	 */
 	req->zero = 1;
-#endif
+	if (!dev->zlp && (length % dev->in_ep->maxpacket) == 0)
+		length++;
+
 	req->length = length;
 
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
@@ -1684,6 +2050,9 @@ static int eth_start_xmit (struct sk_buf
 	}
 
 	if (retval) {
+#ifdef CONFIG_USB_ETH_RNDIS
+drop:
+#endif
 		dev->stats.tx_dropped++;
 		dev_kfree_skb_any (skb);
 		spin_lock_irqsave (&dev->lock, flags);
@@ -1695,6 +2064,81 @@ static int eth_start_xmit (struct sk_buf
 	return 0;
 }
 
+/*-------------------------------------------------------------------------*/
+
+#ifdef CONFIG_USB_ETH_RNDIS
+
+static void rndis_send_media_state (struct eth_dev *dev, int connect)
+{
+	if (!dev)
+		return;
+	
+	if (connect) {
+		if (rndis_signal_connect (dev->rndis_config))
+			return;
+	} else {
+		if (rndis_signal_disconnect (dev->rndis_config))
+			return;
+	}
+}
+
+static void rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
+{
+	if (req->status || req->actual != req->length)
+		DEBUG (dev, "rndis control ack complete --> %d, %d/%d\n",
+		       req->status, req->actual, req->length);
+
+	usb_ep_free_buffer(ep, req->buf, req->dma, 8);
+	usb_ep_free_request(ep, req);
+}
+
+static int rndis_control_ack (struct net_device *net)
+{
+	struct eth_dev          *dev = (struct eth_dev *) net->priv;
+	u32                     length;
+	struct usb_request      *resp;
+	
+	/* in case RNDIS calls this after disconnect */
+	if (!dev->status_ep) {
+		DEBUG (dev, "status ENODEV\n");
+		return -ENODEV;
+	}
+
+	/* Allocate memory for notification ie. ACK */
+	resp = usb_ep_alloc_request (dev->status_ep, GFP_ATOMIC);
+	if (!resp) {
+		DEBUG (dev, "status ENOMEM\n");
+		return -ENOMEM;
+	}
+	
+	resp->buf = usb_ep_alloc_buffer (dev->status_ep, 8,
+					 &resp->dma, GFP_ATOMIC);
+	if (!resp->buf) {
+		DEBUG (dev, "status buf ENOMEM\n");
+		usb_ep_free_request (dev->status_ep, resp);
+		return -ENOMEM;
+	}
+	
+	/* Send RNDIS RESPONSE_AVAILABLE notification;
+	 * CDC_NOTIFY_RESPONSE_AVAILABLE should work too
+	 */
+	resp->length = 8;
+	resp->complete = rndis_control_ack_complete;
+	
+	*((u32 *) resp->buf) = __constant_cpu_to_le32 (1);
+	*((u32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
+	
+	length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
+	if (length < 0) {
+		resp->status = 0;
+		rndis_control_ack_complete (dev->status_ep, resp);
+	}
+	
+	return 0;
+}
+
+#endif	/* RNDIS */
+
 static void eth_start (struct eth_dev *dev, int gfp_flags)
 {
 	DEBUG (dev, "%s\n", __FUNCTION__);
@@ -1705,6 +2149,14 @@ static void eth_start (struct eth_dev *d
 	/* and open the tx floodgates */ 
 	atomic_set (&dev->tx_qlen, 0);
 	netif_wake_queue (dev->net);
+#ifdef CONFIG_USB_ETH_RNDIS
+	if (dev->rndis) {
+		rndis_set_param_medium (dev->rndis_config,
+					NDIS_MEDIUM_802_3,
+					BITRATE(dev->gadget));
+		rndis_send_media_state (dev, 1);
+	}
+#endif	
 }
 
 static int eth_open (struct net_device *net)
@@ -1739,11 +2191,19 @@ static int eth_stop (struct net_device *
 			usb_ep_enable (dev->in_ep, dev->in);
 			usb_ep_enable (dev->out_ep, dev->out);
 		}
-#ifdef	EP_STATUS_NUM
-		usb_ep_disable (dev->status_ep);
-		usb_ep_enable (dev->status_ep, dev->status);
-#endif
+		if (dev->status_ep) {
+			usb_ep_disable (dev->status_ep);
+			usb_ep_enable (dev->status_ep, dev->status);
+		}
+	}
+	
+#ifdef	CONFIG_USB_ETH_RNDIS
+	if (dev->rndis) {
+		rndis_set_param_medium (dev->rndis_config,
+					NDIS_MEDIUM_802_3, 0);
+		rndis_send_media_state (dev, 0);
 	}
+#endif
 
 	return 0;
 }
@@ -1756,6 +2216,10 @@ eth_unbind (struct usb_gadget *gadget)
 	struct eth_dev		*dev = get_gadget_data (gadget);
 
 	DEBUG (dev, "unbind\n");
+#ifdef CONFIG_USB_ETH_RNDIS
+	rndis_deregister (dev->rndis_config);
+	rndis_exit ();
+#endif
 
 	/* we've already been disconnected ... no i/o is active */
 	if (dev->req) {
@@ -1767,37 +2231,218 @@ eth_unbind (struct usb_gadget *gadget)
 	}
 
 	unregister_netdev (dev->net);
-	dev_put (dev->net);
+	free_netdev(dev->net);
 
 	/* assuming we used keventd, it must quiesce too */
 	flush_scheduled_work ();
 	set_gadget_data (gadget, 0);
 }
 
-static int
+static u8 __init nibble (unsigned char c)
+{
+	if (likely (isdigit (c)))
+		return c - '0';
+	c = toupper (c);
+	if (likely (isxdigit (c)))
+		return 10 + c - 'A';
+	return 0;
+}
+
+static void __init get_ether_addr (const char *str, u8 *dev_addr)
+{
+	if (str) {
+		unsigned	i;
+
+		for (i = 0; i < 6; i++) {
+			unsigned char num;
+
+			if((*str == '.') || (*str == ':'))
+				str++;
+			num = nibble(*str++) << 4;
+			num |= (nibble(*str++));
+			dev_addr [i] = num;
+		}
+		if (is_valid_ether_addr (dev_addr))
+			return;
+	}
+	random_ether_addr(dev_addr);
+}
+
+static int __init
 eth_bind (struct usb_gadget *gadget)
 {
 	struct eth_dev		*dev;
 	struct net_device	*net;
+	u8			cdc = 1, zlp = 1, rndis = 1;
+	struct usb_ep		*ep;
 	int			status = -ENOMEM;
-#ifdef	DEV_CONFIG_CDC
-	u8			node_id [ETH_ALEN];
 
-	/* just one upstream link at a time */
-	if (ethaddr [0] != 0)
+	/* these flags are only ever cleared; compiler take note */
+#ifndef	DEV_CONFIG_CDC
+	cdc = 0;
+#endif
+#ifndef	CONFIG_USB_ETH_RNDIS
+	rndis = 0;
+#endif
+
+	/* Because most host side USB stacks handle CDC Ethernet, that
+	 * standard protocol is _strongly_ preferred for interop purposes.
+	 * (By everyone except Microsoft.)
+	 */
+	if (gadget_is_net2280 (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
+	} else if (gadget_is_dummy (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0202);
+	} else if (gadget_is_pxa (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
+		/* pxa doesn't support altsettings */
+		cdc = 0;
+	} else if (gadget_is_sh(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
+		/* sh doesn't support multiple interfaces or configs */
+		cdc = 0;
+		rndis = 0;
+	} else if (gadget_is_sa1100 (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
+		/* hardware can't write zlps */
+		zlp = 0;
+		/* sa1100 CAN do CDC, without status endpoint ... we use
+		 * non-CDC to be compatible with ARM Linux-2.4 "usb-eth".
+		 */
+		cdc = 0;
+	} else if (gadget_is_goku (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
+	} else if (gadget_is_mq11xx (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
+	} else if (gadget_is_omap (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
+	} else {
+		/* can't assume CDC works.  don't want to default to
+		 * anything less functional on CDC-capable hardware,
+		 * so we fail in this case.
+		 */
+		printk (KERN_ERR "%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		return -ENODEV;
+	}
+	snprintf (manufacturer, sizeof manufacturer,
+		UTS_SYSNAME " " UTS_RELEASE "/%s",
+		gadget->name);
+
+	/* If there's an RNDIS configuration, that's what Windows wants to
+	 * be using ... so use these product IDs here and in the "linux.inf"
+	 * needed to install MSFT drivers.  Current Linux kernels will use
+	 * the second configuration if it's CDC Ethernet, and need some help
+	 * to choose the right configuration otherwise.
+	 */
+	if (rndis) {
+		device_desc.idVendor =
+			__constant_cpu_to_le16(RNDIS_VENDOR_NUM);
+		device_desc.idProduct =
+			__constant_cpu_to_le16(RNDIS_PRODUCT_NUM);
+		snprintf (product_desc, sizeof product_desc,
+			"RNDIS/%s", driver_desc);
+
+	/* CDC subset ... recognized by Linux since 2.4.10, but Windows
+	 * drivers aren't widely available.
+	 */
+	} else if (!cdc) {
+		device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+		device_desc.idVendor =
+			__constant_cpu_to_le16(SIMPLE_VENDOR_NUM);
+		device_desc.idProduct =
+			__constant_cpu_to_le16(SIMPLE_PRODUCT_NUM);
+	}
+
+
+	/* support optional vendor/distro customization */
+	if (idVendor) {
+		if (!idProduct) {
+			printk (KERN_ERR "%s: idVendor needs idProduct!\n",
+				shortname);
+			return -ENODEV;
+		}
+		device_desc.idVendor = cpu_to_le16(idVendor);
+		device_desc.idProduct = cpu_to_le16(idProduct);
+		if (bcdDevice)
+			device_desc.bcdDevice = cpu_to_le16(bcdDevice);
+	}
+	if (iManufacturer)
+		strncpy (manufacturer, iManufacturer, sizeof manufacturer);
+	if (iProduct)
+		strncpy (product_desc, iProduct, sizeof product_desc);
+
+	/* all we really need is bulk IN/OUT */
+	usb_ep_autoconfig_reset (gadget);
+	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+	if (!ep) {
+autoconf_fail:
+		printk (KERN_ERR "%s: can't autoconfigure on %s\n",
+			shortname, gadget->name);
 		return -ENODEV;
+	}
+	EP_IN_NAME = ep->name;
+	ep->driver_data = ep;	/* claim */
+	
+	ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_OUT_NAME = ep->name;
+	ep->driver_data = ep;	/* claim */
+
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+	/* CDC Ethernet control interface doesn't require a status endpoint.
+	 * Since some hosts expect one, try to allocate one anyway.
+	 */
+	if (cdc || rndis) {
+		ep = usb_ep_autoconfig (gadget, &fs_status_desc);
+		if (ep) {
+			EP_STATUS_NAME = ep->name;
+			ep->driver_data = ep;	/* claim */
+		} else if (rndis) {
+			printk (KERN_ERR "%s: can't run RNDIS on %s\n",
+				shortname, gadget->name);
+			return -ENODEV;
+		} else if (cdc) {
+			control_intf.bNumEndpoints = 0;
+			/* FIXME remove endpoint from descriptor list */
+		}
+	}
 #endif
 
-	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+	/* one config:  cdc, else minimal subset */
+	if (!cdc) {
+		eth_config.bNumInterfaces = 1;
+		eth_config.iConfiguration = STRING_SUBSET;
+		fs_subset_descriptors();
+		hs_subset_descriptors();
+	}
+
+	/* For now RNDIS is always a second config */
+	if (rndis)
+		device_desc.bNumConfigurations = 2;
+
 #ifdef	CONFIG_USB_GADGET_DUALSPEED
+	if (rndis)
+		dev_qualifier.bNumConfigurations = 2;
+	else if (!cdc)
+		dev_qualifier.bDeviceClass = USB_CLASS_VENDOR_SPEC;
+
 	/* assumes ep0 uses the same value for both speeds ... */
 	dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
+
+	/* and that all endpoints are dual-speed */
+	hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
+	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
+#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+	if (EP_STATUS_NAME)
+		hs_status_desc.bEndpointAddress =
+				fs_status_desc.bEndpointAddress;
 #endif
+#endif	/* DUALSPEED */
 
-#ifdef	SELFPOWERED
-	eth_config.bmAttributes |= USB_CONFIG_ATT_SELFPOWERED;
+	device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 	usb_gadget_set_selfpowered (gadget);
-#endif
 
  	net = alloc_etherdev (sizeof *dev);
  	if (!net)
@@ -1812,25 +2457,32 @@ eth_bind (struct usb_gadget *gadget)
 	dev->net = net;
 	SET_MODULE_OWNER (net);
 	strcpy (net->name, "usb%d");
+	dev->cdc = cdc;
+	dev->zlp = zlp;
 
-	/* one random address for the gadget device ... both of these could
-	 * reasonably come from an id prom or a module parameter.
+	/* Module params for these addresses should come from ID proms.
+	 * The host side address is used with CDC and RNDIS, and commonly
+	 * ends up in a persistent config database.
 	 */
-	get_random_bytes (net->dev_addr, ETH_ALEN);
-	net->dev_addr [0] &= 0xfe;	// clear multicast bit
-	net->dev_addr [0] |= 0x02;	// set local assignment bit (IEEE802)
-
+	get_ether_addr(dev_addr, net->dev_addr);
+	if (cdc || rndis) {
+		get_ether_addr(host_addr, dev->host_mac);
 #ifdef	DEV_CONFIG_CDC
-	/* ... another address for the host, on the other end of the
-	 * link, gets exported through CDC (see CDC spec table 41)
-	 */
-	get_random_bytes (node_id, sizeof node_id);
-	node_id [0] &= 0xfe;	// clear multicast bit
-	node_id [0] |= 0x02;    // set local assignment bit (IEEE802)
-	snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
-		node_id [0], node_id [1], node_id [2],
-		node_id [3], node_id [4], node_id [5]);
+		snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
+			dev->host_mac [0], dev->host_mac [1],
+			dev->host_mac [2], dev->host_mac [3],
+			dev->host_mac [4], dev->host_mac [5]);
 #endif
+	}
+
+	if (rndis) {
+		status = rndis_init();
+		if (status < 0) {
+			printk (KERN_ERR "%s: can't init RNDIS, %d\n",
+				shortname, status);
+			goto fail;
+		}
+	}
 
 	net->change_mtu = eth_change_mtu;
 	net->get_stats = eth_get_stats;
@@ -1867,16 +2519,60 @@ eth_bind (struct usb_gadget *gadget)
 
  	// SET_NETDEV_DEV (dev->net, &gadget->dev);
  	status = register_netdev (dev->net);
- 	if (status == 0) {
+	if (status < 0)
+		goto fail1;
 
-		INFO (dev, "%s, " CHIP ", version: " DRIVER_VERSION "\n",
-				driver_desc);
-#ifdef	DEV_CONFIG_CDC
-		INFO (dev, "CDC host enet %s\n", ethaddr);
-#endif
- 		return status;
+	INFO (dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
+	INFO (dev, "using %s, OUT %s IN %s%s%s\n", gadget->name,
+		EP_OUT_NAME, EP_IN_NAME,
+		EP_STATUS_NAME ? " STATUS " : "",
+		EP_STATUS_NAME ? EP_STATUS_NAME : ""
+		);
+	INFO (dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+		net->dev_addr [0], net->dev_addr [1],
+		net->dev_addr [2], net->dev_addr [3],
+		net->dev_addr [4], net->dev_addr [5]);
+
+	if (cdc || rndis)
+		INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+			dev->host_mac [0], dev->host_mac [1],
+			dev->host_mac [2], dev->host_mac [3],
+			dev->host_mac [4], dev->host_mac [5]);
+
+#ifdef	CONFIG_USB_ETH_RNDIS
+	if (rndis) {
+		u32	vendorID = 0;
+
+		/* FIXME RNDIS vendor id == "vendor NIC code" == ? */
+		
+		dev->rndis_config = rndis_register (rndis_control_ack);
+		if (dev->rndis_config < 0) {
+fail0:
+			unregister_netdev (dev->net);
+			status = -ENODEV;
+			goto fail;
+		}
+		
+		/* these set up a lot of the OIDs that RNDIS needs */
+		rndis_set_host_mac (dev->rndis_config, dev->host_mac);
+		if (rndis_set_param_dev (dev->rndis_config, dev->net,
+					 &dev->stats))
+			goto fail0;
+		if (rndis_set_param_vendor (dev->rndis_config, vendorID,
+					    manufacturer))
+			goto fail0;
+		if (rndis_set_param_medium (dev->rndis_config,
+					    NDIS_MEDIUM_802_3,
+					    0))
+			goto fail0;
+		INFO (dev, "RNDIS ready\n");
 	}
-	pr_debug("%s: register_netdev failed, %d\n", shortname, status);
+#endif	
+
+	return status;
+
+fail1:
+	pr_debug ("%s: register_netdev failed, %d\n", shortname, status);
 fail:
 	eth_unbind (gadget);
 	return status;
@@ -1884,6 +2580,26 @@ fail:
 
 /*-------------------------------------------------------------------------*/
 
+static void
+eth_suspend (struct usb_gadget *gadget)
+{
+	struct eth_dev		*dev = get_gadget_data (gadget);
+
+	DEBUG (dev, "suspend\n");
+	dev->suspended = 1;
+}
+
+static void
+eth_resume (struct usb_gadget *gadget)
+{
+	struct eth_dev		*dev = get_gadget_data (gadget);
+
+	DEBUG (dev, "resume\n");
+	dev->suspended = 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_gadget_driver eth_driver = {
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
@@ -1897,6 +2613,9 @@ static struct usb_gadget_driver eth_driv
 	.setup		= eth_setup,
 	.disconnect	= eth_disconnect,
 
+	.suspend	= eth_suspend,
+	.resume		= eth_resume,
+
 	.driver 	= {
 		.name		= (char *) shortname,
 		// .shutdown = ...
@@ -1906,7 +2625,7 @@ static struct usb_gadget_driver eth_driv
 };
 
 MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_AUTHOR ("David Brownell");
+MODULE_AUTHOR ("David Brownell, Benedikt Spanger");
 MODULE_LICENSE ("GPL");
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/file_storage.c linux-2.4.27-rc4/drivers/usb/gadget/file_storage.c
--- linux-2.4.26/drivers/usb/gadget/file_storage.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/file_storage.c	2004-07-30 16:24:46.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * file_storage.c -- File-backed USB Storage Gadget, for USB development
  *
- * Copyright (C) 2003 Alan Stern
+ * Copyright (C) 2003, 2004 Alan Stern
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -229,12 +229,14 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include "gadget_chips.h"
+
 
 /*-------------------------------------------------------------------------*/
 
 #define DRIVER_DESC		"File-backed Storage Gadget"
 #define DRIVER_NAME		"g_file_storage"
-#define DRIVER_VERSION		"14 January 2004"
+#define DRIVER_VERSION		"05 June 2004"
 
 static const char longname[] = DRIVER_DESC;
 static const char shortname[] = DRIVER_NAME;
@@ -251,165 +253,11 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define DRIVER_PRODUCT_ID	0xa4a5	// Linux-USB File-backed Storage Gadget
 
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * Hardware-specific configuration, controlled by which device
- * controller driver was configured.
- *
- * CHIP ... hardware identifier
- * DRIVER_VERSION_NUM ... alerts the host side driver to differences
- * EP_*_NAME ... which endpoints do we use for which purpose?
- * EP_*_NUM ... numbers for them (often limited by hardware)
- * FS_BULK_IN_MAXPACKET ... maxpacket value for full-speed bulk-in ep
- * FS_BULK_OUT_MAXPACKET ... maxpacket value for full-speed bulk-out ep
- * HIGHSPEED ... define if ep0 and descriptors need high speed support
- * MAX_USB_POWER ... define if we use other than 100 mA bus current
- * SELFPOWER ... if we can run on bus power, zero
- * NO_BULK_STALL ... bulk endpoint halts don't work well so avoid them
- */
-
-
-/*
- * NetChip 2280, PCI based.
- *
- * This has half a dozen configurable endpoints, four with dedicated
- * DMA channels to manage their FIFOs.  It supports high speed.
- * Those endpoints can be arranged in any desired configuration.
- */
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP			"net2280"
-#define DRIVER_VERSION_NUM	0x0211
-static const char EP_BULK_IN_NAME[] = "ep-a";
-#define EP_BULK_IN_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep-b";
-#define EP_BULK_OUT_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep-e";
-#define EP_INTR_IN_NUM		5
-#define HIGHSPEED
-#endif
-
-
-/*
- * Dummy_hcd, software-based loopback controller.
- *
- * This imitates the abilities of the NetChip 2280, so we will use
- * the same configuration.
- */
-#ifdef	CONFIG_USB_GADGET_DUMMY
-#define CHIP			"dummy"
-#define DRIVER_VERSION_NUM	0x0212
-static const char EP_BULK_IN_NAME[] = "ep-a";
-#define EP_BULK_IN_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep-b";
-#define EP_BULK_OUT_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep-e";
-#define EP_INTR_IN_NUM		5
-#define HIGHSPEED
-#endif
-
-
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable PDAs.
- *
- * This has fifteen fixed-function full speed endpoints, and it
- * can support all USB transfer types.
- *
- * These supports three or four configurations, with fixed numbers.
- * The hardware interprets SET_INTERFACE, net effect is that you
- * can't use altsettings or reset the interfaces independently.
- * So stick to a single interface.
- */
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP			"pxa2xx"
-#define DRIVER_VERSION_NUM	0x0213
-static const char EP_BULK_IN_NAME[] = "ep1in-bulk";
-#define EP_BULK_IN_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep2out-bulk";
-#define EP_BULK_OUT_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep6in-bulk";
-#define EP_INTR_IN_NUM		6
-#endif
-
-
 /*
- * SuperH UDC:  UDC built-in to some Renesas SH processors.
- *
- * This has three fixed-function full speed bulk/interrupt endpoints.
- *
- * Only one configuration and interface is supported (SET_CONFIGURATION
- * and SET_INTERFACE are handled completely by the hardware).
- */
-#ifdef	CONFIG_USB_GADGET_SUPERH
-#define CHIP			"superh"
-#define DRIVER_VERSION_NUM	0x0215
-static const char EP_BULK_IN_NAME[] = "ep2in-bulk";
-#define EP_BULK_IN_NUM		2
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_OUT_NAME[] = "ep1out-bulk";
-#define EP_BULK_OUT_NUM		1
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME[] = "ep3in-bulk";
-#define EP_INTR_IN_NUM		3
-#define NO_BULK_STALL
-#endif
-
-
-/*
- * Toshiba TC86C001 ("Goku-S") UDC
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- */
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP			"goku"
-#define DRIVER_VERSION_NUM	0x0216
-static const char EP_BULK_OUT_NAME [] = "ep1-bulk";
-#define EP_BULK_OUT_NUM		1
-#define FS_BULK_IN_MAXPACKET	64
-static const char EP_BULK_IN_NAME [] = "ep2-bulk";
-#define EP_BULK_IN_NUM		2
-#define FS_BULK_OUT_MAXPACKET	64
-static const char EP_INTR_IN_NAME [] = "ep3-bulk";
-#define EP_INTR_IN_NUM		3
-#endif
-
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef CHIP
-#	error Configure some USB peripheral controller driver!
-#endif
-
-/* Power usage is config specific.
- * Hardware that supports remote wakeup defaults to disabling it.
+ * This driver assumes self-powered hardware and has no way for users to
+ * trigger remote wakeup.  It uses autoconfiguration to select endpoints
+ * and endpoint addresses.
  */
-#ifndef	SELFPOWER
-/* default: say we're self-powered */
-#define SELFPOWER USB_CONFIG_ATT_SELFPOWER
-/* else:
- * - SELFPOWER value must be zero
- * - MAX_USB_POWER may be nonzero.
- */
-#endif
-
-#ifndef	MAX_USB_POWER
-/* Any hub supports this steady state bus power consumption */
-#define MAX_USB_POWER	100	/* mA */
-#endif
-
-/* We don't support remote wake-up */
-
-#ifdef NO_BULK_STALL
-#define CAN_STALL	0
-#else
-#define CAN_STALL	1
-#endif
 
 
 /*-------------------------------------------------------------------------*/
@@ -478,14 +326,15 @@ static const char EP_INTR_IN_NAME [] = "
 static char		*file[MAX_LUNS] = {NULL, };
 static int		ro[MAX_LUNS] = {0, };
 static unsigned int	luns = 0;
+						// Default values
 static char 		*transport = "BBB";
 static char 		*protocol = "SCSI";
 static int 		removable = 0;
 static unsigned short	vendor = DRIVER_VENDOR_ID;
 static unsigned short	product = DRIVER_PRODUCT_ID;
-static unsigned short	release = DRIVER_VERSION_NUM;
+static unsigned short	release = 0xffff;	// Use controller chip type
 static unsigned int	buflen = 16384;
-static int		stall = CAN_STALL;
+static int		stall = 1;
 
 static struct {
 	unsigned int	nluns;
@@ -990,7 +839,7 @@ device_desc = {
 	/* The next three values can be overridden by module parameters */
 	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_ID),
 	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_ID),
-	.bcdDevice =		__constant_cpu_to_le16(DRIVER_VERSION_NUM),
+	.bcdDevice =		__constant_cpu_to_le16(0xffff),
 
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
@@ -1003,11 +852,11 @@ config_desc = {
 	.bLength =		sizeof config_desc,
 	.bDescriptorType =	USB_DT_CONFIG,
 
-	/* wTotalLength adjusted during bind() */
+	/* wTotalLength computed by usb_gadget_config_buf() */
 	.bNumInterfaces =	1,
 	.bConfigurationValue =	CONFIG_VALUE,
-	.bmAttributes =		USB_CONFIG_ATT_ONE | SELFPOWER,
-	.bMaxPower =		(MAX_USB_POWER + 1) / 2,
+	.bmAttributes =		USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower =		1,	// self-powered
 };
 
 /* There is only one interface. */
@@ -1017,47 +866,56 @@ intf_desc = {
 	.bLength =		sizeof intf_desc,
 	.bDescriptorType =	USB_DT_INTERFACE,
 
-	.bNumEndpoints =	2,		// Adjusted during bind()
+	.bNumEndpoints =	2,		// Adjusted during fsg_bind()
 	.bInterfaceClass =	USB_CLASS_MASS_STORAGE,
-	.bInterfaceSubClass =	USB_SC_SCSI,	// Adjusted during bind()
-	.bInterfaceProtocol =	USB_PR_BULK,	// Adjusted during bind()
+	.bInterfaceSubClass =	USB_SC_SCSI,	// Adjusted during fsg_bind()
+	.bInterfaceProtocol =	USB_PR_BULK,	// Adjusted during fsg_bind()
 };
 
 /* Three full-speed endpoint descriptors: bulk-in, bulk-out,
  * and interrupt-in. */
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_bulk_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_BULK_IN_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(FS_BULK_IN_MAXPACKET),
+	/* wMaxPacketSize set by autoconfiguration */
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_bulk_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_BULK_OUT_NUM,
+	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16(FS_BULK_OUT_MAXPACKET),
+	/* wMaxPacketSize set by autoconfiguration */
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_intr_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_INTR_IN_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	__constant_cpu_to_le16(2),
 	.bInterval =		32,	// frames -> 32 ms
 };
 
-#ifdef	HIGHSPEED
+static const struct usb_descriptor_header *fs_function[] = {
+	(struct usb_descriptor_header *) &intf_desc,
+	(struct usb_descriptor_header *) &fs_bulk_in_desc,
+	(struct usb_descriptor_header *) &fs_bulk_out_desc,
+	(struct usb_descriptor_header *) &fs_intr_in_desc,
+	NULL,
+};
+
+
+#ifdef	CONFIG_USB_GADGET_DUALSPEED
 
 /*
  * USB 2.0 devices need to expose both high speed and full speed
@@ -1067,47 +925,55 @@ fs_intr_in_desc = {
  * and a "device qualifier" ... plus more construction options
  * for the config descriptor.
  */
-static const struct usb_endpoint_descriptor
+static struct usb_qualifier_descriptor
+dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
+
+	.bNumConfigurations =	1,
+};
+
+static struct usb_endpoint_descriptor
 hs_bulk_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_BULK_IN_NUM | USB_DIR_IN,
+	/* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_bulk_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_BULK_OUT_NUM,
+	/* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 	.wMaxPacketSize =	__constant_cpu_to_le16(512),
 	.bInterval =		1,	// NAK every 1 uframe
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 hs_intr_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_INTR_IN_NUM | USB_DIR_IN,
+	/* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
 	.bmAttributes =		USB_ENDPOINT_XFER_INT,
 	.wMaxPacketSize =	__constant_cpu_to_le16(2),
 	.bInterval =		9,	// 2**(9-1) = 256 uframes -> 32 ms
 };
 
-static struct usb_qualifier_descriptor
-dev_qualifier = {
-	.bLength =		sizeof dev_qualifier,
-	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
-
-	.bcdUSB =		__constant_cpu_to_le16(0x0200),
-	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
-
-	.bNumConfigurations =	1,
+static const struct usb_descriptor_header *hs_function[] = {
+	(struct usb_descriptor_header *) &intf_desc,
+	(struct usb_descriptor_header *) &hs_bulk_in_desc,
+	(struct usb_descriptor_header *) &hs_bulk_out_desc,
+	(struct usb_descriptor_header *) &hs_intr_in_desc,
+	NULL,
 };
 
 /* Maxpacket and other transfer characteristics vary by speed. */
@@ -1115,22 +981,23 @@ dev_qualifier = {
 
 #else
 
-/* If there's no high speed support, maxpacket doesn't change. */
+/* If there's no high speed support, always use the full-speed descriptor. */
 #define ep_desc(g,fs,hs)	fs
 
-#endif	/* !HIGHSPEED */
+#endif	/* !CONFIG_USB_GADGET_DUALSPEED */
 
 
 /* The CBI specification limits the serial string to 12 uppercase hexadecimal
  * characters. */
+static char				manufacturer[40];
 static char				serial[13];
 
-/* Static strings, in ISO 8859/1 */
+/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
 static struct usb_string		strings[] = {
-	{ STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, },
-	{ STRING_PRODUCT, longname, },
-	{ STRING_SERIAL, serial, },
-	{ }			// end of list
+	{STRING_MANUFACTURER,	manufacturer},
+	{STRING_PRODUCT,	longname},
+	{STRING_SERIAL,		serial},
+	{}
 };
 
 static struct usb_gadget_strings	stringtab = {
@@ -1140,61 +1007,33 @@ static struct usb_gadget_strings	stringt
 
 
 /*
- * Config descriptors are handcrafted.  They must agree with the code
- * that sets configurations and with code managing interfaces and their
- * altsettings.  They must also handle different speeds and other-speed
- * requests.
+ * Config descriptors must agree with the code that sets configurations
+ * and with code managing interfaces and their altsettings.  They must
+ * also handle different speeds and other-speed requests.
  */
 static int populate_config_buf(enum usb_device_speed speed,
-		u8 *buf0, u8 type, unsigned index)
+		u8 *buf, u8 type, unsigned index)
 {
-	u8	*buf = buf0;
-#ifdef HIGHSPEED
-	int	hs;
-#endif
+	int					len;
+	const struct usb_descriptor_header	**function;
 
 	if (index > 0)
 		return -EINVAL;
-	if (config_desc.wTotalLength  > EP0_BUFSIZE)
-		return -EDOM;
 
-	/* Config (or other speed config) */
-	memcpy(buf, &config_desc, USB_DT_CONFIG_SIZE);
-	buf[1] = type;
-	buf += USB_DT_CONFIG_SIZE;
-
-	/* Interface */
-	memcpy(buf, &intf_desc, USB_DT_INTERFACE_SIZE);
-	buf += USB_DT_INTERFACE_SIZE;
-
-	/* The endpoints in the interface (at that speed) */
-#ifdef HIGHSPEED
-	hs = (speed == USB_SPEED_HIGH);
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	if (type == USB_DT_OTHER_SPEED_CONFIG)
-		hs = !hs;
-	if (hs) {
-		memcpy(buf, &hs_bulk_in_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy(buf, &hs_bulk_out_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		if (transport_is_cbi()) {
-			memcpy(buf, &hs_intr_in_desc, USB_DT_ENDPOINT_SIZE);
-			buf += USB_DT_ENDPOINT_SIZE;
-		}
-	} else
+		speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed;
+	if (speed == USB_SPEED_HIGH)
+		function = hs_function;
+	else
 #endif
-	{
-		memcpy(buf, &fs_bulk_in_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		memcpy(buf, &fs_bulk_out_desc, USB_DT_ENDPOINT_SIZE);
-		buf += USB_DT_ENDPOINT_SIZE;
-		if (transport_is_cbi()) {
-			memcpy(buf, &fs_intr_in_desc, USB_DT_ENDPOINT_SIZE);
-			buf += USB_DT_ENDPOINT_SIZE;
-		}
-	}
+		function = fs_function;
 
-	return buf - buf0;
+	len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function);
+	if (len < 0)
+		return len;
+	((struct usb_config_descriptor *) buf)->bDescriptorType = type;
+	return len;
 }
 
 
@@ -1493,22 +1332,26 @@ static int standard_setup_req(struct fsg
 			value = min(ctrl->wLength, (u16) sizeof device_desc);
 			memcpy(req->buf, &device_desc, value);
 			break;
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
 			VDBG(fsg, "get device qualifier\n");
+			if (!fsg->gadget->is_dualspeed)
+				break;
 			value = min(ctrl->wLength, (u16) sizeof dev_qualifier);
 			memcpy(req->buf, &dev_qualifier, value);
 			break;
 
 		case USB_DT_OTHER_SPEED_CONFIG:
 			VDBG(fsg, "get other-speed config descriptor\n");
+			if (!fsg->gadget->is_dualspeed)
+				break;
 			goto get_config;
-#endif /* HIGHSPEED */
+#endif
 		case USB_DT_CONFIG:
 			VDBG(fsg, "get configuration descriptor\n");
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 		get_config:
-#endif /* HIGHSPEED */
+#endif
 			value = populate_config_buf(fsg->gadget->speed,
 					req->buf,
 					ctrl->wValue >> 8,
@@ -2148,7 +1991,7 @@ static int do_inquiry(struct fsg_dev *fs
 	buf[4] = 31;		// Additional length
 				// No special options
 	sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, product_id,
-			DRIVER_VERSION_NUM);
+			mod_data.release);
 	return 36;
 }
 
@@ -2196,7 +2039,7 @@ static int do_request_sense(struct fsg_d
 	buf[0] = 0x80 | 0x70;			// Valid, current error
 	buf[2] = SK(sd);
 	put_be32(&buf[3], sdinfo);		// Sense information
-	buf[7] = 18 - 7;			// Additional sense length
+	buf[7] = 18 - 8;			// Additional sense length
 	buf[12] = ASC(sd);
 	buf[13] = ASCQ(sd);
 	return 18;
@@ -2643,7 +2486,7 @@ static int send_status(struct fsg_dev *f
 		/* Store and send the Bulk-only CSW */
 		csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG);
 		csw->Tag = fsg->tag;
-		csw->Residue = fsg->residue;
+		csw->Residue = cpu_to_le32(fsg->residue);
 		csw->Status = status;
 
 		bh->inreq->length = USB_BULK_CS_WRAP_LEN;
@@ -3089,7 +2932,7 @@ static int received_cbw(struct fsg_dev *
 		fsg->data_dir = DATA_DIR_TO_HOST;
 	else
 		fsg->data_dir = DATA_DIR_FROM_HOST;
-	fsg->data_size = cbw->DataTransferLength;
+	fsg->data_size = le32_to_cpu(cbw->DataTransferLength);
 	if (fsg->data_size == 0)
 		fsg->data_dir = DATA_DIR_NONE;
 	fsg->lun = cbw->Lun;
@@ -3242,6 +3085,7 @@ reset:
 	if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
 		goto reset;
 	fsg->bulk_out_enabled = 1;
+	fsg->bulk_out_maxpacket = d->wMaxPacketSize;
 
 	if (transport_is_cbi()) {
 		d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
@@ -3717,6 +3561,34 @@ static int __init check_parameters(struc
 	mod_data.protocol_type = USB_SC_SCSI;
 	mod_data.protocol_name = "Transparent SCSI";
 
+	if (gadget_is_sh(fsg->gadget))
+		mod_data.can_stall = 0;
+
+	if (mod_data.release == 0xffff) {	// Parameter wasn't set
+		if (gadget_is_net2280(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0221);
+		else if (gadget_is_dummy(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0222);
+		else if (gadget_is_pxa(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0223);
+		else if (gadget_is_sh(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0224);
+
+		/* The sa1100 controller is not supported */
+
+		else if (gadget_is_goku(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0226);
+		else if (gadget_is_mq11xx(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0227);
+		else if (gadget_is_omap(fsg->gadget))
+			mod_data.release = __constant_cpu_to_le16(0x0228);
+		else {
+			WARN(fsg, "controller '%s' not recognized\n",
+				fsg->gadget->name);
+			mod_data.release = __constant_cpu_to_le16(0x0299);
+		}
+	}
+
 	prot = simple_strtol(mod_data.protocol_parm, NULL, 0);
 
 #ifdef CONFIG_USB_FILE_STORAGE_TEST
@@ -3729,7 +3601,7 @@ static int __init check_parameters(struc
 		mod_data.transport_type = USB_PR_CBI;
 		mod_data.transport_name = "Control-Bulk-Interrupt";
 	} else {
-		INFO(fsg, "invalid transport: %s\n", mod_data.transport_parm);
+		ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm);
 		return -EINVAL;
 	}
 
@@ -3758,13 +3630,13 @@ static int __init check_parameters(struc
 		mod_data.protocol_type = USB_SC_8070;
 		mod_data.protocol_name = "8070i";
 	} else {
-		INFO(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
+		ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm);
 		return -EINVAL;
 	}
 
 	mod_data.buflen &= PAGE_CACHE_MASK;
 	if (mod_data.buflen <= 0) {
-		INFO(fsg, "invalid buflen\n");
+		ERROR(fsg, "invalid buflen\n");
 		return -ETOOSMALL;
 	}
 #endif /* CONFIG_USB_FILE_STORAGE_TEST */
@@ -3800,7 +3672,7 @@ static int __init fsg_bind(struct usb_ga
 		}
 	}
 	if (i > MAX_LUNS) {
-		INFO(fsg, "invalid number of LUNs: %d\n", i);
+		ERROR(fsg, "invalid number of LUNs: %d\n", i);
 		rc = -EINVAL;
 		goto out;
 	}
@@ -3827,45 +3699,57 @@ static int __init fsg_bind(struct usb_ga
 			if ((rc = open_backing_file(curlun, file[i])) != 0)
 				goto out;
 		} else if (!mod_data.removable) {
-			INFO(fsg, "no file given for LUN%d\n", i);
+			ERROR(fsg, "no file given for LUN%d\n", i);
 			rc = -EINVAL;
 			goto out;
 		}
 	}
 
+	/* Find all the endpoints we will use */
+	usb_ep_autoconfig_reset(gadget);
+	ep = usb_ep_autoconfig(gadget, &fs_bulk_in_desc);
+	if (!ep)
+		goto autoconf_fail;
+	ep->driver_data = fsg;		// claim the endpoint
+	fsg->bulk_in = ep;
+
+	ep = usb_ep_autoconfig(gadget, &fs_bulk_out_desc);
+	if (!ep)
+		goto autoconf_fail;
+	ep->driver_data = fsg;		// claim the endpoint
+	fsg->bulk_out = ep;
+
+	if (transport_is_cbi()) {
+		ep = usb_ep_autoconfig(gadget, &fs_intr_in_desc);
+		if (!ep)
+			goto autoconf_fail;
+		ep->driver_data = fsg;		// claim the endpoint
+		fsg->intr_in = ep;
+	}
+
 	/* Fix up the descriptors */
 	device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket;
-#ifdef HIGHSPEED
-	dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;		// ???
-#endif
 	device_desc.idVendor = cpu_to_le16(mod_data.vendor);
 	device_desc.idProduct = cpu_to_le16(mod_data.product);
 	device_desc.bcdDevice = cpu_to_le16(mod_data.release);
 
 	i = (transport_is_cbi() ? 3 : 2);	// Number of endpoints
-	config_desc.wTotalLength = USB_DT_CONFIG_SIZE + USB_DT_INTERFACE_SIZE
-			+ USB_DT_ENDPOINT_SIZE * i;
 	intf_desc.bNumEndpoints = i;
 	intf_desc.bInterfaceSubClass = mod_data.protocol_type;
 	intf_desc.bInterfaceProtocol = mod_data.transport_type;
+	fs_function[i+1] = NULL;
 
-	/* Find all the endpoints we will use */
-	gadget_for_each_ep(ep, gadget) {
-		if (strcmp(ep->name, EP_BULK_IN_NAME) == 0)
-			fsg->bulk_in = ep;
-		else if (strcmp(ep->name, EP_BULK_OUT_NAME) == 0)
-			fsg->bulk_out = ep;
-		else if (strcmp(ep->name, EP_INTR_IN_NAME) == 0)
-			fsg->intr_in = ep;
-	}
-	if (!fsg->bulk_in || !fsg->bulk_out ||
-			(transport_is_cbi() && !fsg->intr_in)) {
-		DBG(fsg, "unable to find all endpoints\n");
-		rc = -ENOTSUPP;
-		goto out;
-	}
-	fsg->bulk_out_maxpacket = (gadget->speed == USB_SPEED_HIGH ? 512 :
-			FS_BULK_OUT_MAXPACKET);
+#ifdef CONFIG_USB_GADGET_DUALSPEED
+	hs_function[i+1] = NULL;
+
+	/* Assume ep0 uses the same maxpacket value for both speeds */
+	dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket;
+
+	/* Assume that all endpoint addresses are the same for both speeds */
+	hs_bulk_in_desc.bEndpointAddress = fs_bulk_in_desc.bEndpointAddress;
+	hs_bulk_out_desc.bEndpointAddress = fs_bulk_out_desc.bEndpointAddress;
+	hs_intr_in_desc.bEndpointAddress = fs_intr_in_desc.bEndpointAddress;
+#endif
 
 	rc = -ENOMEM;
 
@@ -3894,6 +3778,10 @@ static int __init fsg_bind(struct usb_ga
 	/* This should reflect the actual gadget power source */
 	usb_gadget_set_selfpowered(gadget);
 
+	snprintf(manufacturer, sizeof manufacturer,
+			UTS_SYSNAME " " UTS_RELEASE " with %s",
+			gadget->name);
+
 	/* On a real device, serial[] would be loaded from permanent
 	 * storage.  We just encode it from the driver version string. */
 	for (i = 0; i < sizeof(serial) - 2; i += 2) {
@@ -3942,6 +3830,10 @@ static int __init fsg_bind(struct usb_ga
 	DBG(fsg, "I/O thread pid: %d\n", fsg->thread_pid);
 	return 0;
 
+autoconf_fail:
+	ERROR(fsg, "unable to autoconfigure all endpoints\n");
+	rc = -ENOTSUPP;
+
 out:
 	fsg->state = FSG_STATE_TERMINATED;	// The thread is dead
 	fsg_unbind(gadget);
@@ -3953,7 +3845,7 @@ out:
 /*-------------------------------------------------------------------------*/
 
 static struct usb_gadget_driver		fsg_driver = {
-#ifdef HIGHSPEED
+#ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
 #else
 	.speed		= USB_SPEED_FULL,
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/gadget_chips.h linux-2.4.27-rc4/drivers/usb/gadget/gadget_chips.h
--- linux-2.4.26/drivers/usb/gadget/gadget_chips.h	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/gadget_chips.h	2004-07-30 16:26:10.000000000 +0000
@@ -14,7 +14,13 @@
 #define	gadget_is_net2280(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA
+#ifdef CONFIG_USB_GADGET_DUMMY_HCD
+#define	gadget_is_dummy(g)	!strcmp("dummy_udc", (g)->name)
+#else
+#define	gadget_is_dummy(g)	0
+#endif
+
+#ifdef CONFIG_USB_GADGET_PXA2XX
 #define	gadget_is_pxa(g)	!strcmp("pxa2xx_udc", (g)->name)
 #else
 #define	gadget_is_pxa(g)	0
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/ndis.h linux-2.4.27-rc4/drivers/usb/gadget/ndis.h
--- linux-2.4.26/drivers/usb/gadget/ndis.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/ndis.h	2004-07-30 16:29:50.000000000 +0000
@@ -0,0 +1,217 @@
+/*
+ * ndis.h 
+ * 
+ * ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
+ * 
+ * Thanks to the cygwin development team, 
+ * espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
+ * 
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef _LINUX_NDIS_H
+#define _LINUX_NDIS_H
+
+
+#define NDIS_STATUS_MULTICAST_FULL	  0xC0010009
+#define NDIS_STATUS_MULTICAST_EXISTS      0xC001000A
+#define NDIS_STATUS_MULTICAST_NOT_FOUND   0xC001000B
+
+enum NDIS_DEVICE_POWER_STATE {
+	NdisDeviceStateUnspecified = 0,
+	NdisDeviceStateD0,
+	NdisDeviceStateD1,
+	NdisDeviceStateD2,
+	NdisDeviceStateD3,
+	NdisDeviceStateMaximum
+};
+
+struct NDIS_PM_WAKE_UP_CAPABILITIES {
+	enum NDIS_DEVICE_POWER_STATE  MinMagicPacketWakeUp;
+	enum NDIS_DEVICE_POWER_STATE  MinPatternWakeUp;
+	enum NDIS_DEVICE_POWER_STATE  MinLinkChangeWakeUp;
+};
+
+/* NDIS_PNP_CAPABILITIES.Flags constants */
+#define NDIS_DEVICE_WAKE_UP_ENABLE                0x00000001
+#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE  0x00000002
+#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE   0x00000004
+
+struct NDIS_PNP_CAPABILITIES {
+	u32					Flags;
+	struct NDIS_PM_WAKE_UP_CAPABILITIES	WakeUpCapabilities;
+};
+
+struct NDIS_PM_PACKET_PATTERN {
+	u32	Priority;
+	u32	Reserved;
+	u32	MaskSize;
+	u32	PatternOffset;
+	u32	PatternSize;
+	u32	PatternFlags;
+};
+
+
+/* Required Object IDs (OIDs) */
+#define OID_GEN_SUPPORTED_LIST            0x00010101
+#define OID_GEN_HARDWARE_STATUS           0x00010102
+#define OID_GEN_MEDIA_SUPPORTED           0x00010103
+#define OID_GEN_MEDIA_IN_USE              0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD         0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE        0x00010106
+#define OID_GEN_LINK_SPEED                0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE     0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE      0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE       0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE        0x0001010B
+#define OID_GEN_VENDOR_ID                 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION        0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER     0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD         0x0001010F
+#define OID_GEN_DRIVER_VERSION            0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE        0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS          0x00010112
+#define OID_GEN_MAC_OPTIONS               0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS      0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS      0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION     0x00010116
+#define OID_GEN_SUPPORTED_GUIDS           0x00010117
+#define OID_GEN_NETWORK_LAYER_ADDRESSES   0x00010118
+#define OID_GEN_TRANSPORT_HEADER_OFFSET   0x00010119
+#define OID_GEN_MACHINE_NAME              0x0001021A
+#define OID_GEN_RNDIS_CONFIG_PARAMETER    0x0001021B
+#define OID_GEN_VLAN_ID                   0x0001021C
+
+/* Optional OIDs */
+#define OID_GEN_MEDIA_CAPABILITIES        0x00010201
+#define OID_GEN_PHYSICAL_MEDIUM           0x00010202
+
+/* Required statistics OIDs */
+#define OID_GEN_XMIT_OK                   0x00020101
+#define OID_GEN_RCV_OK                    0x00020102
+#define OID_GEN_XMIT_ERROR                0x00020103
+#define OID_GEN_RCV_ERROR                 0x00020104
+#define OID_GEN_RCV_NO_BUFFER             0x00020105
+
+/* Optional statistics OIDs */
+#define OID_GEN_DIRECTED_BYTES_XMIT       0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT      0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT      0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT     0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT      0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT     0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV        0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV       0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV       0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV      0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV       0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV      0x0002020C
+#define OID_GEN_RCV_CRC_ERROR             0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH     0x0002020E
+#define OID_GEN_GET_TIME_CAPS             0x0002020F
+#define OID_GEN_GET_NETCARD_TIME          0x00020210
+#define OID_GEN_NETCARD_LOAD              0x00020211
+#define OID_GEN_DEVICE_PROFILE            0x00020212
+#define OID_GEN_INIT_TIME_MS              0x00020213
+#define OID_GEN_RESET_COUNTS              0x00020214
+#define OID_GEN_MEDIA_SENSE_COUNTS        0x00020215
+#define OID_GEN_FRIENDLY_NAME             0x00020216
+#define OID_GEN_MINIPORT_INFO             0x00020217
+#define OID_GEN_RESET_VERIFY_PARAMETERS   0x00020218
+
+/* IEEE 802.3 (Ethernet) OIDs */
+#define NDIS_802_3_MAC_OPTION_PRIORITY    0x00000001
+
+#define OID_802_3_PERMANENT_ADDRESS       0x01010101
+#define OID_802_3_CURRENT_ADDRESS         0x01010102
+#define OID_802_3_MULTICAST_LIST          0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE       0x01010104
+#define OID_802_3_MAC_OPTIONS             0x01010105
+#define OID_802_3_RCV_ERROR_ALIGNMENT     0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION      0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS    0x01020103
+#define OID_802_3_XMIT_DEFERRED           0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS     0x01020202
+#define OID_802_3_RCV_OVERRUN             0x01020203
+#define OID_802_3_XMIT_UNDERRUN           0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE  0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST     0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS    0x01020207
+
+/* OID_GEN_MINIPORT_INFO constants */
+#define NDIS_MINIPORT_BUS_MASTER                      0x00000001
+#define NDIS_MINIPORT_WDM_DRIVER                      0x00000002
+#define NDIS_MINIPORT_SG_LIST                         0x00000004
+#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY            0x00000008
+#define NDIS_MINIPORT_INDICATES_PACKETS               0x00000010
+#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE             0x00000020
+#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE            0x00000040
+#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS        0x00000080
+#define NDIS_MINIPORT_INTERMEDIATE_DRIVER             0x00000100
+#define NDIS_MINIPORT_IS_NDIS_5                       0x00000200
+#define NDIS_MINIPORT_IS_CO                           0x00000400
+#define NDIS_MINIPORT_DESERIALIZE                     0x00000800
+#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING          0x00001000
+#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE            0x00002000
+#define NDIS_MINIPORT_NETBOOT_CARD                    0x00004000
+#define NDIS_MINIPORT_PM_SUPPORTED                    0x00008000
+#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE  0x00010000
+#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS           0x00020000
+#define NDIS_MINIPORT_HIDDEN                          0x00040000
+#define NDIS_MINIPORT_SWENUM                          0x00080000
+#define NDIS_MINIPORT_SURPRISE_REMOVE_OK              0x00100000
+#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND              0x00200000
+#define NDIS_MINIPORT_HARDWARE_DEVICE                 0x00400000
+#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS    0x00800000
+#define NDIS_MINIPORT_64BITS_DMA                      0x01000000
+
+#define NDIS_MEDIUM_802_3		0x00000000
+#define NDIS_MEDIUM_802_5		0x00000001
+#define NDIS_MEDIUM_FDDI		0x00000002
+#define NDIS_MEDIUM_WAN			0x00000003
+#define NDIS_MEDIUM_LOCAL_TALK		0x00000004
+#define NDIS_MEDIUM_DIX			0x00000005
+#define NDIS_MEDIUM_ARCENT_RAW		0x00000006
+#define NDIS_MEDIUM_ARCENT_878_2	0x00000007
+#define NDIS_MEDIUM_ATM			0x00000008
+#define NDIS_MEDIUM_WIRELESS_LAN	0x00000009
+#define NDIS_MEDIUM_IRDA		0x0000000A
+#define NDIS_MEDIUM_BPC			0x0000000B
+#define NDIS_MEDIUM_CO_WAN		0x0000000C
+#define NDIS_MEDIUM_1394		0x0000000D
+
+#define NDIS_PACKET_TYPE_DIRECTED	0x00000001
+#define NDIS_PACKET_TYPE_MULTICAST	0x00000002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST	0x00000004
+#define NDIS_PACKET_TYPE_BROADCAST	0x00000008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING	0x00000010
+#define NDIS_PACKET_TYPE_PROMISCUOUS	0x00000020
+#define NDIS_PACKET_TYPE_SMT		0x00000040
+#define NDIS_PACKET_TYPE_ALL_LOCAL	0x00000080
+#define NDIS_PACKET_TYPE_GROUP		0x00000100
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL	0x00000200
+#define NDIS_PACKET_TYPE_FUNCTIONAL	0x00000400
+#define NDIS_PACKET_TYPE_MAC_FRAME	0x00000800
+
+#define NDIS_MEDIA_STATE_CONNECTED	0x00000000
+#define NDIS_MEDIA_STATE_DISCONNECTED	0x00000001
+
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA     0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED      0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND      0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK             0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX             0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION         0x00000020
+#define NDIS_MAC_OPTION_8021P_PRIORITY          0x00000040
+#define NDIS_MAC_OPTION_RESERVED                0x80000000
+
+#endif /* _LINUX_NDIS_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/rndis.c linux-2.4.27-rc4/drivers/usb/gadget/rndis.c
--- linux-2.4.26/drivers/usb/gadget/rndis.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/rndis.c	2004-07-30 16:32:13.000000000 +0000
@@ -0,0 +1,1426 @@
+/* 
+ * RNDIS MSG parser
+ * 
+ * Version:     $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
+ * 
+ * Authors:	Benedikt Spranger, Pengutronix
+ * 		Robert Schwebel, Pengutronix
+ * 
+ *              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. 
+ * 
+ *		This software was originally developed in conformance with
+ *		Microsoft's Remote NDIS Specification License Agreement.
+ *              
+ * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
+ *		Fixed message length bug in init_response
+ * 
+ * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
+ * 		Fixed rndis_rm_hdr length bug.
+ *
+ * Copyright (C) 2004 by David Brownell
+ *		updates to merge with Linux 2.6, better match RNDIS spec
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+
+#include <asm/io.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+
+#undef	RNDIS_PM
+#undef	VERBOSE
+
+#include "rndis.h"
+
+
+/* The driver for your USB chip needs to support ep0 OUT to work with
+ * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional).
+ *
+ * Windows hosts need an INF file like Documentation/usb/linux.inf
+ * and will be happier if you provide the host_addr module parameter.
+ */
+
+#if 0
+#define DEBUG(str,args...) do { \
+	if (rndis_debug) \
+		printk(KERN_DEBUG str , ## args ); \
+	} while (0)
+static int rndis_debug = 0;
+
+module_param (rndis_debug, bool, 0);
+MODULE_PARM_DESC (rndis_debug, "enable debugging");
+
+#else
+
+#define rndis_debug		0
+#define DEBUG(str,args...)	do{}while(0)
+#endif
+
+#define RNDIS_MAX_CONFIGS	1
+
+static struct proc_dir_entry *rndis_connect_dir;
+static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS];
+
+static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
+
+/* Driver Version */
+static const u32 rndis_driver_version = __constant_cpu_to_le32 (1);
+
+/* Function Prototypes */
+static int rndis_init_response (int configNr, rndis_init_msg_type *buf);
+static int rndis_query_response (int configNr, rndis_query_msg_type *buf);
+static int rndis_set_response (int configNr, rndis_set_msg_type *buf);
+static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf);
+static int rndis_keepalive_response (int configNr, 
+				     rndis_keepalive_msg_type *buf);
+
+static rndis_resp_t *rndis_add_response (int configNr, u32 length);
+
+
+/* NDIS Functions */
+static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
+{
+	int 			retval = -ENOTSUPP;
+	u32 			length = 0;
+	u32			*tmp;
+	int			i, count;
+	rndis_query_cmplt_type	*resp;
+
+	if (!r) return -ENOMEM;
+	resp = (rndis_query_cmplt_type *) r->buf;
+
+	if (!resp) return -ENOMEM;
+	
+	switch (OID) {
+
+	/* general oids (table 4-1) */
+
+	/* mandatory */
+	case OID_GEN_SUPPORTED_LIST:
+		DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__);
+		length = sizeof (oid_supported_list);
+		count  = length / sizeof (u32);
+		tmp = (u32 *) ((u8 *)resp + 24);
+		for (i = 0; i < count; i++)
+			tmp[i] = cpu_to_le32 (oid_supported_list[i]);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_GEN_HARDWARE_STATUS:
+		DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
+		length = 4;
+		/* Bogus question! 
+		 * Hardware must be ready to recieve high level protocols.
+		 * BTW: 
+		 * reddite ergo quae sunt Caesaris Caesari
+		 * et quae sunt Dei Deo!
+		 */
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_GEN_MEDIA_SUPPORTED:
+		DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params [configNr].medium);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_GEN_MEDIA_IN_USE:
+		DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
+		length = 4;
+		/* one medium, one transport... (maybe you do it better) */
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params [configNr].medium);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_GEN_MAXIMUM_FRAME_SIZE:
+		DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].dev) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].dev->mtu);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_GEN_LINK_SPEED:
+		DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
+		length = 4;
+		if (rndis_per_dev_params [configNr].media_state
+			== NDIS_MEDIA_STATE_DISCONNECTED)
+		    *((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		else
+		    *((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].speed);
+		retval = 0;
+		break;
+
+	/* mandatory */
+	case OID_GEN_TRANSMIT_BLOCK_SIZE:
+		DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].dev) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].dev->mtu);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_GEN_RECEIVE_BLOCK_SIZE:
+		DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].dev) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr].dev->mtu);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_GEN_VENDOR_ID:
+		DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+			rndis_per_dev_params [configNr].vendorID);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_GEN_VENDOR_DESCRIPTION:
+		DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
+		length = strlen (rndis_per_dev_params [configNr].vendorDescr);
+		memcpy ((u8 *) resp + 24, 
+			rndis_per_dev_params [configNr].vendorDescr, length);
+		retval = 0;
+		break;
+
+	case OID_GEN_VENDOR_DRIVER_VERSION:
+		DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__);
+		length = 4;
+		/* Created as LE */
+		*((u32 *) resp + 6) = rndis_driver_version;
+		retval = 0;
+		break;
+
+	/* mandatory */
+	case OID_GEN_CURRENT_PACKET_FILTER:
+		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params[configNr].filter);
+		retval = 0;
+		break;
+
+	/* mandatory */
+	case OID_GEN_MAXIMUM_TOTAL_SIZE:
+		DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32(
+					RNDIS_MAX_TOTAL_SIZE);
+		retval = 0;
+		break;
+
+	/* mandatory */
+	case OID_GEN_MEDIA_CONNECT_STATUS:
+		DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = cpu_to_le32 (
+					rndis_per_dev_params [configNr]
+						.media_state);
+		retval = 0;
+		break;
+
+	case OID_GEN_PHYSICAL_MEDIUM:
+		DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+
+	/* The RNDIS specification is incomplete/wrong.   Some versions
+	 * of MS-Windows expect OIDs that aren't specified there.  Other
+	 * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
+	 */
+	case OID_GEN_MAC_OPTIONS:		/* from WinME */
+		DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32(
+			  NDIS_MAC_OPTION_RECEIVE_SERIALIZED
+			| NDIS_MAC_OPTION_FULL_DUPLEX);
+		retval = 0;
+		break;
+
+	/* statistics OIDs (table 4-2) */
+
+	/* mandatory */
+	case OID_GEN_XMIT_OK:
+		DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+			    rndis_per_dev_params [configNr].stats->tx_packets - 
+			    rndis_per_dev_params [configNr].stats->tx_errors -
+			    rndis_per_dev_params [configNr].stats->tx_dropped);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+
+	/* mandatory */
+	case OID_GEN_RCV_OK:
+		DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+			    rndis_per_dev_params [configNr].stats->rx_packets - 
+			    rndis_per_dev_params [configNr].stats->rx_errors -
+			    rndis_per_dev_params [configNr].stats->rx_dropped);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_GEN_XMIT_ERROR:
+		DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->tx_errors);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_GEN_RCV_ERROR:
+		DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_errors);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_GEN_RCV_NO_BUFFER:
+		DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_dropped);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+
+#ifdef	RNDIS_OPTIONAL_STATS
+	case OID_GEN_DIRECTED_BYTES_XMIT:
+		DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
+		/* 
+		 * Aunt Tilly's size of shoes
+		 * minus antarctica count of penguins
+		 * divided by weight of Alpha Centauri
+		 */
+		if (rndis_per_dev_params [configNr].stats) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				(rndis_per_dev_params [configNr]
+					.stats->tx_packets - 
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_errors -
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_dropped)
+				* 123);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_DIRECTED_FRAMES_XMIT:
+		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
+		/* dito */
+		if (rndis_per_dev_params [configNr].stats) {
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				(rndis_per_dev_params [configNr]
+					.stats->tx_packets - 
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_errors -
+				 rndis_per_dev_params [configNr]
+					 .stats->tx_dropped)
+				/ 123);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_MULTICAST_BYTES_XMIT:
+		DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast*1234);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_MULTICAST_FRAMES_XMIT:
+		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_BROADCAST_BYTES_XMIT:
+		DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->tx_packets/42*255);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_BROADCAST_FRAMES_XMIT:
+		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->tx_packets/42);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_DIRECTED_BYTES_RCV:
+		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+		
+	case OID_GEN_DIRECTED_FRAMES_RCV:
+		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+		
+	case OID_GEN_MULTICAST_BYTES_RCV:
+		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast * 1111);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_MULTICAST_FRAMES_RCV:
+		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->multicast);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_BROADCAST_BYTES_RCV:
+		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_packets/42*255);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_BROADCAST_FRAMES_RCV:
+		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_packets/42);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_RCV_CRC_ERROR:
+		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats) {
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_crc_errors);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+	/* ieee802.3 OIDs (table 4-3) */
+
+	/* mandatory */
+	case OID_802_3_PERMANENT_ADDRESS:
+		DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].dev) {
+			length = ETH_ALEN;
+			memcpy ((u8 *) resp + 24,
+				rndis_per_dev_params [configNr].host_mac,
+				length);
+			retval = 0;
+		} else {
+			*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_802_3_CURRENT_ADDRESS:
+		DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].dev) {
+			length = ETH_ALEN;
+			memcpy ((u8 *) resp + 24,
+				rndis_per_dev_params [configNr].host_mac,
+				length);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_802_3_MULTICAST_LIST:
+		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+		length = 4;
+		/* Multicast base address only */
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0xE0000000);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_802_3_MAXIMUM_LIST_SIZE:
+		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
+		 length = 4;
+		/* Multicast base address only */
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (1);
+		retval = 0;
+		break;
+		
+	case OID_802_3_MAC_OPTIONS:
+		DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
+		break;
+
+	/* ieee802.3 statistics OIDs (table 4-4) */
+
+	/* mandatory */
+	case OID_802_3_RCV_ERROR_ALIGNMENT:
+		DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__);
+		if (rndis_per_dev_params [configNr].stats)
+		{
+			length = 4;
+			*((u32 *) resp + 6) = cpu_to_le32 (
+				rndis_per_dev_params [configNr]
+					.stats->rx_frame_errors);
+			retval = 0;
+		}
+		break;
+		
+	/* mandatory */
+	case OID_802_3_XMIT_ONE_COLLISION:
+		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+		
+	/* mandatory */
+	case OID_802_3_XMIT_MORE_COLLISIONS:
+		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
+		length = 4;
+		*((u32 *) resp + 6) = __constant_cpu_to_le32 (0);
+		retval = 0;
+		break;
+		
+#ifdef	RNDIS_OPTIONAL_STATS
+	case OID_802_3_XMIT_DEFERRED:
+		DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
+		/* TODO */
+		break;
+		
+	case OID_802_3_XMIT_MAX_COLLISIONS:
+		DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
+		/* TODO */
+		break;
+		
+	case OID_802_3_RCV_OVERRUN:
+		DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
+		/* TODO */
+		break;
+		
+	case OID_802_3_XMIT_UNDERRUN:
+		DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
+		/* TODO */
+		break;
+		
+	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
+		DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
+		/* TODO */
+		break;
+		
+	case OID_802_3_XMIT_TIMES_CRS_LOST:
+		DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
+		/* TODO */
+		break;
+		
+	case OID_802_3_XMIT_LATE_COLLISIONS:
+		DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
+		/* TODO */
+		break;		
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+#ifdef	RNDIS_PM
+	/* power management OIDs (table 4-5) */
+	case OID_PNP_CAPABILITIES:
+		DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__);
+
+		/* just PM, and remote wakeup on link status change
+		 * (not magic packet or pattern match)
+		 */
+		length = sizeof (struct NDIS_PNP_CAPABILITIES);
+		memset (resp, 0, length);
+		{
+			struct NDIS_PNP_CAPABILITIES *caps = (void *) resp;
+
+			caps->Flags = NDIS_DEVICE_WAKE_UP_ENABLE;
+			caps->WakeUpCapabilities.MinLinkChangeWakeUp 
+				 = NdisDeviceStateD3;
+
+			/* FIXME then use usb_gadget_wakeup(), and
+			 * set USB_CONFIG_ATT_WAKEUP in config desc
+			 */
+		}
+		retval = 0;
+		break;
+	case OID_PNP_QUERY_POWER:
+		DEBUG("%s: OID_PNP_QUERY_POWER\n", __FUNCTION__);
+		/* sure, handle any power state that maps to USB suspend */
+		retval = 0;
+		break;
+#endif
+
+	default:
+		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 
+			 __FUNCTION__, OID);
+	}
+	
+	resp->InformationBufferOffset = __constant_cpu_to_le32 (16);
+	resp->InformationBufferLength = cpu_to_le32 (length);
+	resp->MessageLength = cpu_to_le32 (24 + length);
+	r->length = 24 + length;
+	return retval;
+}
+
+static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, 
+			      rndis_resp_t *r)
+{
+	rndis_set_cmplt_type		*resp;
+	int 				i, retval = -ENOTSUPP;
+	struct rndis_params		*params;
+
+	if (!r)
+		return -ENOMEM;
+	resp = (rndis_set_cmplt_type *) r->buf;
+	if (!resp)
+		return -ENOMEM;
+
+	DEBUG("set OID %08x value, len %d:\n", OID, buf_len);
+	for (i = 0; i < buf_len; i += 16) {
+		DEBUG ("%03d: "
+			" %02x %02x %02x %02x"
+			" %02x %02x %02x %02x"
+			" %02x %02x %02x %02x"
+			" %02x %02x %02x %02x"
+			"\n",
+			i,
+			buf[i], buf [i+1],
+				buf[i+2], buf[i+3],
+			buf[i+4], buf [i+5],
+				buf[i+6], buf[i+7],
+			buf[i+8], buf [i+9],
+				buf[i+10], buf[i+11],
+			buf[i+12], buf [i+13],
+				buf[i+14], buf[i+15]);
+	}
+
+	switch (OID) {
+	case OID_GEN_CURRENT_PACKET_FILTER:
+		params = &rndis_per_dev_params [configNr];
+		retval = 0;
+
+		/* FIXME use these NDIS_PACKET_TYPE_* bitflags to
+		 * filter packets in hard_start_xmit()
+		 * NDIS_PACKET_TYPE_x == CDC_PACKET_TYPE_x for x in:
+		 *	PROMISCUOUS, DIRECTED,
+		 *	MULTICAST, ALL_MULTICAST, BROADCAST
+		 */
+		params->filter = cpu_to_le32p((u32 *)buf);
+		DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n",
+			__FUNCTION__, params->filter);
+
+		/* this call has a significant side effect:  it's
+		 * what makes the packet flow start and stop, like
+		 * activating the CDC Ethernet altsetting.
+		 */
+		if (params->filter) {
+			params->state = RNDIS_DATA_INITIALIZED;
+			netif_carrier_on(params->dev);
+			if (netif_running(params->dev))
+				netif_wake_queue (params->dev);
+		} else {
+			params->state = RNDIS_INITIALIZED;
+			netif_carrier_off (params->dev);
+			netif_stop_queue (params->dev);
+		}
+		break;
+		
+	case OID_802_3_MULTICAST_LIST:
+		/* I think we can ignore this */		
+		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
+		retval = 0;
+		break;
+#if 0
+	case OID_GEN_RNDIS_CONFIG_PARAMETER:
+		{
+		struct rndis_config_parameter	*param;
+		param = (struct rndis_config_parameter *) buf;
+		DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n",
+			__FUNCTION__,
+			min(cpu_to_le32(param->ParameterNameLength),80),
+			buf + param->ParameterNameOffset);
+		retval = 0;
+		}
+		break;
+#endif
+
+#ifdef	RNDIS_PM
+	case OID_PNP_SET_POWER:
+		DEBUG ("OID_PNP_SET_POWER\n");
+		/* sure, handle any power state that maps to USB suspend */
+		retval = 0;
+		break;
+
+	case OID_PNP_ENABLE_WAKE_UP:
+		/* always-connected ... */
+		DEBUG ("OID_PNP_ENABLE_WAKE_UP\n");
+		retval = 0;
+		break;
+
+	// no PM resume patterns supported (specified where?)
+	// so OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN always fails
+#endif
+
+	default:
+		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", 
+			 __FUNCTION__, OID, buf_len);
+	}
+	
+	return retval;
+}
+
+/* 
+ * Response Functions 
+ */
+
+static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
+{
+	rndis_init_cmplt_type	*resp; 
+	rndis_resp_t            *r;
+	
+	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+	
+	r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
+	
+	if (!r) return -ENOMEM;
+	
+	resp = (rndis_init_cmplt_type *) r->buf;
+	
+	if (!resp) return -ENOMEM;
+	
+	resp->MessageType = __constant_cpu_to_le32 (
+			REMOTE_NDIS_INITIALIZE_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (52);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION);
+	resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION);
+	resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS);
+	resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3);
+	resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1);
+	resp->MaxTransferSize = cpu_to_le32 (
+		  rndis_per_dev_params [configNr].dev->mtu
+		+ sizeof (struct ethhdr)
+		+ sizeof (struct rndis_packet_msg_type)
+		+ 22);
+	resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0);
+	resp->AFListOffset = __constant_cpu_to_le32 (0);
+	resp->AFListSize = __constant_cpu_to_le32 (0);
+	
+	if (rndis_per_dev_params [configNr].ack)
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
+	
+	return 0;
+}
+
+static int rndis_query_response (int configNr, rndis_query_msg_type *buf)
+{
+	rndis_query_cmplt_type *resp;
+	rndis_resp_t            *r;
+	
+	// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
+	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
+	
+	/* 
+	 * we need more memory: 
+	 * oid_supported_list is the largest answer 
+	 */
+	r = rndis_add_response (configNr, sizeof (oid_supported_list));
+	
+	if (!r) return -ENOMEM;
+	resp = (rndis_query_cmplt_type *) r->buf;
+	
+	if (!resp) return -ENOMEM;
+	
+	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (24);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	
+	if (gen_ndis_query_resp (configNr, cpu_to_le32 (buf->OID), r)) {
+		/* OID not supported */
+		resp->Status = __constant_cpu_to_le32 (
+				RNDIS_STATUS_NOT_SUPPORTED);
+		resp->InformationBufferLength = __constant_cpu_to_le32 (0);
+		resp->InformationBufferOffset = __constant_cpu_to_le32 (0);
+	} else
+		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	
+	if (rndis_per_dev_params [configNr].ack)
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
+	return 0;
+}
+
+static int rndis_set_response (int configNr, rndis_set_msg_type *buf)
+{
+	u32			BufLength, BufOffset;
+	rndis_set_cmplt_type	*resp;
+	rndis_resp_t		*r;
+	
+	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
+	
+	if (!r) return -ENOMEM;
+	resp = (rndis_set_cmplt_type *) r->buf;
+	if (!resp) return -ENOMEM;
+
+	BufLength = cpu_to_le32 (buf->InformationBufferLength);
+	BufOffset = cpu_to_le32 (buf->InformationBufferOffset);
+
+#ifdef	VERBOSE
+	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
+	DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
+	DEBUG("%s: InfoBuffer: ", __FUNCTION__);
+	
+	for (i = 0; i < BufLength; i++) {
+		DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
+	}
+	
+	DEBUG ("\n");
+#endif
+	
+	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (16);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	if (gen_ndis_set_resp (configNr, cpu_to_le32 (buf->OID), 
+			       ((u8 *) buf) + 8 + BufOffset, BufLength, r))
+	    resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
+	else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	
+	if (rndis_per_dev_params [configNr].ack)
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
+	
+	return 0;
+}
+
+static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf)
+{
+	rndis_reset_cmplt_type	*resp;
+	rndis_resp_t		*r;
+	
+	r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
+	
+	if (!r) return -ENOMEM;
+	resp = (rndis_reset_cmplt_type *) r->buf;
+	if (!resp) return -ENOMEM;
+	
+	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (16);
+	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	/* resent information */
+	resp->AddressingReset = __constant_cpu_to_le32 (1);
+	
+	if (rndis_per_dev_params [configNr].ack)
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
+
+	return 0;
+}
+
+static int rndis_keepalive_response (int configNr,
+				     rndis_keepalive_msg_type *buf)
+{
+	rndis_keepalive_cmplt_type	*resp;
+	rndis_resp_t			*r;
+
+	/* host "should" check only in RNDIS_DATA_INITIALIZED state */
+
+	r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
+	resp = (rndis_keepalive_cmplt_type *) r->buf;
+	if (!resp) return -ENOMEM;
+		
+	resp->MessageType = __constant_cpu_to_le32 (
+			REMOTE_NDIS_KEEPALIVE_CMPLT);
+	resp->MessageLength = __constant_cpu_to_le32 (16);
+	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
+	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+	
+	if (rndis_per_dev_params [configNr].ack)
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
+	
+	return 0;
+}
+
+
+/* 
+ * Device to Host Comunication 
+ */
+static int rndis_indicate_status_msg (int configNr, u32 status)
+{
+	rndis_indicate_status_msg_type	*resp;	
+	rndis_resp_t			*r;
+	
+	if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
+	    return -ENOTSUPP;
+	
+	r = rndis_add_response (configNr, 
+				sizeof (rndis_indicate_status_msg_type));
+	if (!r) return -ENOMEM;
+	
+	resp = (rndis_indicate_status_msg_type *) r->buf;
+	if (!resp) return -ENOMEM;
+	
+	resp->MessageType = __constant_cpu_to_le32 (
+			REMOTE_NDIS_INDICATE_STATUS_MSG);
+	resp->MessageLength = __constant_cpu_to_le32 (20);
+	resp->Status = cpu_to_le32 (status);
+	resp->StatusBufferLength = __constant_cpu_to_le32 (0);
+	resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
+	
+	if (rndis_per_dev_params [configNr].ack) 
+	    rndis_per_dev_params [configNr].ack (
+	    		rndis_per_dev_params [configNr].dev);
+	return 0;
+}
+
+int rndis_signal_connect (int configNr)
+{
+	rndis_per_dev_params [configNr].media_state
+			= NDIS_MEDIA_STATE_CONNECTED;
+	return rndis_indicate_status_msg (configNr, 
+					  RNDIS_STATUS_MEDIA_CONNECT);
+}
+
+int rndis_signal_disconnect (int configNr)
+{
+	rndis_per_dev_params [configNr].media_state
+			= NDIS_MEDIA_STATE_DISCONNECTED;
+	return rndis_indicate_status_msg (configNr,
+					  RNDIS_STATUS_MEDIA_DISCONNECT);
+}
+
+void rndis_set_host_mac (int configNr, const u8 *addr)
+{
+	rndis_per_dev_params [configNr].host_mac = addr;
+}
+
+/* 
+ * Message Parser 
+ */
+int rndis_msg_parser (u8 configNr, u8 *buf)
+{
+	u32 MsgType, MsgLength, *tmp;
+	struct rndis_params		*params;
+	
+	if (!buf)
+		return -ENOMEM;
+	
+	tmp = (u32 *) buf; 
+	MsgType   = cpu_to_le32p(tmp++);
+	MsgLength = cpu_to_le32p(tmp++);
+	
+	if (configNr >= RNDIS_MAX_CONFIGS)
+		return -ENOTSUPP;
+	params = &rndis_per_dev_params [configNr];
+	
+	/* For USB: responses may take up to 10 seconds */
+	switch (MsgType)
+	{
+	case REMOTE_NDIS_INITIALIZE_MSG:
+		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 
+			__FUNCTION__ );
+		params->state = RNDIS_INITIALIZED;
+		return  rndis_init_response (configNr,
+					     (rndis_init_msg_type *) buf);
+		
+	case REMOTE_NDIS_HALT_MSG:
+		DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
+			__FUNCTION__ );
+		params->state = RNDIS_UNINITIALIZED;
+		if (params->dev) {
+			netif_carrier_off (params->dev);
+			netif_stop_queue (params->dev);
+		}
+		return 0;
+		
+	case REMOTE_NDIS_QUERY_MSG:
+		return rndis_query_response (configNr, 
+					     (rndis_query_msg_type *) buf);
+		
+	case REMOTE_NDIS_SET_MSG:
+		return rndis_set_response (configNr, 
+					   (rndis_set_msg_type *) buf);
+		
+	case REMOTE_NDIS_RESET_MSG:
+		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", 
+			__FUNCTION__ );
+		return rndis_reset_response (configNr,
+					     (rndis_reset_msg_type *) buf);
+
+	case REMOTE_NDIS_KEEPALIVE_MSG:
+		/* For USB: host does this every 5 seconds */
+#ifdef	VERBOSE
+		DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
+			__FUNCTION__ );
+#endif
+		return rndis_keepalive_response (configNr,
+						 (rndis_keepalive_msg_type *) 
+						 buf);
+		
+	default: 
+		/* At least Windows XP emits some undefined RNDIS messages.
+		 * In one case those messages seemed to relate to the host
+		 * suspending itself.
+		 */
+		printk (KERN_WARNING
+			"%s: unknown RNDIS message 0x%08X len %d\n", 
+			__FUNCTION__ , MsgType, MsgLength);
+		{
+			unsigned i;
+			for (i = 0; i < MsgLength; i += 16) {
+				DEBUG ("%03d: "
+					" %02x %02x %02x %02x"
+					" %02x %02x %02x %02x"
+					" %02x %02x %02x %02x"
+					" %02x %02x %02x %02x"
+					"\n",
+					i,
+					buf[i], buf [i+1],
+						buf[i+2], buf[i+3],
+					buf[i+4], buf [i+5],
+						buf[i+6], buf[i+7],
+					buf[i+8], buf [i+9],
+						buf[i+10], buf[i+11],
+					buf[i+12], buf [i+13],
+						buf[i+14], buf[i+15]);
+			}
+		}
+		break;
+	}
+	
+	return -ENOTSUPP;
+}
+
+int rndis_register (int (* rndis_control_ack) (struct net_device *))
+{
+	u8 i;
+	
+	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
+		if (!rndis_per_dev_params [i].used) {
+			rndis_per_dev_params [i].used = 1;
+			rndis_per_dev_params [i].ack = rndis_control_ack;
+			DEBUG("%s: configNr = %d\n", __FUNCTION__, i);
+			return i;
+		}
+	}
+	DEBUG("failed\n");
+	
+	return -1;
+}
+
+void rndis_deregister (int configNr)
+{
+	DEBUG("%s: \n", __FUNCTION__ );
+	
+	if (configNr >= RNDIS_MAX_CONFIGS) return;
+	rndis_per_dev_params [configNr].used = 0;
+	
+	return;
+}
+
+int rndis_set_param_dev (u8 configNr, struct net_device *dev, 
+			 struct net_device_stats *stats)
+{
+	DEBUG("%s:\n", __FUNCTION__ );
+	if (!dev || !stats) return -1;
+	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+	
+	rndis_per_dev_params [configNr].dev = dev;
+	rndis_per_dev_params [configNr].stats = stats;
+	
+	return 0;
+}
+
+int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr)
+{
+	DEBUG("%s:\n", __FUNCTION__ );
+	if (!vendorDescr) return -1;
+	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+	
+	rndis_per_dev_params [configNr].vendorID = vendorID;
+	rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
+	
+	return 0;
+}
+
+int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed)
+{
+	DEBUG("%s:\n", __FUNCTION__ );
+	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
+	
+	rndis_per_dev_params [configNr].medium = medium;
+	rndis_per_dev_params [configNr].speed = speed;
+	
+	return 0;
+}
+
+void rndis_add_hdr (struct sk_buff *skb)
+{
+	if (!skb) return;
+	skb_push (skb, sizeof (struct rndis_packet_msg_type));
+	memset (skb->data, 0, sizeof (struct rndis_packet_msg_type));
+	*((u32 *) skb->data) = __constant_cpu_to_le32 (1);
+	*((u32 *) skb->data + 1) = cpu_to_le32(skb->len);
+	*((u32 *) skb->data + 2) = __constant_cpu_to_le32 (36);
+	*((u32 *) skb->data + 3) = cpu_to_le32(skb->len - 44);
+	
+	return;
+}
+
+void rndis_free_response (int configNr, u8 *buf)
+{
+	rndis_resp_t		*r;
+	struct list_head	*act, *tmp;
+	
+	list_for_each_safe (act, tmp, 
+			    &(rndis_per_dev_params [configNr].resp_queue))
+	{
+		r = list_entry (act, rndis_resp_t, list);
+		if (r && r->buf == buf) {
+			list_del (&r->list);
+			kfree (r);
+		}
+	}
+}
+
+u8 *rndis_get_next_response (int configNr, u32 *length)
+{
+	rndis_resp_t		*r;
+	struct list_head 	*act, *tmp;
+	
+	if (!length) return NULL;
+	
+	list_for_each_safe (act, tmp, 
+			    &(rndis_per_dev_params [configNr].resp_queue))
+	{
+		r = list_entry (act, rndis_resp_t, list);
+		if (!r->send) {
+			r->send = 1;
+			*length = r->length;
+			return r->buf;
+		}
+	}
+	
+	return NULL;
+}
+
+static rndis_resp_t *rndis_add_response (int configNr, u32 length)
+{
+	rndis_resp_t	*r;
+	
+	r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
+	if (!r) return NULL;
+	
+	r->buf = (u8 *) (r + 1);
+	r->length = length;
+	r->send = 0;
+	
+	list_add_tail (&r->list, 
+		       &(rndis_per_dev_params [configNr].resp_queue));
+	return r;
+}
+
+int rndis_rm_hdr (u8 *buf, u32 *length)
+{
+	u32 i, messageLen, dataOffset, *tmp;
+	
+	tmp = (u32 *) buf; 
+
+	if (!buf || !length) return -1;
+	if (cpu_to_le32p(tmp++) != 1) return -1;
+	
+	messageLen = cpu_to_le32p(tmp++);
+	dataOffset = cpu_to_le32p(tmp++) + 8;
+
+	if (messageLen < dataOffset || messageLen > *length) return -1;
+	
+	for (i = dataOffset; i < messageLen; i++)
+		buf [i - dataOffset] = buf [i];
+		
+	*length = messageLen - dataOffset;
+	
+	return 0;
+}
+
+int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, 
+		     void *data)
+{
+	char *out = page;
+	int len;
+	rndis_params *param = (rndis_params *) data;
+	
+	out += snprintf (out, count, 
+			 "Config Nr. %d\n"
+			 "used      : %s\n"
+			 "state     : %s\n"
+			 "medium    : 0x%08X\n"
+			 "speed     : %d\n"
+			 "cable     : %s\n"
+			 "vendor ID : 0x%08X\n"
+			 "vendor    : %s\n", 
+			 param->confignr, (param->used) ? "y" : "n", 
+			 ({ char *s = "?";
+			 switch (param->state) {
+			 case RNDIS_UNINITIALIZED:
+				s = "RNDIS_UNINITIALIZED"; break;
+			 case RNDIS_INITIALIZED:
+				s = "RNDIS_INITIALIZED"; break;
+			 case RNDIS_DATA_INITIALIZED:
+				s = "RNDIS_DATA_INITIALIZED"; break;
+			}; s; }),
+			 param->medium, 
+			 (param->media_state) ? 0 : param->speed*100, 
+			 (param->media_state) ? "disconnected" : "connected",
+			 param->vendorID, param->vendorDescr);      
+	
+	len = out - page;
+	len -= off;
+	
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0)
+			return 0;
+	} else
+		len = count;
+	
+	*start = page + off;
+	return len;
+}
+
+int rndis_proc_write (struct file *file, const char *buffer, 
+		      unsigned long count, void *data)
+{
+	u32 speed = 0;
+	int i, fl_speed = 0;
+	
+	for (i = 0; i < count; i++) {
+		switch (*buffer) {
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			fl_speed = 1;
+			speed = speed*10 + *buffer - '0';
+			break;
+		case 'C':
+		case 'c':
+			rndis_signal_connect (((rndis_params *) data)
+				->confignr);
+			break;
+		case 'D':
+		case 'd':
+			rndis_signal_disconnect (((rndis_params *) data)
+				->confignr);
+			break;
+		default: 
+			if (fl_speed) ((rndis_params *) data)->speed = speed;
+			else DEBUG ("%c is not valid\n", *buffer);
+			break;
+		}
+		
+		buffer++;
+	}
+	
+	return count;
+}
+
+int __init rndis_init (void)
+{
+	u8 i;
+	char name [4];
+
+	/* FIXME this should probably be /proc/driver/rndis,
+	 * and only if debugging is enabled
+	 */
+	
+	if (!(rndis_connect_dir =  proc_mkdir ("rndis", NULL))) {
+		printk (KERN_ERR "%s: couldn't create /proc/rndis entry", 
+			__FUNCTION__);
+		return -EIO;
+	}
+	
+	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
+		sprintf (name, "%03d", i);
+		if (!(rndis_connect_state [i]
+				= create_proc_entry (name, 0660,
+						rndis_connect_dir))) 
+		{
+			DEBUG ("%s :remove entries", __FUNCTION__);
+			for (i--; i > 0; i--) {
+				sprintf (name, "%03d", i);
+				remove_proc_entry (name, rndis_connect_dir);
+			}
+			DEBUG ("\n");
+			
+			remove_proc_entry ("000", rndis_connect_dir);
+			remove_proc_entry ("rndis", NULL);
+			return -EIO;
+		}
+		rndis_connect_state [i]->nlink = 1;
+		rndis_connect_state [i]->write_proc = rndis_proc_write;
+		rndis_connect_state [i]->read_proc = rndis_proc_read;
+		rndis_connect_state [i]->data = (void *)
+				(rndis_per_dev_params + i);
+		rndis_per_dev_params [i].confignr = i;
+		rndis_per_dev_params [i].used = 0;
+		rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
+		rndis_per_dev_params [i].media_state
+				= NDIS_MEDIA_STATE_DISCONNECTED;
+		INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
+	}
+	
+	return 0;
+}
+
+void rndis_exit (void)
+{
+	u8 i;
+	char name [4];
+	
+	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
+		sprintf (name, "%03d", i);
+		remove_proc_entry (name, rndis_connect_dir);
+	}
+	remove_proc_entry ("rndis", NULL);
+	return;
+}
+
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/rndis.h linux-2.4.27-rc4/drivers/usb/gadget/rndis.h
--- linux-2.4.26/drivers/usb/gadget/rndis.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/rndis.h	2004-07-30 16:29:41.000000000 +0000
@@ -0,0 +1,348 @@
+/* 
+ * RNDIS	Definitions for Remote NDIS
+ * 
+ * Version:	$Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $
+ * 
+ * Authors:	Benedikt Spranger, Pengutronix
+ * 		Robert Schwebel, Pengutronix
+ * 
+ * 		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. 
+ * 
+ *		This software was originally developed in conformance with
+ *		Microsoft's Remote NDIS Specification License Agreement.
+ */
+
+#ifndef _LINUX_RNDIS_H
+#define _LINUX_RNDIS_H
+
+#include "ndis.h"
+
+#define RNDIS_MAXIMUM_FRAME_SIZE	1518
+#define RNDIS_MAX_TOTAL_SIZE		1558
+
+/* Remote NDIS Versions */
+#define RNDIS_MAJOR_VERSION		1
+#define RNDIS_MINOR_VERSION		0
+
+/* Status Values */
+#define RNDIS_STATUS_SUCCESS		0x00000000U	/* Success           */
+#define RNDIS_STATUS_FAILURE		0xC0000001U	/* Unspecified error */
+#define RNDIS_STATUS_INVALID_DATA	0xC0010015U	/* Invalid data      */
+#define RNDIS_STATUS_NOT_SUPPORTED	0xC00000BBU	/* Unsupported request */
+#define RNDIS_STATUS_MEDIA_CONNECT	0x4001000BU	/* Device connected  */
+#define RNDIS_STATUS_MEDIA_DISCONNECT	0x4001000CU	/* Device disconnected */
+/* For all not specified status messages:
+ * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx 
+ */
+
+/* Message Set for Connectionless (802.3) Devices */
+#define REMOTE_NDIS_INITIALIZE_MSG	0x00000002U	/* Initialize device */
+#define REMOTE_NDIS_HALT_MSG		0x00000003U
+#define REMOTE_NDIS_QUERY_MSG		0x00000004U
+#define REMOTE_NDIS_SET_MSG		0x00000005U
+#define REMOTE_NDIS_RESET_MSG		0x00000006U
+#define REMOTE_NDIS_INDICATE_STATUS_MSG	0x00000007U
+#define REMOTE_NDIS_KEEPALIVE_MSG	0x00000008U
+
+/* Message completion */
+#define REMOTE_NDIS_INITIALIZE_CMPLT	0x80000002U
+#define REMOTE_NDIS_QUERY_CMPLT		0x80000004U
+#define REMOTE_NDIS_SET_CMPLT		0x80000005U
+#define REMOTE_NDIS_RESET_CMPLT		0x80000006U
+#define REMOTE_NDIS_KEEPALIVE_CMPLT	0x80000008U
+
+/* Device Flags */
+#define RNDIS_DF_CONNECTIONLESS		0x00000001U
+#define RNDIS_DF_CONNECTION_ORIENTED	0x00000002U
+
+#define RNDIS_MEDIUM_802_3		0x00000000U
+
+/* from drivers/net/sk98lin/h/skgepnmi.h */
+#define OID_PNP_CAPABILITIES			0xFD010100
+#define OID_PNP_SET_POWER			0xFD010101
+#define OID_PNP_QUERY_POWER			0xFD010102
+#define OID_PNP_ADD_WAKE_UP_PATTERN		0xFD010103
+#define OID_PNP_REMOVE_WAKE_UP_PATTERN		0xFD010104
+#define OID_PNP_ENABLE_WAKE_UP			0xFD010106
+
+
+/* supported OIDs */
+static const u32 oid_supported_list [] = 
+{
+	/* the general stuff */
+	OID_GEN_SUPPORTED_LIST,
+	OID_GEN_HARDWARE_STATUS,
+	OID_GEN_MEDIA_SUPPORTED,
+	OID_GEN_MEDIA_IN_USE,
+	OID_GEN_MAXIMUM_FRAME_SIZE,
+	OID_GEN_LINK_SPEED,
+	OID_GEN_TRANSMIT_BLOCK_SIZE,
+	OID_GEN_RECEIVE_BLOCK_SIZE,
+	OID_GEN_VENDOR_ID,
+	OID_GEN_VENDOR_DESCRIPTION,
+	OID_GEN_VENDOR_DRIVER_VERSION,
+	OID_GEN_CURRENT_PACKET_FILTER,
+	OID_GEN_MAXIMUM_TOTAL_SIZE,
+	OID_GEN_MEDIA_CONNECT_STATUS,
+	OID_GEN_PHYSICAL_MEDIUM,
+#if 0
+	OID_GEN_RNDIS_CONFIG_PARAMETER,
+#endif
+	
+	/* the statistical stuff */
+	OID_GEN_XMIT_OK,
+	OID_GEN_RCV_OK,
+	OID_GEN_XMIT_ERROR,
+	OID_GEN_RCV_ERROR,
+	OID_GEN_RCV_NO_BUFFER,
+#ifdef	RNDIS_OPTIONAL_STATS
+	OID_GEN_DIRECTED_BYTES_XMIT,
+	OID_GEN_DIRECTED_FRAMES_XMIT,
+	OID_GEN_MULTICAST_BYTES_XMIT,
+	OID_GEN_MULTICAST_FRAMES_XMIT,
+	OID_GEN_BROADCAST_BYTES_XMIT,
+	OID_GEN_BROADCAST_FRAMES_XMIT,
+	OID_GEN_DIRECTED_BYTES_RCV,
+	OID_GEN_DIRECTED_FRAMES_RCV,
+	OID_GEN_MULTICAST_BYTES_RCV,
+	OID_GEN_MULTICAST_FRAMES_RCV,
+	OID_GEN_BROADCAST_BYTES_RCV,
+	OID_GEN_BROADCAST_FRAMES_RCV,
+	OID_GEN_RCV_CRC_ERROR,
+	OID_GEN_TRANSMIT_QUEUE_LENGTH,
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+    	/* mandatory 802.3 */
+	/* the general stuff */
+	OID_802_3_PERMANENT_ADDRESS,
+	OID_802_3_CURRENT_ADDRESS,
+	OID_802_3_MULTICAST_LIST,
+	OID_802_3_MAC_OPTIONS,
+	OID_802_3_MAXIMUM_LIST_SIZE,
+	
+	/* the statistical stuff */
+	OID_802_3_RCV_ERROR_ALIGNMENT,
+	OID_802_3_XMIT_ONE_COLLISION,
+	OID_802_3_XMIT_MORE_COLLISIONS,
+#ifdef	RNDIS_OPTIONAL_STATS
+	OID_802_3_XMIT_DEFERRED,
+	OID_802_3_XMIT_MAX_COLLISIONS,
+	OID_802_3_RCV_OVERRUN,
+	OID_802_3_XMIT_UNDERRUN,
+	OID_802_3_XMIT_HEARTBEAT_FAILURE,
+	OID_802_3_XMIT_TIMES_CRS_LOST,
+	OID_802_3_XMIT_LATE_COLLISIONS,
+#endif	/* RNDIS_OPTIONAL_STATS */
+
+#ifdef	RNDIS_PM
+	/* PM and wakeup are mandatory for USB: */
+
+	/* power management */
+	OID_PNP_CAPABILITIES,
+	OID_PNP_QUERY_POWER,
+	OID_PNP_SET_POWER,
+
+	/* wake up host */
+	OID_PNP_ENABLE_WAKE_UP,
+	OID_PNP_ADD_WAKE_UP_PATTERN,
+	OID_PNP_REMOVE_WAKE_UP_PATTERN,
+#endif
+};
+
+
+typedef struct rndis_init_msg_type 
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	MajorVersion;
+	u32	MinorVersion;
+	u32	MaxTransferSize;
+} rndis_init_msg_type;
+
+typedef struct rndis_init_cmplt_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	Status;
+	u32	MajorVersion;
+	u32	MinorVersion;
+	u32	DeviceFlags;
+	u32	Medium;
+	u32	MaxPacketsPerTransfer;
+	u32	MaxTransferSize;
+	u32	PacketAlignmentFactor;
+	u32	AFListOffset;
+	u32	AFListSize;
+} rndis_init_cmplt_type;
+
+typedef struct rndis_halt_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+} rndis_halt_msg_type;
+
+typedef struct rndis_query_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	OID;
+	u32	InformationBufferLength;
+	u32	InformationBufferOffset;
+	u32	DeviceVcHandle;
+} rndis_query_msg_type;
+
+typedef struct rndis_query_cmplt_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	Status;
+	u32	InformationBufferLength;
+	u32	InformationBufferOffset;
+} rndis_query_cmplt_type;
+
+typedef struct rndis_set_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	OID;
+	u32	InformationBufferLength;
+	u32	InformationBufferOffset;
+	u32	DeviceVcHandle;
+} rndis_set_msg_type;
+
+typedef struct rndis_set_cmplt_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	Status;
+} rndis_set_cmplt_type;
+
+typedef struct rndis_reset_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	Reserved;
+} rndis_reset_msg_type;
+
+typedef struct rndis_reset_cmplt_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	Status;
+	u32	AddressingReset;
+} rndis_reset_cmplt_type;
+
+typedef struct rndis_indicate_status_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	Status;
+	u32	StatusBufferLength;
+	u32	StatusBufferOffset;
+} rndis_indicate_status_msg_type;
+
+typedef struct rndis_keepalive_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+} rndis_keepalive_msg_type;
+
+typedef struct rndis_keepalive_cmplt_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	RequestID;
+	u32	Status;
+} rndis_keepalive_cmplt_type;
+
+struct rndis_packet_msg_type
+{
+	u32	MessageType;
+	u32	MessageLength;
+	u32	DataOffset;
+	u32	DataLength;
+	u32	OOBDataOffset;
+	u32	OOBDataLength;
+	u32	NumOOBDataElements;
+	u32	PerPacketInfoOffset;
+	u32	PerPacketInfoLength;
+	u32	VcHandle;
+	u32	Reserved;
+};
+
+struct rndis_config_parameter
+{
+	u32	ParameterNameOffset;
+	u32	ParameterNameLength;
+	u32	ParameterType;
+	u32	ParameterValueOffset;
+	u32	ParameterValueLength;
+};
+
+/* implementation specific */
+enum rndis_state
+{
+	RNDIS_UNINITIALIZED,
+	RNDIS_INITIALIZED,
+	RNDIS_DATA_INITIALIZED,
+};
+
+typedef struct rndis_resp_t
+{
+	struct list_head	list;
+	u8			*buf;
+	u32			length;
+	int			send;
+} rndis_resp_t;
+
+typedef struct rndis_params
+{
+	u8			confignr;
+	int			used;
+	enum rndis_state	state;
+	u32			filter;
+	u32			medium;
+	u32			speed;
+	u32			media_state;
+	const u8		*host_mac;
+	struct net_device 	*dev;
+	struct net_device_stats *stats;
+	u32			vendorID;
+	const char		*vendorDescr;
+	int 			(*ack) (struct net_device *);
+	struct list_head	resp_queue;
+} rndis_params;
+
+/* RNDIS Message parser and other useless functions */
+int  rndis_msg_parser (u8 configNr, u8 *buf);
+int  rndis_register (int (*rndis_control_ack) (struct net_device *));
+void rndis_deregister (int configNr);
+int  rndis_set_param_dev (u8 configNr, struct net_device *dev,
+			 struct net_device_stats *stats);
+int  rndis_set_param_vendor (u8 configNr, u32 vendorID, 
+			    const char *vendorDescr);
+int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
+void rndis_add_hdr (struct sk_buff *skb);
+int  rndis_rm_hdr (u8 *buf, u32 *length);
+u8   *rndis_get_next_response (int configNr, u32 *length);
+void rndis_free_response (int configNr, u8 *buf);
+
+int  rndis_signal_connect (int configNr);
+int  rndis_signal_disconnect (int configNr);
+int  rndis_state (int configNr);
+extern void rndis_set_host_mac (int configNr, const u8 *addr);
+
+int __init rndis_init (void);
+void rndis_exit (void);
+
+#endif  /* _LINUX_RNDIS_H */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/usbstring.c linux-2.4.27-rc4/drivers/usb/gadget/usbstring.c
--- linux-2.4.26/drivers/usb/gadget/usbstring.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/usbstring.c	2004-07-30 16:26:15.000000000 +0000
@@ -11,11 +11,12 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/string.h>
-#include <linux/version.h>
+#include <linux/init.h>
 
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/gadget/zero.c linux-2.4.27-rc4/drivers/usb/gadget/zero.c
--- linux-2.4.26/drivers/usb/gadget/zero.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/gadget/zero.c	2004-07-30 16:25:46.000000000 +0000
@@ -87,10 +87,12 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
+#include "gadget_chips.h"
+
 
 /*-------------------------------------------------------------------------*/
 
-#define DRIVER_VERSION		"Bastille Day 2003"
+#define DRIVER_VERSION		"St Patrick's Day 2004"
 
 static const char shortname [] = "zero";
 static const char longname [] = "Gadget Zero";
@@ -103,100 +105,12 @@ static const char loopback [] = "loop in
 /*
  * driver assumes self-powered hardware, and
  * has no way for users to trigger remote wakeup.
- */
-
-/*
- * hardware-specific configuration, controlled by which device
- * controller driver was configured.
- *
- * CHIP ... hardware identifier
- * DRIVER_VERSION_NUM ... alerts the host side driver to differences
- * EP_*_NAME ... which endpoints do we use for which purpose?
- * EP_*_NUM ... numbers for them (often limited by hardware)
  *
- * add other defines for other portability issues, like hardware that
- * for some reason doesn't handle full speed bulk maxpacket of 64.
+ * this version autoconfigures as much as possible,
+ * which is reasonable for most "bulk-only" drivers.
  */
-
-/*
- * DRIVER_VERSION_NUM 0x0000 (?):  Martin Diehl's ezusb an21/fx code
- */
-
-/*
- * NetChip 2280, PCI based.
- *
- * This has half a dozen configurable endpoints, four with dedicated
- * DMA channels to manage their FIFOs.  It supports high speed.
- * Those endpoints can be arranged in any desired configuration.
- */
-#ifdef	CONFIG_USB_GADGET_NET2280
-#define CHIP			"net2280"
-#define DRIVER_VERSION_NUM	0x0111
-static const char EP_OUT_NAME [] = "ep-a";
-#define EP_OUT_NUM	2
-static const char EP_IN_NAME [] = "ep-b";
-#define EP_IN_NUM	2
-#endif
-
-/*
- * PXA-2xx UDC:  widely used in second gen Linux-capable PDAs.
- *
- * This has fifteen fixed-function full speed endpoints, and it
- * can support all USB transfer types.
- *
- * These supports three or four configurations, with fixed numbers.
- * The hardware interprets SET_INTERFACE, net effect is that you
- * can't use altsettings or reset the interfaces independently.
- * So stick to a single interface.
- */
-#ifdef	CONFIG_USB_GADGET_PXA2XX
-#define CHIP			"pxa2xx"
-#define DRIVER_VERSION_NUM	0x0113
-static const char EP_OUT_NAME [] = "ep12out-bulk";
-#define EP_OUT_NUM	12
-static const char EP_IN_NAME [] = "ep11in-bulk";
-#define EP_IN_NUM	11
-#endif
-
-/*
- * SA-1100 UDC:  widely used in first gen Linux-capable PDAs.
- *
- * This has only two fixed function endpoints, which can only
- * be used for bulk (or interrupt) transfers.  (Plus control.)
- *
- * Since it can't flush its TX fifos without disabling the UDC,
- * the current configuration or altsettings can't change except
- * in special situations.  So this is a case of "choose it right
- * during enumeration" ...
- */
-#ifdef	CONFIG_USB_GADGET_SA1100
-#define CHIP			"sa1100"
-#define DRIVER_VERSION_NUM	0x0115
-static const char EP_OUT_NAME [] = "ep1out-bulk";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep2in-bulk";
-#define EP_IN_NUM	2
-#endif
-
-/*
- * Toshiba TC86C001 ("Goku-S") UDC
- *
- * This has three semi-configurable full speed bulk/interrupt endpoints.
- */
-#ifdef	CONFIG_USB_GADGET_GOKU
-#define CHIP			"goku"
-#define DRIVER_VERSION_NUM	0x0116
-static const char EP_OUT_NAME [] = "ep1-bulk";
-#define EP_OUT_NUM	1
-static const char EP_IN_NAME [] = "ep2-bulk";
-#define EP_IN_NUM	2
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#ifndef EP_OUT_NUM
-#	error Configure some USB peripheral controller driver!
-#endif
+static const char *EP_IN_NAME;		/* source */
+static const char *EP_OUT_NAME;		/* sink */
 
 /*-------------------------------------------------------------------------*/
 
@@ -214,6 +128,9 @@ struct zero_dev {
 	 */
 	u8			config;
 	struct usb_ep		*in_ep, *out_ep;
+
+	/* autoresume timer */
+	struct timer_list	resume;
 };
 
 #define xprintk(d,level,fmt,args...) \
@@ -221,20 +138,19 @@ struct zero_dev {
 		## args)
 
 #ifdef DEBUG
-#undef DEBUG
-#define DEBUG(dev,fmt,args...) \
+#define DBG(dev,fmt,args...) \
 	xprintk(dev , KERN_DEBUG , fmt , ## args)
 #else
-#define DEBUG(dev,fmt,args...) \
+#define DBG(dev,fmt,args...) \
 	do { } while (0)
 #endif /* DEBUG */
 
 #ifdef VERBOSE
-#define VDEBUG	DEBUG
+#define VDBG	DBG
 #else
-#define VDEBUG(dev,fmt,args...) \
+#define VDBG(dev,fmt,args...) \
 	do { } while (0)
-#endif /* DEBUG */
+#endif /* VERBOSE */
 
 #define ERROR(dev,fmt,args...) \
 	xprintk(dev , KERN_ERR , fmt , ## args)
@@ -270,6 +186,13 @@ MODULE_PARM_DESC (pattern, "0 for defaul
 MODULE_PARM (loopdefault, "b");
 MODULE_PARM_DESC (loopdefault, "true to have default config be loopback");
 
+/*
+ * if it's nonzero, autoresume says how many seconds to wait
+ * before trying to wake up the host after suspend.
+ */
+static unsigned autoresume = 0;
+MODULE_PARM (autoresume, "i");
+
 /*-------------------------------------------------------------------------*/
 
 /* Thanks to NetChip Technologies for donating this product ID.
@@ -310,14 +233,13 @@ device_desc = {
 
 	.idVendor =		__constant_cpu_to_le16 (DRIVER_VENDOR_NUM),
 	.idProduct =		__constant_cpu_to_le16 (DRIVER_PRODUCT_NUM),
-	.bcdDevice =		__constant_cpu_to_le16 (DRIVER_VERSION_NUM),
 	.iManufacturer =	STRING_MANUFACTURER,
 	.iProduct =		STRING_PRODUCT,
 	.iSerialNumber =	STRING_SERIAL,
 	.bNumConfigurations =	2,
 };
 
-static const struct usb_config_descriptor
+static struct usb_config_descriptor
 source_sink_config = {
 	.bLength =		sizeof source_sink_config,
 	.bDescriptorType =	USB_DT_CONFIG,
@@ -330,7 +252,7 @@ source_sink_config = {
 	.bMaxPower =		1,	/* self-powered */
 };
 
-static const struct usb_config_descriptor
+static struct usb_config_descriptor
 loopback_config = {
 	.bLength =		sizeof loopback_config,
 	.bDescriptorType =	USB_DT_CONFIG,
@@ -367,24 +289,22 @@ loopback_intf = {
 
 /* two full speed bulk endpoints; their use is config-dependent */
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_source_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_IN_NUM | USB_DIR_IN,
+	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
-static const struct usb_endpoint_descriptor
+static struct usb_endpoint_descriptor
 fs_sink_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
 
-	.bEndpointAddress =	EP_OUT_NUM,
+	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
-	.wMaxPacketSize =	__constant_cpu_to_le16 (64),
 };
 
 static const struct usb_descriptor_header *fs_source_sink_function [] = {
@@ -648,7 +568,7 @@ static void source_sink_complete (struct
 	case -ECONNABORTED: 		/* hardware forced ep reset */
 	case -ECONNRESET:		/* request dequeued */
 	case -ESHUTDOWN:		/* disconnect from host */
-		VDEBUG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
+		VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status,
 				req->actual, req->length);
 		if (ep == dev->out_ep)
 			check_read_data (dev, ep, req);
@@ -661,7 +581,7 @@ static void source_sink_complete (struct
 					 */
 	default:
 #if 1
-		DEBUG (dev, "%s complete --> %d, %d/%d\n", ep->name,
+		DBG (dev, "%s complete --> %d, %d/%d\n", ep->name,
 				status, req->actual, req->length);
 #endif
 	case -EREMOTEIO:		/* short read */
@@ -752,7 +672,7 @@ set_source_sink_config (struct zero_dev 
 		break;
 	}
 	if (result == 0)
-		DEBUG (dev, "buflen %d\n", buflen);
+		DBG (dev, "buflen %d\n", buflen);
 
 	/* caller is responsible for cleanup on error */
 	return result;
@@ -863,14 +783,14 @@ set_loopback_config (struct zero_dev *de
 				req->complete = loopback_complete;
 				result = usb_ep_queue (ep, req, GFP_ATOMIC);
 				if (result)
-					DEBUG (dev, "%s queue req --> %d\n",
+					DBG (dev, "%s queue req --> %d\n",
 							ep->name, result);
 			} else
 				result = -ENOMEM;
 		}
 	}
 	if (result == 0)
-		DEBUG (dev, "qlen %d, buflen %d\n", qlen, buflen);
+		DBG (dev, "qlen %d, buflen %d\n", qlen, buflen);
 
 	/* caller is responsible for cleanup on error */
 	return result;
@@ -883,7 +803,7 @@ static void zero_reset_config (struct ze
 	if (dev->config == 0)
 		return;
 
-	DEBUG (dev, "reset config\n");
+	DBG (dev, "reset config\n");
 
 	/* just disable endpoints, forcing completion of pending i/o.
 	 * all our completion handlers free their requests in this case.
@@ -918,13 +838,11 @@ zero_set_config (struct zero_dev *dev, u
 	if (number == dev->config)
 		return 0;
 
-#ifdef CONFIG_USB_GADGET_SA1100
-	if (dev->config) {
+	if (gadget_is_sa1100 (gadget) && dev->config) {
 		/* tx fifo is full, but we can't clear it...*/
 		INFO (dev, "can't change configurations\n");
 		return -ESPIPE;
 	}
-#endif
 	zero_reset_config (dev);
 
 	switch (number) {
@@ -968,7 +886,7 @@ zero_set_config (struct zero_dev *dev, u
 static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req)
 {
 	if (req->status || req->actual != req->length)
-		DEBUG ((struct zero_dev *) ep->driver_data,
+		DBG ((struct zero_dev *) ep->driver_data,
 				"setup complete --> %d, %d/%d\n",
 				req->status, req->actual, req->length);
 }
@@ -1116,7 +1034,7 @@ zero_setup (struct usb_gadget *gadget, c
 
 	default:
 unknown:
-		VDEBUG (dev,
+		VDBG (dev,
 			"unknown control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
@@ -1127,7 +1045,7 @@ unknown:
 		req->length = value;
 		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0) {
-			DEBUG (dev, "ep_queue --> %d\n", value);
+			DBG (dev, "ep_queue --> %d\n", value);
 			req->status = 0;
 			zero_setup_complete (gadget->ep0, req);
 		}
@@ -1157,6 +1075,19 @@ zero_disconnect (struct usb_gadget *gadg
 	 */
 }
 
+static void
+zero_autoresume (unsigned long _dev)
+{
+	struct zero_dev	*dev = (struct zero_dev *) _dev;
+	int		status;
+
+	/* normally the host would be woken up for something
+	 * more significant than just a timer firing...
+	 */
+	status = usb_gadget_wakeup (dev->gadget);
+	DBG (dev, "wakeup --> %d\n", status);
+}
+
 /*-------------------------------------------------------------------------*/
 
 static void
@@ -1164,11 +1095,12 @@ zero_unbind (struct usb_gadget *gadget)
 {
 	struct zero_dev		*dev = get_gadget_data (gadget);
 
-	DEBUG (dev, "unbind\n");
+	DBG (dev, "unbind\n");
 
 	/* we've already been disconnected ... no i/o is active */
 	if (dev->req)
 		free_ep_req (gadget->ep0, dev->req);
+	del_timer_sync (&dev->resume);
 	kfree (dev);
 	set_gadget_data (gadget, 0);
 }
@@ -1177,7 +1109,70 @@ static int
 zero_bind (struct usb_gadget *gadget)
 {
 	struct zero_dev		*dev;
+	struct usb_ep		*ep;
+
+	/* Bulk-only drivers like this one SHOULD be able to
+	 * autoconfigure on any sane usb controller driver,
+	 * but there may also be important quirks to address.
+	 */
+	usb_ep_autoconfig_reset (gadget);
+	ep = usb_ep_autoconfig (gadget, &fs_source_desc);
+	if (!ep) {
+autoconf_fail:
+		printk (KERN_ERR "%s: can't autoconfigure on %s\n",
+			shortname, gadget->name);
+		return -ENODEV;
+	}
+	EP_IN_NAME = ep->name;
+	ep->driver_data = ep;	/* claim */
+	
+	ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
+	if (!ep)
+		goto autoconf_fail;
+	EP_OUT_NAME = ep->name;
+	ep->driver_data = ep;	/* claim */
+
+
+	/*
+	 * DRIVER POLICY CHOICE:  you may want to do this differently.
+	 * One thing to avoid is reusing a bcdDevice revision code
+	 * with different host-visible configurations or behavior
+	 * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc
+	 */
+	if (gadget_is_net2280 (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201);
+	} else if (gadget_is_pxa (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0203);
+#if 0
+	} else if (gadget_is_sh(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0204);
+		/* SH has only one configuration; see "loopdefault" */
+		device_desc.bNumConfigurations = 1;
+		/* FIXME make 1 == default.bConfigurationValue */
+#endif
+	} else if (gadget_is_sa1100 (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0205);
+	} else if (gadget_is_goku (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0206);
+	} else if (gadget_is_mq11xx (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
+	} else if (gadget_is_omap (gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
+	} else {
+		/* gadget zero is so simple (for now, no altsettings) that
+		 * it SHOULD NOT have problems with bulk-capable hardware.
+		 * so warn about unrcognized controllers, don't panic.
+		 *
+		 * things like configuration and altsetting numbering
+		 * can need hardware-specific attention though.
+		 */
+		printk (KERN_WARNING "%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x9999);
+	}
 
+
+	/* ok, we made sense of the hardware ... */
 	dev = kmalloc (sizeof *dev, SLAB_KERNEL);
 	if (!dev)
 		return -ENOMEM;
@@ -1208,6 +1203,16 @@ zero_bind (struct usb_gadget *gadget)
 	hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
 #endif
 
+	usb_gadget_set_selfpowered (gadget);
+
+	init_timer (&dev->resume);
+	dev->resume.function = zero_autoresume;
+	dev->resume.data = (unsigned long) dev;
+	if (autoresume) {
+		source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+		loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
 	gadget->ep0->driver_data = dev;
 
 	INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname);
@@ -1227,6 +1232,33 @@ enomem:
 
 /*-------------------------------------------------------------------------*/
 
+static void
+zero_suspend (struct usb_gadget *gadget)
+{
+	struct zero_dev		*dev = get_gadget_data (gadget);
+
+	if (gadget->speed == USB_SPEED_UNKNOWN)
+		return;
+
+	if (autoresume) {
+		mod_timer (&dev->resume, jiffies + (HZ * autoresume));
+		DBG (dev, "suspend, wakeup in %d seconds\n", autoresume);
+	} else
+		DBG (dev, "suspend\n");
+}
+
+static void
+zero_resume (struct usb_gadget *gadget)
+{
+	struct zero_dev		*dev = get_gadget_data (gadget);
+
+	DBG (dev, "resume\n");
+	del_timer (&dev->resume);
+}
+
+
+/*-------------------------------------------------------------------------*/
+
 static struct usb_gadget_driver zero_driver = {
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 	.speed		= USB_SPEED_HIGH,
@@ -1240,6 +1272,9 @@ static struct usb_gadget_driver zero_dri
 	.setup		= zero_setup,
 	.disconnect	= zero_disconnect,
 
+	.suspend	= zero_suspend,
+	.resume		= zero_resume,
+
 	.driver 	= {
 		.name		= (char *) shortname,
 		// .shutdown = ...
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/hiddev.c linux-2.4.27-rc4/drivers/usb/hiddev.c
--- linux-2.4.26/drivers/usb/hiddev.c	2004-04-14 13:05:32.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/hiddev.c	2004-07-30 16:27:49.000000000 +0000
@@ -433,7 +433,9 @@ static int hiddev_ioctl(struct inode *in
 		dinfo.product = dev->descriptor.idProduct;
 		dinfo.version = dev->descriptor.bcdDevice;
 		dinfo.num_applications = hid->maxapplication;
-		return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
+		if (copy_to_user((void *) arg, &dinfo, sizeof(dinfo)))
+			return -EFAULT;
+		return 0;
 
 	case HIDIOCGFLAG:
 		return put_user(list->flags, (int *) arg);
@@ -522,7 +524,9 @@ static int hiddev_ioctl(struct inode *in
 
 		rinfo.num_fields = report->maxfield;
 
-		return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
+		if (copy_to_user((void *) arg, &rinfo, sizeof(rinfo)))
+			return -EFAULT;
+		return 0;
 
 	case HIDIOCGFIELDINFO:
 		if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
@@ -552,7 +556,9 @@ static int hiddev_ioctl(struct inode *in
 		finfo.unit_exponent = field->unit_exponent;
 		finfo.unit = field->unit;
 
-		return copy_to_user((void *) arg, &finfo, sizeof(finfo));
+		if (copy_to_user((void *) arg, &finfo, sizeof(finfo)))
+			return -EFAULT;
+		return 0;
 
 	case HIDIOCGUCODE:
 		if (copy_from_user(uref, (void *) arg, sizeof(*uref)))
@@ -572,7 +578,9 @@ static int hiddev_ioctl(struct inode *in
 
 		uref->usage_code = field->usage[uref->usage_index].hid;
 
-		return 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:
@@ -656,7 +664,9 @@ static int hiddev_ioctl(struct inode *in
 		cinfo.usage = hid->collection[cinfo.index].usage;
 		cinfo.level = hid->collection[cinfo.index].level;
 
-		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
+		if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo)))
+			return -EFAULT;
+		return 0;
 
 	default:
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/host/ehci-hcd.c linux-2.4.27-rc4/drivers/usb/host/ehci-hcd.c
--- linux-2.4.26/drivers/usb/host/ehci-hcd.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/host/ehci-hcd.c	2004-07-30 16:28:32.000000000 +0000
@@ -291,7 +291,7 @@ static int bios_handoff (struct ehci_hcd
 		int msec = 500;
 
 		/* request handoff to OS */
-		cap &= 1 << 24;
+		cap |= 1 << 24;
 		pci_write_config_dword (ehci->hcd.pdev, where, cap);
 
 		/* and wait a while for it to happen */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/host/ehci-sched.c linux-2.4.27-rc4/drivers/usb/host/ehci-sched.c
--- linux-2.4.26/drivers/usb/host/ehci-sched.c	2004-04-14 13:05:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/host/ehci-sched.c	2004-07-30 16:27:19.000000000 +0000
@@ -402,7 +402,7 @@ static int qh_schedule (struct ehci_hcd 
 		qh->start = frame;
 
 		/* reset S-frame and (maybe) C-frame masks */
-		qh->hw_info2 &= ~0xffff;
+		qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff);
 		qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
 	} else
 		dbg ("reused previous qh %p schedule", qh);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/printer.c linux-2.4.27-rc4/drivers/usb/printer.c
--- linux-2.4.26/drivers/usb/printer.c	2004-04-14 13:05:33.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/printer.c	2004-07-30 16:26:14.000000000 +0000
@@ -1,9 +1,9 @@
 /*
- * printer.c  Version 0.11
+ * printer.c  Version 0.13
  *
  * Copyright (c) 1999 Michael Gee	<michael@linuxspecific.com>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
- * Copyright (c) 2000 Randy Dunlap	<randy.dunlap@intel.com>
+ * Copyright (c) 2000 Randy Dunlap	<rddunlap@osdl.org>
  * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  # Copyright (c) 2001 Pete Zaitcev	<zaitcev@redhat.com>
  # Copyright (c) 2001 David Paschal	<paschal@rcsis.com>
@@ -222,6 +222,7 @@ static int usblp_select_alts(struct usbl
 static int usblp_set_protocol(struct usblp *usblp, int protocol);
 static int usblp_cache_device_id_string(struct usblp *usblp);
 
+static DECLARE_MUTEX(usblp_sem);	/* locks the existence of usblp's. */
 
 /*
  * Functions for usblp control messages.
@@ -229,11 +230,21 @@ static int usblp_cache_device_id_string(
 
 static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
 {
-	int retval = usb_control_msg(usblp->dev,
+	int retval;
+	int index = usblp->ifnum;
+
+	/* High byte has the interface index.
+	   Low byte has the alternate setting.
+	 */
+	if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) {
+	  index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting;
+	}
+
+	retval = usb_control_msg(usblp->dev,
 		dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
-		request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
-	dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
-		request, !!dir, recip, value, len, retval);
+		request, type | dir | recip, value, index, buf, len, USBLP_WRITE_TIMEOUT);
+	dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d",
+		request, !!dir, recip, value, index, len, retval);
 	return retval < 0 ? retval : 0;
 }
 
@@ -332,7 +343,7 @@ static int usblp_open(struct inode *inod
 	if (minor < 0 || minor >= USBLP_MINORS)
 		return -ENODEV;
 
-	lock_kernel();
+	down (&usblp_sem);
 	usblp  = usblp_table[minor];
 
 	retval = -ENODEV;
@@ -374,7 +385,7 @@ static int usblp_open(struct inode *inod
 		}
 	}
 out:
-	unlock_kernel();
+	up (&usblp_sem);
 	return retval;
 }
 
@@ -404,15 +415,13 @@ static int usblp_release(struct inode *i
 {
 	struct usblp *usblp = file->private_data;
 
-	down (&usblp->sem);
-	lock_kernel();
+	down (&usblp_sem);
 	usblp->used = 0;
 	if (usblp->present) {
 		usblp_unlink_urbs(usblp);
-		up(&usblp->sem);
 	} else 		/* finish cleanup from disconnect */
 		usblp_cleanup (usblp);
-	unlock_kernel();
+	up (&usblp_sem);
 	return 0;
 }
 
@@ -748,6 +757,7 @@ static ssize_t usblp_read(struct file *f
 			usblp->minor, usblp->readurb->status);
 		usblp->readurb->dev = usblp->dev;
  		usblp->readcount = 0;
+		usblp->rcomplete = 0;
 		if (usb_submit_urb(usblp->readurb) < 0)
 			dbg("error submitting urb");
 		count = -EIO;
@@ -1112,17 +1122,16 @@ static void usblp_disconnect(struct usb_
 		BUG ();
 	}
 
+	down (&usblp_sem);
 	down (&usblp->sem);
-	lock_kernel();
 	usblp->present = 0;
 
 	usblp_unlink_urbs(usblp);
+	up (&usblp->sem);
 
 	if (!usblp->used)
 		usblp_cleanup (usblp);
-	else 	/* cleanup later, on release */
-		up (&usblp->sem);
-	unlock_kernel();
+	up (&usblp_sem);
 }
 
 static struct usb_device_id usblp_ids [] = {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/ftdi_sio.c linux-2.4.27-rc4/drivers/usb/serial/ftdi_sio.c
--- linux-2.4.26/drivers/usb/serial/ftdi_sio.c	2004-04-14 13:05:34.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/ftdi_sio.c	2004-07-30 16:30:23.000000000 +0000
@@ -17,6 +17,9 @@
  * See http://ftdi-usb-sio.sourceforge.net for upto date testing info
  *	and extra documentation
  *
+ * (10/Mar/2004) Jan Capek
+ *      Added PID's for ICD-U20/ICD-U40 - incircuit PIC debuggers from CCS Inc.
+ *
  * (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.
@@ -428,6 +431,8 @@ static struct usb_device_id id_table_FT2
 	{ 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) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ }						/* Terminating entry */
 };
 
@@ -526,6 +531,8 @@ static __devinitdata struct usb_device_i
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_3) },
 	{ USB_DEVICE(FTDI_VID, PROTEGO_SPECIAL_4) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
 	{ }						/* Terminating entry */
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/ftdi_sio.h linux-2.4.27-rc4/drivers/usb/serial/ftdi_sio.h
--- linux-2.4.26/drivers/usb/serial/ftdi_sio.h	2004-04-14 13:05:34.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/ftdi_sio.h	2004-07-30 16:30:49.000000000 +0000
@@ -165,6 +165,11 @@
 #define PROTEGO_SPECIAL_3	0xFC72	/* special/unknown device */
 #define PROTEGO_SPECIAL_4	0xFC73	/* special/unknown device */ 
 
+/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */
+/* unit for PIC16's/PIC18's */
+#define FTDI_CCSICDU20_0_PID  0xF9D0     
+#define FTDI_CCSICDU40_1_PID  0xF9D1     
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/io_edgeport.c linux-2.4.27-rc4/drivers/usb/serial/io_edgeport.c
--- linux-2.4.26/drivers/usb/serial/io_edgeport.c	2004-04-14 13:05:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/io_edgeport.c	2004-07-30 16:25:17.000000000 +0000
@@ -1913,6 +1913,7 @@ static int edge_ioctl (struct usb_serial
 
 		case TIOCGICOUNT:
 			cnow = edge_port->icount;
+			memset(&icount, 0, sizeof(icount));
 			icount.cts = cnow.cts;
 			icount.dsr = cnow.dsr;
 			icount.rng = cnow.rng;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/ipaq.c linux-2.4.27-rc4/drivers/usb/serial/ipaq.c
--- linux-2.4.26/drivers/usb/serial/ipaq.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/ipaq.c	2004-07-30 16:28:59.000000000 +0000
@@ -188,6 +188,7 @@ static int ipaq_open(struct usb_serial_p
 	port->private = (void *)priv;
 	priv->active = 0;
 	priv->queue_len = 0;
+	priv->free_len = 0;
 	INIT_LIST_HEAD(&priv->queue);
 	INIT_LIST_HEAD(&priv->freelist);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/mct_u232.c linux-2.4.27-rc4/drivers/usb/serial/mct_u232.c
--- linux-2.4.26/drivers/usb/serial/mct_u232.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/mct_u232.c	2004-07-30 16:29:43.000000000 +0000
@@ -169,7 +169,8 @@ static struct usb_serial_device_type mct
 
 
 struct mct_u232_private {
-	unsigned long	     control_state; /* Modem Line Setting (TIOCM) */
+	spinlock_t lock;
+	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
 	unsigned char        last_lcr;      /* Line Control Register */
 	unsigned char	     last_lsr;      /* Line Status Register */
 	unsigned char	     last_msr;      /* Modem Status Register */
@@ -181,25 +182,49 @@ struct mct_u232_private {
 
 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
 
+/*
+ * Later day 2.6.0-test kernels have new baud rates like B230400 which
+ * we do not know how to support. We ignore them for the moment.
+ * XXX Rate-limit the error message, it's user triggerable.
+ */
 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
 	if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
 	  || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
 		switch (value) {
-			case    300: return 0x01;
-			case    600: return 0x02; /* this one not tested */
-			case   1200: return 0x03;
-			case   2400: return 0x04;
-			case   4800: return 0x06;
-			case   9600: return 0x08;
-			case  19200: return 0x09;
-			case  38400: return 0x0a;
-			case  57600: return 0x0b;
-			case 115200: return 0x0c;
-			default:     return -1; /* normally not reached */
+		case    B300: return 0x01;
+		case    B600: return 0x02; /* this one not tested */
+		case   B1200: return 0x03;
+		case   B2400: return 0x04;
+		case   B4800: return 0x06;
+		case   B9600: return 0x08;
+		case  B19200: return 0x09;
+		case  B38400: return 0x0a;
+		case  B57600: return 0x0b;
+		case B115200: return 0x0c;
+		default:
+			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
+			    " using default of B9600", value);
+			return 0x08;
+		}
+	} else {
+		switch (value) {
+		case    B300: value =     300;
+		case    B600: value =     600;
+		case   B1200: value =    1200;
+		case   B2400: value =    2400;
+		case   B4800: value =    4800;
+		case   B9600: value =    9600;
+		case  B19200: value =   19200;
+		case  B38400: value =   38400;
+		case  B57600: value =   57600;
+		case B115200: value =  115200;
+		default:
+			err("MCT USB-RS232: unsupported baudrate request 0x%x,"
+			    " using default of B9600", value);
+			value = 9600;
 		}
+		return 115200/value;
 	}
-	else
-		return MCT_U232_BAUD_RATE(value);
 }
 
 static int mct_u232_set_baud_rate(struct usb_serial *serial, int value)
@@ -207,7 +232,9 @@ static int mct_u232_set_baud_rate(struct
 	unsigned int divisor;
         int rc;
         unsigned char zero_byte = 0;
+
 	divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value));
+
         rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                              MCT_U232_SET_BAUD_RATE_REQUEST,
 			     MCT_U232_SET_REQUEST_TYPE,
@@ -215,7 +242,7 @@ static int mct_u232_set_baud_rate(struct
 			     WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set BAUD RATE %d failed (error = %d)", value, rc);
-	dbg("set_baud_rate: value: %d, divisor: 0x%x", value, divisor);
+	dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor);
 
 	/* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which
 	   always sends two extra USB 'device request' messages after the
@@ -263,7 +290,7 @@ static int mct_u232_set_line_ctrl(struct
 } /* mct_u232_set_line_ctrl */
 
 static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
-				   unsigned long control_state)
+				   unsigned int control_state)
 {
         int rc;
 	unsigned char mcr = MCT_U232_MCR_NONE;
@@ -280,7 +307,7 @@ static int mct_u232_set_modem_ctrl(struc
 			     WDR_TIMEOUT);
 	if (rc < 0)
 		err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc);
-	dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr);
+	dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
 
         return rc;
 } /* mct_u232_set_modem_ctrl */
@@ -301,7 +328,7 @@ static int mct_u232_get_modem_stat(struc
         return rc;
 } /* mct_u232_get_modem_stat */
 
-static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr)
+static void mct_u232_msr_to_state(unsigned int *control_state, unsigned char msr)
 {
  	/* Translate Control Line states */
 	if (msr & MCT_U232_MSR_DSR)
@@ -320,7 +347,7 @@ static void mct_u232_msr_to_state(unsign
 		*control_state |=  TIOCM_CD;
 	else
 		*control_state &= ~TIOCM_CD;
- 	dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state);
+ 	dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state);
 } /* mct_u232_msr_to_state */
 
 /*
@@ -330,20 +357,32 @@ static void mct_u232_msr_to_state(unsign
 static int mct_u232_startup (struct usb_serial *serial)
 {
 	struct mct_u232_private *priv;
+	struct usb_serial_port *port, *rport;
 
 	/* allocate the private data structure */
-	serial->port->private = kmalloc(sizeof(struct mct_u232_private),
-					GFP_KERNEL);
-	if (!serial->port->private)
-		return (-1); /* error */
-	priv = (struct mct_u232_private *)serial->port->private;
+	priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 	/* set initial values for control structures */
+	spin_lock_init(&priv->lock);
 	priv->control_state = 0;
 	priv->last_lsr = 0;
 	priv->last_msr = 0;
-
+	serial->port->private = priv;
+ 
 	init_waitqueue_head(&serial->port->write_wait);
-	
+
+	/* Puh, that's dirty */
+	port = &serial->port[0];
+	rport = &serial->port[1];
+	if (port->read_urb) {
+		/* No unlinking, it wasn't submitted yet. */
+		usb_free_urb(port->read_urb);
+	}
+	port->read_urb = rport->interrupt_in_urb;
+	rport->interrupt_in_urb = NULL;
+	port->read_urb->context = port;
+
 	return (0);
 } /* mct_u232_startup */
 
@@ -354,7 +393,6 @@ static void mct_u232_shutdown (struct us
 	
 	dbg("%s", __FUNCTION__);
 
-	/* stop reads and writes on all ports */
 	for (i=0; i < serial->num_ports; ++i) {
 		/* My special items, the standard routines free my urbs */
 		if (serial->port[i].private)
@@ -367,6 +405,10 @@ static int  mct_u232_open (struct usb_se
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
 	int retval = 0;
+	unsigned int control_state;
+	unsigned long flags;
+	unsigned char last_lcr;
+	unsigned char last_msr;
 
 	dbg("%s port %d", __FUNCTION__, port->number);
 
@@ -383,29 +425,27 @@ static int  mct_u232_open (struct usb_se
 	 * sure if this is really necessary. But it should not harm
 	 * either.
 	 */
+	spin_lock_irqsave(&priv->lock, flags);
 	if (port->tty->termios->c_cflag & CBAUD)
 		priv->control_state = TIOCM_DTR | TIOCM_RTS;
 	else
 		priv->control_state = 0;
-	mct_u232_set_modem_ctrl(serial, priv->control_state);
 	
 	priv->last_lcr = (MCT_U232_DATA_BITS_8 | 
 			  MCT_U232_PARITY_NONE |
 			  MCT_U232_STOP_BITS_1);
-	mct_u232_set_line_ctrl(serial, priv->last_lcr);
+	control_state = priv->control_state;
+	last_lcr = priv->last_lcr;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	mct_u232_set_modem_ctrl(serial, control_state);
+	mct_u232_set_line_ctrl(serial, last_lcr);
 
 	/* Read modem status and update control state */
-	mct_u232_get_modem_stat(serial, &priv->last_msr);
+	mct_u232_get_modem_stat(serial, &last_msr);
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->last_msr = last_msr;
 	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
-
-	{
-		/* Puh, that's dirty */
-		struct usb_serial_port *rport;	
-		rport = &serial->port[1];
-		rport->tty = port->tty;
-		rport->private = port->private;
-		port->read_urb = rport->interrupt_in_urb;
-	}
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	port->read_urb->dev = port->serial->dev;
 	retval = usb_submit_urb(port->read_urb);
@@ -551,6 +591,7 @@ static void mct_u232_read_int_callback (
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
 
         dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -587,6 +628,7 @@ static void mct_u232_read_int_callback (
 	 * The interrupt-in pipe signals exceptional conditions (modem line
 	 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
 	 */
+	spin_lock_irqsave(&priv->lock, flags);
 	priv->last_msr = data[MCT_U232_MSR_INDEX];
 	
 	/* Record Control Line states */
@@ -617,6 +659,7 @@ static void mct_u232_read_int_callback (
 		}
 	}
 #endif
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* INT urbs are automatically re-submitted */
 } /* mct_u232_read_int_callback */
@@ -628,125 +671,113 @@ static void mct_u232_set_termios (struct
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
 	unsigned int iflag = port->tty->termios->c_iflag;
-	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int cflag = port->tty->termios->c_cflag;
 	unsigned int old_cflag = old_termios->c_cflag;
-	
+	unsigned long flags;
+	unsigned int control_state, new_state;
+	unsigned char last_lcr;
+
+	/* get a local copy of the current port settings */
+	spin_lock_irqsave(&priv->lock, flags);
+	control_state = priv->control_state;
+	spin_unlock_irqrestore(&priv->lock, flags);
+	last_lcr = 0;
+
 	/*
-	 * Update baud rate
+	 * Update baud rate.
+	 * Do not attempt to cache old rates and skip settings,
+	 * disconnects screw such tricks up completely.
+	 * Premature optimization is the root of all evil.
 	 */
-	if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
-	        /* reassert DTR and (maybe) RTS on transition from B0 */
-		if( (old_cflag & CBAUD) == B0 ) {
-			dbg("%s: baud was B0", __FUNCTION__);
-			priv->control_state |= TIOCM_DTR;
-			/* don't set RTS if using hardware flow control */
-			if (!(old_cflag & CRTSCTS)) {
-				priv->control_state |= TIOCM_RTS;
-			}
-			mct_u232_set_modem_ctrl(serial, priv->control_state);
-		}
-		
-		switch(cflag & CBAUD) {
-		case B0: /* handled below */
-			break;
-		case B300: mct_u232_set_baud_rate(serial, 300);
-			break;
-		case B600: mct_u232_set_baud_rate(serial, 600);
-			break;
-		case B1200: mct_u232_set_baud_rate(serial, 1200);
-			break;
-		case B2400: mct_u232_set_baud_rate(serial, 2400);
-			break;
-		case B4800: mct_u232_set_baud_rate(serial, 4800);
-			break;
-		case B9600: mct_u232_set_baud_rate(serial, 9600);
-			break;
-		case B19200: mct_u232_set_baud_rate(serial, 19200);
-			break;
-		case B38400: mct_u232_set_baud_rate(serial, 38400);
-			break;
-		case B57600: mct_u232_set_baud_rate(serial, 57600);
-			break;
-		case B115200: mct_u232_set_baud_rate(serial, 115200);
-			break;
-		default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");
-			mct_u232_set_baud_rate(serial, 9600); break;
-		}
-		if ((cflag & CBAUD) == B0 ) {
-			dbg("%s: baud is B0", __FUNCTION__);
-			/* Drop RTS and DTR */
-			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-        		mct_u232_set_modem_ctrl(serial, priv->control_state);
-		}
+
+        /* reassert DTR and (maybe) RTS on transition from B0 */
+	if ((old_cflag & CBAUD) == B0) {
+		dbg("%s: baud was B0", __FUNCTION__);
+		control_state |= TIOCM_DTR;
+		/* don't set RTS if using hardware flow control */
+		if (!(old_cflag & CRTSCTS)) {
+			control_state |= TIOCM_RTS;
+		}
+		mct_u232_set_modem_ctrl(serial, control_state);
+	}
+
+	mct_u232_set_baud_rate(serial, cflag & CBAUD);
+
+	if ((cflag & CBAUD) == B0 ) {
+		dbg("%s: baud is B0", __FUNCTION__);
+		/* Drop RTS and DTR */
+		control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+       		mct_u232_set_modem_ctrl(serial, control_state);
 	}
 
 	/*
 	 * Update line control register (LCR)
 	 */
-	if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
-	    || (cflag & CSIZE) != (old_cflag & CSIZE)
-	    || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
-		
 
-		priv->last_lcr = 0;
+	/* set the parity */
+	if (cflag & PARENB)
+		last_lcr |= (cflag & PARODD) ?
+			MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
+	else
+		last_lcr |= MCT_U232_PARITY_NONE;
 
-		/* set the parity */
-		if (cflag & PARENB)
-			priv->last_lcr |= (cflag & PARODD) ?
-				MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;
-		else
-			priv->last_lcr |= MCT_U232_PARITY_NONE;
+	/* set the number of data bits */
+	switch (cflag & CSIZE) {
+	case CS5:
+		last_lcr |= MCT_U232_DATA_BITS_5; break;
+	case CS6:
+		last_lcr |= MCT_U232_DATA_BITS_6; break;
+	case CS7:
+		last_lcr |= MCT_U232_DATA_BITS_7; break;
+	case CS8:
+		last_lcr |= MCT_U232_DATA_BITS_8; break;
+	default:
+		err("CSIZE was not CS5-CS8, using default of 8");
+		last_lcr |= MCT_U232_DATA_BITS_8;
+		break;
+	}
 
-		/* set the number of data bits */
-		switch (cflag & CSIZE) {
-		case CS5:
-			priv->last_lcr |= MCT_U232_DATA_BITS_5; break;
-		case CS6:
-			priv->last_lcr |= MCT_U232_DATA_BITS_6; break;
-		case CS7:
-			priv->last_lcr |= MCT_U232_DATA_BITS_7; break;
-		case CS8:
-			priv->last_lcr |= MCT_U232_DATA_BITS_8; break;
-		default:
-			err("CSIZE was not CS5-CS8, using default of 8");
-			priv->last_lcr |= MCT_U232_DATA_BITS_8;
-			break;
-		}
+	/* set the number of stop bits */
+	last_lcr |= (cflag & CSTOPB) ?
+		MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
 
-		/* set the number of stop bits */
-		priv->last_lcr |= (cflag & CSTOPB) ?
-			MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;
+	mct_u232_set_line_ctrl(serial, last_lcr);
 
-		mct_u232_set_line_ctrl(serial, priv->last_lcr);
-	}
-	
 	/*
 	 * Set flow control: well, I do not really now how to handle DTR/RTS.
 	 * Just do what we have seen with SniffUSB on Win98.
 	 */
-	if( (iflag & IXOFF) != (old_iflag & IXOFF)
-	    || (iflag & IXON) != (old_iflag & IXON)
-	    ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
-		
-		/* Drop DTR/RTS if no flow control otherwise assert */
-		if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
-			priv->control_state |= TIOCM_DTR | TIOCM_RTS;
-		else
-			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-		mct_u232_set_modem_ctrl(serial, priv->control_state);
+	/* Drop DTR/RTS if no flow control otherwise assert */
+	new_state = control_state;
+	if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS))
+		new_state |= TIOCM_DTR | TIOCM_RTS;
+	else
+		new_state &= ~(TIOCM_DTR | TIOCM_RTS);
+	if (new_state != control_state) {
+		mct_u232_set_modem_ctrl(serial, control_state);
+		control_state = new_state;
 	}
-} /* mct_u232_set_termios */
 
+	/* save off the modified port settings */
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->control_state = control_state;
+	priv->last_lcr = last_lcr;
+	spin_unlock_irqrestore(&priv->lock, flags);
+} /* mct_u232_set_termios */
 
 static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
 {
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
-	unsigned char lcr = priv->last_lcr;
+	unsigned char lcr;
+	unsigned long flags;
 
 	dbg("%sstate=%d", __FUNCTION__, break_state);
 
+	spin_lock_irqsave(&priv->lock, flags);
+	lcr = priv->last_lcr;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	if (break_state)
 		lcr |= MCT_U232_SET_BREAK;
 
@@ -760,7 +791,8 @@ static int mct_u232_ioctl (struct usb_se
 	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
 	int mask;
-	
+	unsigned long flags;
+
 	dbg("%scmd=0x%x", __FUNCTION__, cmd);
 
 	/* Based on code from acm.c and others */
@@ -775,6 +807,7 @@ static int mct_u232_ioctl (struct usb_se
 		if (get_user(mask, (unsigned long *) arg))
 			return -EFAULT;
 
+		spin_lock_irqsave(&priv->lock, flags);
 		if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {
 			/* RTS needs set */
 			if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||
@@ -792,6 +825,7 @@ static int mct_u232_ioctl (struct usb_se
 			else
 				priv->control_state &= ~TIOCM_DTR;
 		}
+		spin_unlock_irqrestore(&priv->lock, flags);
 		mct_u232_set_modem_ctrl(serial, priv->control_state);
 		break;
 					
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/pl2303.c linux-2.4.27-rc4/drivers/usb/serial/pl2303.c
--- linux-2.4.26/drivers/usb/serial/pl2303.c	2004-04-14 13:05:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/pl2303.c	2004-07-30 16:28:21.000000000 +0000
@@ -107,6 +107,7 @@ MODULE_DEVICE_TABLE (usb, id_table);
 #define VENDOR_READ_REQUEST		0x01
 
 #define UART_STATE			0x08
+#define UART_STATE_TRANSIENT_MASK	0x74
 #define UART_DCD			0x01
 #define UART_DSR			0x02
 #define UART_BREAK_ERROR		0x04
@@ -198,6 +199,9 @@ static int pl2303_write (struct usb_seri
 
 	dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
 
+	if (!count)
+		return count;
+
 	if (port->write_urb->status == -EINPROGRESS) {
 		dbg("%s - already writing", __FUNCTION__);
 		return 0;
@@ -648,7 +652,7 @@ static void pl2303_break_ctl (struct usb
 		state = BREAK_OFF;
 	else
 		state = BREAK_ON;
-	dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__);
+	dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
 	result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
 				  BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
@@ -678,6 +682,7 @@ static void pl2303_read_int_callback (st
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
 	unsigned long flags;
+	u8 uart_state;
 
 	dbg("%s (%d)", __FUNCTION__, port->number);
 
@@ -708,8 +713,10 @@ static void pl2303_read_int_callback (st
 		return;
 
 	/* Save off the uart status for others to look at */
+	uart_state = data[UART_STATE];
 	spin_lock_irqsave(&priv->lock, flags);
-	priv->line_status = data[UART_STATE];
+	uart_state |= (priv->line_status & UART_STATE_TRANSIENT_MASK);
+	priv->line_status = uart_state;
 	spin_unlock_irqrestore(&priv->lock, flags);
 	wake_up_interruptible (&priv->delta_msr_wait);
 
@@ -767,7 +774,9 @@ static void pl2303_read_bulk_callback (s
 
 	spin_lock_irqsave(&priv->lock, flags);
 	status = priv->line_status;
+	priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
 	spin_unlock_irqrestore(&priv->lock, flags);
+	wake_up_interruptible (&priv->delta_msr_wait); //AF from 2.6
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/usb-serial.h linux-2.4.27-rc4/drivers/usb/serial/usb-serial.h
--- linux-2.4.26/drivers/usb/serial/usb-serial.h	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/usb-serial.h	2004-07-30 16:32:23.000000000 +0000
@@ -111,6 +111,8 @@ struct usb_serial_port {
 	int			bulk_out_size;
 	struct urb *		write_urb;
 	__u8			bulk_out_endpointAddress;
+	char			write_busy;	/* URB is active */
+	int			write_backlog;	/* Fifo used */
 
 	wait_queue_head_t	write_wait;
 	struct tq_struct	tqueue;
@@ -161,6 +163,7 @@ struct usb_serial {
 	__u16				product;
 	struct usb_serial_port		port[MAX_NUM_PORTS];
 	void *				private;
+	int				ref;
 };
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/usbserial.c linux-2.4.27-rc4/drivers/usb/serial/usbserial.c
--- linux-2.4.26/drivers/usb/serial/usbserial.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/usbserial.c	2004-07-30 16:27:45.000000000 +0000
@@ -347,11 +347,29 @@ static struct usb_serial_device_type gen
 };
 #endif
 
+/*
+ * The post kludge structures and variables.
+ */
+#define POST_BSIZE	100	/* little below 128 in total */
+struct usb_serial_post_job {
+	struct list_head link;
+	struct usb_serial_port *port;
+	int len;
+	char buff[POST_BSIZE];
+};
+static spinlock_t post_lock = SPIN_LOCK_UNLOCKED;	/* Also covers ->ref */
+static struct list_head post_list = LIST_HEAD_INIT(post_list);
+static struct tq_struct post_task;
 
 /* local function prototypes */
 static int  serial_open (struct tty_struct *tty, struct file * filp);
 static void serial_close (struct tty_struct *tty, struct file * filp);
+static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
 static int  serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
+static int  serial_post_job(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count);
+static int  serial_post_one(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count);
 static int  serial_write_room (struct tty_struct *tty);
 static int  serial_chars_in_buffer (struct tty_struct *tty);
 static void serial_throttle (struct tty_struct * tty);
@@ -448,6 +466,63 @@ static void return_serial (struct usb_se
 	return;
 }
 
+/*
+ * The post kludge.
+ *
+ * Our component drivers are hideously buggy and written by people
+ * who have difficulty understanding the concept of spinlocks.
+ * There were so many races and lockups that Greg K-H made a watershed
+ * decision to provide what is essentially a single-threaded sandbox
+ * for component drivers, protected by a semaphore. It helped a lot, but
+ * for one little problem: when tty->low_latency is set, line disciplines
+ * can call ->write from an interrupt, where the semaphore oopses.
+ *
+ * Rather than open the whole can of worms again, we just post writes
+ * into a helper which can sleep.
+ *
+ * Kernel 2.6 has a proper fix. It replaces semaphores with proper locking.
+ */
+static void post_helper(void *arg)
+{
+	struct list_head *pos;
+	struct usb_serial_post_job *job;
+	struct usb_serial_port *port;
+	struct usb_serial *serial;
+	unsigned int flags;
+
+	spin_lock_irqsave(&post_lock, flags);
+	pos = post_list.next;
+	while (pos != &post_list) {
+		job = list_entry(pos, struct usb_serial_post_job, link);
+		port = job->port;
+		/* get_usb_serial checks port->tty, so cannot be used */
+		serial = port->serial;
+		if (port->write_busy) {
+			dbg("%s - port %d busy", __FUNCTION__, port->number);
+			pos = pos->next;
+			continue;
+		}
+		list_del(&job->link);
+		spin_unlock_irqrestore(&post_lock, flags);
+
+		down(&port->sem);
+		dbg("%s - port %d len %d backlog %d", __FUNCTION__,
+		    port->number, job->len, port->write_backlog);
+		if (port->tty != NULL)
+			__serial_write(port, 0, job->buff, job->len);
+		up(&port->sem);
+
+		spin_lock_irqsave(&post_lock, flags);
+		port->write_backlog -= job->len;
+		kfree(job);
+		if (--serial->ref == 0)
+			kfree(serial);
+		/* Have to reset because we dropped spinlock */
+		pos = post_list.next;
+	}
+	spin_unlock_irqrestore(&post_lock, flags);
+}
+
 #ifdef USES_EZUSB_FUNCTIONS
 /* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
 #define CPUCS_REG    0x7F92
@@ -580,23 +655,34 @@ static void serial_close(struct tty_stru
 
 	/* if disconnect beat us to the punch here, there's nothing to do */
 	if (tty->driver_data) {
+		/*
+		 * XXX The right thing would be to wait for the output to drain.
+		 * But we are not sufficiently daring to experiment in 2.4.
+		 * N.B. If we do wait, no need to run post_helper here.
+		 * Normall callback mechanism wakes it up just fine.
+		 */
+#if I_AM_A_DARING_HACKER
+		tty->closing = 1;
+		up (&port->sem);
+		if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+			tty_wait_until_sent(tty, info->closing_wait);
+		down (&port->sem);
+		if (!tty->driver_data) /* woopsie, disconnect, now what */ ;
+#endif
 		__serial_close(port, filp);
 	}
 
 	up (&port->sem);
 }
 
-static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+static int __serial_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
 {
-	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 	int retval = -EINVAL;
 
 	if (!serial)
 		return -ENODEV;
 
-	down (&port->sem);
-
 	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
 
 	if (!port->open_count) {
@@ -611,10 +697,132 @@ static int serial_write (struct tty_stru
 		retval = generic_write(port, from_user, buf, count);
 
 exit:
-	up (&port->sem);
 	return retval;
 }
 
+static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+	int rc;
+
+	if (!in_interrupt()) {
+		/*
+		 * Run post_list to reduce a possiblity of reordered writes.
+		 * Tasks can make keventd to sleep, sometimes for a long time.
+		 */
+		post_helper(NULL);
+
+		down(&port->sem);
+		/*
+		 * This happens when a line discipline asks how much room
+		 * we have, gets 64, then tries to perform two writes
+		 * for a byte each. First write takes whole URB, second
+		 * write hits this check.
+		 */
+		if (port->write_busy) {
+			up(&port->sem);
+			return serial_post_job(port, from_user, GFP_KERNEL,
+			    buf, count);
+		}
+
+		rc = __serial_write(port, from_user, buf, count);
+		up(&port->sem);
+		return rc;
+	}
+
+	if (from_user) {
+		/*
+		 * This is a BUG-able offense because we cannot
+		 * pagefault while in_interrupt, but we want to see
+		 * something in dmesg rather than just blinking LEDs.
+		 */
+		err("user data in interrupt write");
+		return -EINVAL;
+	}
+
+	return serial_post_job(port, 0, GFP_ATOMIC, buf, count);
+}
+
+static int serial_post_job(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count)
+{
+	int done = 0, length;
+	int rc;
+
+	if (port == NULL)
+		return -EPIPE;
+
+	if (count >= 512) {
+		static int rate = 0;
+		/*
+		 * Data loss due to extreme circumstances.
+		 * It's a ususal thing on serial to lose characters, isn't it?
+		 * Neener, neener! Actually, it's probably an echo loop anyway.
+		 * Only happens when getty starts talking to Visor.
+		 */
+		if (++rate % 1000 < 3) {
+			err("too much data (%d) from %s", count,
+			    from_user? "user": "kernel");
+		}
+		count = 512;
+	}
+
+	while (done < count) {
+		length = count - done;
+		if (length > POST_BSIZE)
+			length = POST_BSIZE;
+		if (length > port->bulk_out_size)
+			length = port->bulk_out_size;
+
+		rc = serial_post_one(port, from_user, gfp, buf + done, length);
+		if (rc <= 0) {
+			if (done != 0)
+				return done;
+			return rc;
+		}
+		done += rc;
+	}
+
+	return done;
+}
+
+static int serial_post_one(struct usb_serial_port *port, int from_user,
+    int gfp, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+	struct usb_serial_post_job *job;
+	unsigned long flags;
+
+	dbg("%s - port %d user %d count %d", __FUNCTION__, port->number, from_user, count);
+
+	job = kmalloc(sizeof(struct usb_serial_post_job), gfp);
+	if (job == NULL)
+		return -ENOMEM;
+
+	job->port = port;
+	if (count >= POST_BSIZE)
+		count = POST_BSIZE;
+	job->len = count;
+
+	if (from_user) {
+		if (copy_from_user(job->buff, buf, count)) {
+			kfree(job);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(job->buff, buf, count);
+	}
+
+	spin_lock_irqsave(&post_lock, flags);
+	port->write_backlog += count;
+	list_add_tail(&job->link, &post_list);
+	serial->ref++;		/* Protect the port->sem from kfree() */
+	schedule_task(&post_task);
+	spin_unlock_irqrestore(&post_lock, flags);
+
+	return count;
+}
+
 static int serial_write_room (struct tty_struct *tty) 
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
@@ -624,6 +832,14 @@ static int serial_write_room (struct tty
 	if (!serial)
 		return -ENODEV;
 
+	if (in_interrupt()) {
+		retval = 0;
+		if (!port->write_busy && port->write_backlog == 0)
+			retval = port->bulk_out_size;
+		dbg("%s - returns %d", __FUNCTION__, retval);
+		return retval;
+	}
+
 	down (&port->sem);
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
@@ -655,10 +871,8 @@ static int serial_chars_in_buffer (struc
 
 	down (&port->sem);
 
-	dbg("%s = port %d", __FUNCTION__, port->number);
-
 	if (!port->open_count) {
-		dbg("%s - port not open", __FUNCTION__);
+		dbg("%s - port %d: not open", __FUNCTION__, port->number);
 		goto exit;
 	}
 
@@ -917,18 +1131,23 @@ static int generic_write (struct usb_ser
 {
 	struct usb_serial *serial = port->serial;
 	int result;
-
-	dbg("%s - port %d", __FUNCTION__, port->number);
+	unsigned long flags;
 
 	if (count == 0) {
 		dbg("%s - write request of 0 bytes", __FUNCTION__);
 		return (0);
 	}
+	if (count < 0) {
+		err("%s - port %d: write request of %d bytes", __FUNCTION__,
+		    port->number, count);
+		return (0);
+	}
 
 	/* only do something if we have a bulk out endpoint */
 	if (serial->num_bulk_out) {
-		if (port->write_urb->status == -EINPROGRESS) {
-			dbg("%s - already writing", __FUNCTION__);
+		if (port->write_busy) {
+			/* Happens when two threads run port_helper. Watch. */
+			info("%s - already writing", __FUNCTION__);
 			return (0);
 		}
 
@@ -937,12 +1156,10 @@ static int generic_write (struct usb_ser
 		if (from_user) {
 			if (copy_from_user(port->write_urb->transfer_buffer, buf, count))
 				return -EFAULT;
-		}
-		else {
+		} else {
 			memcpy (port->write_urb->transfer_buffer, buf, count);
 		}
-
-		usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+		dbg("%s - port %d [%d]", __FUNCTION__, port->number, count);
 
 		/* set up our urb */
 		usb_fill_bulk_urb (port->write_urb, serial->dev,
@@ -954,10 +1171,18 @@ static int generic_write (struct usb_ser
 				     generic_write_bulk_callback), port);
 
 		/* send the data out the bulk port */
+		port->write_busy = 1;
 		result = usb_submit_urb(port->write_urb);
-		if (result)
-			err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
-		else
+		if (result) {
+			err("%s - port %d: failed submitting write urb (%d)",
+			     __FUNCTION__, port->number, result);
+			port->write_busy = 0;
+			spin_lock_irqsave(&post_lock, flags);
+			if (port->write_backlog != 0)
+				schedule_task(&post_task);
+			spin_unlock_irqrestore(&post_lock, flags);
+
+		} else
 			result = count;
 
 		return result;
@@ -972,14 +1197,12 @@ static int generic_write_room (struct us
 	struct usb_serial *serial = port->serial;
 	int room = 0;
 
-	dbg("%s - port %d", __FUNCTION__, port->number);
-	
 	if (serial->num_bulk_out) {
-		if (port->write_urb->status != -EINPROGRESS)
+		if (!port->write_busy && port->write_backlog == 0)
 			room = port->bulk_out_size;
 	}
 
-	dbg("%s - returns %d", __FUNCTION__, room);
+	dbg("%s - port %d, returns %d", __FUNCTION__, port->number, room);
 	return (room);
 }
 
@@ -991,8 +1214,9 @@ static int generic_chars_in_buffer (stru
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (serial->num_bulk_out) {
-		if (port->write_urb->status == -EINPROGRESS)
-			chars = port->write_urb->transfer_buffer_length;
+		if (port->write_busy)
+			chars += port->write_urb->transfer_buffer_length;
+		chars += port->write_backlog;	/* spin_lock... Baah */
 	}
 
 	dbg("%s - returns %d", __FUNCTION__, chars);
@@ -1056,14 +1280,16 @@ static void generic_write_bulk_callback 
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
+	port->write_busy = 0;
+	wmb();
+
 	if (!serial) {
-		dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+		err("%s - null serial pointer, exiting", __FUNCTION__);
 		return;
 	}
 
 	if (urb->status) {
 		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
-		return;
 	}
 
 	queue_task(&port->tqueue, &tq_immediate);
@@ -1089,12 +1315,18 @@ static void port_softint(void *private)
 	struct usb_serial_port *port = (struct usb_serial_port *)private;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
 	struct tty_struct *tty;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 	
 	if (!serial)
 		return;
 
+	spin_lock_irqsave(&post_lock, flags);
+	if (port->write_backlog != 0)
+		schedule_task(&post_task);
+	spin_unlock_irqrestore(&post_lock, flags);
+
 	tty = port->tty;
 	if (!tty)
 		return;
@@ -1108,7 +1340,6 @@ static void port_softint(void *private)
 }
 
 
-
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
 			       const struct usb_device_id *id)
 {
@@ -1132,6 +1363,7 @@ static void * usb_serial_probe(struct us
 	int num_ports;
 	int max_endpoints;
 	const struct usb_device_id *id_pattern = NULL;
+	unsigned long flags;
 
 	/* loop through our list of known serial converters, and see if this
 	   device matches. */
@@ -1342,11 +1574,15 @@ static void * usb_serial_probe(struct us
 		init_MUTEX (&port->sem);
 	}
 
+	spin_lock_irqsave(&post_lock, flags);
+	serial->ref = 1;
+	spin_unlock_irqrestore(&post_lock, flags);
+
 	/* if this device type has a startup function, call it */
 	if (type->startup) {
 		i = type->startup (serial);
 		if (i < 0)
-			goto probe_error;
+			goto startup_error;
 		if (i > 0)
 			return serial;
 	}
@@ -1361,6 +1597,12 @@ static void * usb_serial_probe(struct us
 	return serial; /* success */
 
 
+startup_error:
+	spin_lock_irqsave(&post_lock, flags);
+	if (serial->ref != 1) {
+		err("bug in component startup: ref %d\n", serial->ref);
+	}
+	spin_unlock_irqrestore(&post_lock, flags);
 probe_error:
 	for (i = 0; i < num_bulk_in; ++i) {
 		port = &serial->port[i];
@@ -1396,6 +1638,7 @@ static void usb_serial_disconnect(struct
 {
 	struct usb_serial *serial = (struct usb_serial *) ptr;
 	struct usb_serial_port *port;
+	unsigned long flags;
 	int i;
 
 	dbg ("%s", __FUNCTION__);
@@ -1453,7 +1696,10 @@ static void usb_serial_disconnect(struct
 		return_serial (serial);
 
 		/* free up any memory that we allocated */
-		kfree (serial);
+		spin_lock_irqsave(&post_lock, flags);
+		if (--serial->ref == 0)
+			kfree(serial);
+		spin_unlock_irqrestore(&post_lock, flags);
 
 	} else {
 		info("device disconnected");
@@ -1505,6 +1751,7 @@ static int __init usb_serial_init(void)
 	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
 		serial_table[i] = NULL;
 	}
+	post_task.routine = post_helper;
 
 	/* register the tty driver */
 	serial_tty_driver.init_termios          = tty_std_termios;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/serial/visor.c linux-2.4.27-rc4/drivers/usb/serial/visor.c
--- linux-2.4.26/drivers/usb/serial/visor.c	2004-04-14 13:05:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/serial/visor.c	2004-07-30 16:27:10.000000000 +0000
@@ -184,6 +184,7 @@ static void visor_write_bulk_callback	(s
 static void visor_read_bulk_callback	(struct urb *urb);
 static void visor_read_int_callback	(struct urb *urb);
 static int  clie_3_5_startup	(struct usb_serial *serial);
+static int  clie_5_startup	(struct usb_serial *serial);
 static void treo_attach		(struct usb_serial *serial);
 
 /* Parameters that may be passed into the module. */
@@ -211,7 +212,6 @@ static struct usb_device_id id_table [] 
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_1_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NX60_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_NZ90V_ID) },
-	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
 	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
 	{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
 	{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
@@ -224,6 +224,12 @@ static struct usb_device_id clie_id_3_5_
 	{ }					/* Terminating entry */
 };
 
+
+static struct usb_device_id clie_id_5_table [] = {
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
+	{ }					/* Terminating entry */
+};
+
 static __devinitdata struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_TREO_ID) },
@@ -310,6 +316,32 @@ static struct usb_serial_device_type cli
 	.read_bulk_callback =	visor_read_bulk_callback,
 };
 
+
+/* device info for the Sony Clie OS version 5.0 */
+static struct usb_serial_device_type clie_5_device = {
+	.owner =		THIS_MODULE,
+	.name =			"Sony Clié 5.0",
+	.id_table =		clie_id_5_table,
+	.num_interrupt_in =	NUM_DONT_CARE,
+	.num_bulk_in =		2,
+	.num_bulk_out =		2,
+	.num_ports =		2,
+	.open =			visor_open,
+	.close =		visor_close,
+	.throttle =		visor_throttle,
+	.unthrottle =		visor_unthrottle,
+	.startup =		clie_5_startup,
+	.shutdown =		visor_shutdown,
+	.ioctl =		visor_ioctl,
+	.set_termios =		visor_set_termios,
+	.write =		visor_write,
+	.write_room =		visor_write_room,
+	.chars_in_buffer =	visor_chars_in_buffer,
+	.write_bulk_callback =	visor_write_bulk_callback,
+	.read_bulk_callback =	visor_read_bulk_callback,
+	.read_int_callback =	visor_read_int_callback,
+};
+
 /* This structure is for Handspring Visor, and Palm 4.0 devices that are not
  * compiled into the kernel, but can be passed in when the module is loaded.
  * This will allow the visor driver to work with new Vendor and Device IDs
@@ -853,6 +885,67 @@ static int clie_3_5_startup (struct usb_
 	return 0;
 }
 
+
+static int clie_5_startup (struct usb_serial *serial)
+{
+	int response;
+	unsigned char *transfer_buffer;
+	struct palm_ext_connection_info *connection_info;
+
+	dbg("%s", __FUNCTION__);
+
+	dbg("%s - Set config to 1", __FUNCTION__);
+	usb_set_configuration(serial->dev, 1);
+
+	transfer_buffer = kmalloc(sizeof (*connection_info),
+					GFP_KERNEL);
+	if (!transfer_buffer) {
+		err("%s - kmalloc(%d) failed.", __FUNCTION__,
+			sizeof (*connection_info));
+		return -ENOMEM;
+	}
+
+	response = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), 
+					PALM_GET_EXT_CONNECTION_INFORMATION,
+					0xc2, 0x0000, 0x0000, transfer_buffer, 
+					sizeof(*connection_info), 300);
+	if (response < 0) {
+		err("%s - error %d getting connection info",
+			 __FUNCTION__, response);
+	} else {
+		usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
+	}
+
+	/* ask for the number of bytes available, but ignore the response as it is broken */
+	response = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
+					0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
+	if (response < 0) {
+		err("%s - error getting bytes available request", __FUNCTION__);
+	}
+
+	kfree (transfer_buffer);
+
+	/* UX50/TH55 registers 2 ports. 
+	   Communication in from the TH55 uses bulk_in_endpointAddress from port 0 
+	   Communication out to the TH55 uses bulk_out_endpointAddress from port 1 
+
+	   Lets do a quick and dirty mapping
+	*/
+
+	/* some sanity check */
+	if (serial->num_ports < 2)
+		return -ENODEV;
+
+	/* port 0 now uses the modified endpoint Address */
+	serial->port[0].bulk_out_endpointAddress = serial->port[1].bulk_out_endpointAddress;
+
+	/* continue on with initialization */
+	return 0;
+}
+
+
+
+
 static void treo_attach (struct usb_serial *serial)
 {
 	struct usb_serial_port *port;
@@ -993,6 +1086,7 @@ static int __init visor_init (void)
 	}
 	usb_serial_register (&handspring_device);
 	usb_serial_register (&clie_3_5_device);
+	usb_serial_register (&clie_5_device);
 	
 	/* create our write urb pool and transfer buffers */ 
 	spin_lock_init (&write_urb_pool_lock);
@@ -1029,6 +1123,7 @@ static void __exit visor_exit (void)
 	}
 	usb_serial_deregister (&handspring_device);
 	usb_serial_deregister (&clie_3_5_device);
+	usb_serial_deregister (&clie_5_device);
 
 	spin_lock_irqsave (&write_urb_pool_lock, flags);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/speedtch.c linux-2.4.27-rc4/drivers/usb/speedtch.c
--- linux-2.4.26/drivers/usb/speedtch.c	2003-11-28 18:26:20.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/speedtch.c	2004-07-30 16:27:23.000000000 +0000
@@ -83,6 +83,10 @@
 #define VERBOSE_DEBUG
 */
 
+#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
+#	define DEBUG
+#endif
+
 #include <linux/usb.h>
 
 #ifdef DEBUG
@@ -101,8 +105,8 @@ static int udsl_print_packet (const unsi
 #endif
 
 #define DRIVER_AUTHOR	"Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
-#define DRIVER_DESC	"Alcatel SpeedTouch USB driver"
-#define DRIVER_VERSION	"1.7"
+#define DRIVER_VERSION	"1.8"
+#define DRIVER_DESC	"Alcatel SpeedTouch USB driver version " DRIVER_VERSION
 
 static const char udsl_driver_name [] = "speedtch";
 
@@ -294,6 +298,19 @@ static struct usb_driver udsl_usb_driver
 };
 
 
+/***********
+**  misc  **
+***********/
+
+static inline void udsl_pop (struct atm_vcc *vcc, struct sk_buff *skb)
+{
+	if (vcc->pop)
+		vcc->pop (vcc, skb);
+	else
+		dev_kfree_skb (skb);
+}
+
+
 /*************
 **  decode  **
 *************/
@@ -717,10 +734,7 @@ made_progress:
 	if (!UDSL_SKB (skb)->num_cells) {
 		struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc;
 
-		if (vcc->pop)
-			vcc->pop (vcc, skb);
-		else
-			dev_kfree_skb (skb);
+		udsl_pop (vcc, skb);
 		instance->current_skb = NULL;
 
 		atomic_inc (&vcc->stats->tx);
@@ -739,10 +753,7 @@ static void udsl_cancel_send (struct uds
 		if (UDSL_SKB (skb)->atm_data.vcc == vcc) {
 			dbg ("udsl_cancel_send: popping skb 0x%p", skb);
 			__skb_unlink (skb, &instance->sndqueue);
-			if (vcc->pop)
-				vcc->pop (vcc, skb);
-			else
-				dev_kfree_skb (skb);
+			udsl_pop (vcc, skb);
 		}
 	spin_unlock_irq (&instance->sndqueue.lock);
 
@@ -750,10 +761,7 @@ static void udsl_cancel_send (struct uds
 	if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) {
 		dbg ("udsl_cancel_send: popping current skb (0x%p)", skb);
 		instance->current_skb = NULL;
-		if (vcc->pop)
-			vcc->pop (vcc, skb);
-		else
-			dev_kfree_skb (skb);
+		udsl_pop (vcc, skb);
 	}
 	tasklet_enable (&instance->send_tasklet);
 	dbg ("udsl_cancel_send done");
@@ -762,22 +770,26 @@ static void udsl_cancel_send (struct uds
 static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
 {
 	struct udsl_instance_data *instance = vcc->dev->dev_data;
+	int err;
 
 	vdbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len);
 
 	if (!instance || !instance->usb_dev) {
 		dbg ("udsl_atm_send: NULL data!");
-		return -ENODEV;
+		err = -ENODEV;
+		goto fail;
 	}
 
 	if (vcc->qos.aal != ATM_AAL5) {
 		dbg ("udsl_atm_send: unsupported ATM type %d!", vcc->qos.aal);
-		return -EINVAL;
+		err = -EINVAL;
+		goto fail;
 	}
 
 	if (skb->len > ATM_MAX_AAL5_PDU) {
 		dbg ("udsl_atm_send: packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU);
-		return -EINVAL;
+		err = -EINVAL;
+		goto fail;
 	}
 
 	PACKETDEBUG (skb->data, skb->len);
@@ -787,6 +799,10 @@ static int udsl_atm_send (struct atm_vcc
 	tasklet_schedule (&instance->send_tasklet);
 
 	return 0;
+
+fail:
+	udsl_pop (vcc, skb);
+	return err;
 }
 
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/storage/jumpshot.c linux-2.4.27-rc4/drivers/usb/storage/jumpshot.c
--- linux-2.4.26/drivers/usb/storage/jumpshot.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/storage/jumpshot.c	2004-07-30 16:25:02.000000000 +0000
@@ -710,15 +710,8 @@ int jumpshot_transport(Scsi_Cmnd * srb, 
 
 		// build the reply
 		//
-		ptr[0] = (info->sectors >> 24) & 0xFF;
-		ptr[1] = (info->sectors >> 16) & 0xFF;
-		ptr[2] = (info->sectors >> 8) & 0xFF;
-		ptr[3] = (info->sectors) & 0xFF;
-
-		ptr[4] = (info->ssize >> 24) & 0xFF;
-		ptr[5] = (info->ssize >> 16) & 0xFF;
-		ptr[6] = (info->ssize >> 8) & 0xFF;
-		ptr[7] = (info->ssize) & 0xFF;
+		((u32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+		((u32 *) ptr)[1] = cpu_to_be32(info->ssize);
 
 		return USB_STOR_TRANSPORT_GOOD;
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/storage/scsiglue.c linux-2.4.27-rc4/drivers/usb/storage/scsiglue.c
--- linux-2.4.26/drivers/usb/storage/scsiglue.c	2004-04-14 13:05:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/storage/scsiglue.c	2004-07-30 16:28:38.000000000 +0000
@@ -218,7 +218,14 @@ static int device_reset( Scsi_Cmnd *srb 
 	US_DEBUGP("device_reset() called\n" );
 
 	spin_unlock_irq(&io_request_lock);
+	down(&(us->dev_semaphore));
+	if (!us->pusb_dev) {
+		up(&(us->dev_semaphore));
+		spin_lock_irq(&io_request_lock);
+		return SUCCESS;
+	}
 	rc = us->transport_reset(us);
+	up(&(us->dev_semaphore));
 	spin_lock_irq(&io_request_lock);
 	return rc;
 }
@@ -235,27 +242,44 @@ static int bus_reset( Scsi_Cmnd *srb )
 	/* we use the usb_reset_device() function to handle this for us */
 	US_DEBUGP("bus_reset() called\n");
 
+	spin_unlock_irq(&io_request_lock);
+
+	down(&(us->dev_semaphore));
+
 	/* if the device has been removed, this worked */
 	if (!us->pusb_dev) {
 		US_DEBUGP("-- device removed already\n");
+		up(&(us->dev_semaphore));
+		spin_lock_irq(&io_request_lock);
 		return SUCCESS;
 	}
 
-	spin_unlock_irq(&io_request_lock);
+	/* The USB subsystem doesn't handle synchronisation between
+	 * a device's several drivers. Therefore we reset only devices
+	 * with just one interface, which we of course own. */
+	if (us->pusb_dev->actconfig->bNumInterfaces != 1) {
+		printk(KERN_NOTICE "usb-storage: "
+		    "Refusing to reset a multi-interface device\n");
+		up(&(us->dev_semaphore));
+		spin_lock_irq(&io_request_lock);
+		/* XXX Don't just return success, make sure current cmd fails */
+		return SUCCESS;
+	}
 
 	/* release the IRQ, if we have one */
-	down(&(us->irq_urb_sem));
 	if (us->irq_urb) {
 		US_DEBUGP("-- releasing irq URB\n");
 		result = usb_unlink_urb(us->irq_urb);
 		US_DEBUGP("-- usb_unlink_urb() returned %d\n", result);
 	}
-	up(&(us->irq_urb_sem));
 
 	/* attempt to reset the port */
 	if (usb_reset_device(us->pusb_dev) < 0) {
-		spin_lock_irq(&io_request_lock);
-		return FAILED;
+		/*
+		 * Do not return errors, or else the error handler might
+		 * invoke host_reset, which is not implemented.
+		 */
+		goto bail_out;
 	}
 
 	/* FIXME: This needs to lock out driver probing while it's working
@@ -286,17 +310,18 @@ static int bus_reset( Scsi_Cmnd *srb )
 		up(&intf->driver->serialize);
 	}
 
+bail_out:
 	/* re-allocate the IRQ URB and submit it to restore connectivity
 	 * for CBI devices
 	 */
 	if (us->protocol == US_PR_CBI) {
-		down(&(us->irq_urb_sem));
 		us->irq_urb->dev = us->pusb_dev;
 		result = usb_submit_urb(us->irq_urb);
 		US_DEBUGP("usb_submit_urb() returns %d\n", result);
-		up(&(us->irq_urb_sem));
 	}
-	
+
+	up(&(us->dev_semaphore));
+
 	spin_lock_irq(&io_request_lock);
 
 	US_DEBUGP("bus_reset() complete\n");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/storage/unusual_devs.h linux-2.4.27-rc4/drivers/usb/storage/unusual_devs.h
--- linux-2.4.26/drivers/usb/storage/unusual_devs.h	2004-04-14 13:05:35.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/storage/unusual_devs.h	2004-07-30 16:30:20.000000000 +0000
@@ -185,7 +185,7 @@ UNUSUAL_DEV(  0x04e6, 0x0005, 0x0100, 0x
 UNUSUAL_DEV(  0x04e6, 0x0006, 0x0100, 0x0205, 
 		"Shuttle",
 		"eUSB MMC Adapter",
-		US_SC_SCSI, US_PR_CB, NULL, 
+		US_SC_SCSI, US_PR_DEVICE, NULL, 
 		US_FL_SINGLE_LUN), 
 
 UNUSUAL_DEV(  0x04e6, 0x0007, 0x0100, 0x0200, 
@@ -273,6 +273,13 @@ UNUSUAL_DEV(  0x054c, 0x002e, 0x0106, 0x
 		US_SC_SCSI, US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN | US_FL_MODE_XLATE),
 
+/* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
+UNUSUAL_DEV(  0x054c, 0x002e, 0x0500, 0x0500, 
+		"Sony",
+		"Handycam HC-85",
+		US_SC_UFI, US_PR_DEVICE, NULL,
+		US_FL_SINGLE_LUN | US_FL_MODE_XLATE),
+
 UNUSUAL_DEV(  0x054c, 0x0032, 0x0000, 0x9999,
 		"Sony",
 		"Memorystick MSC-U01N",
@@ -311,6 +318,15 @@ UNUSUAL_DEV(  0x057b, 0x0000, 0x0300, 0x
 		US_SC_DEVICE,  US_PR_DEVICE, NULL,
 		US_FL_SINGLE_LUN),
 
+/* Reported by Johann Cardon <johann.cardon@free.fr>
+ * This entry is needed only because the device reports
+ * bInterfaceClass = 0xff (vendor-specific)
+ */
+UNUSUAL_DEV(  0x057b, 0x0022, 0x0000, 0x9999, 
+		"Y-E Data",
+		"Silicon Media R/W",
+		US_SC_DEVICE, US_PR_DEVICE, NULL, 0),
+
 /* Fabrizio Fellini <fello@libero.it> */
 UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
 		"Fujifilm",
@@ -669,7 +685,7 @@ UNUSUAL_DEV(  0x097a, 0x0001, 0x0000, 0x
 UNUSUAL_DEV(  0x0a16, 0x8888, 0x0100, 0x0100,
 		"IBM",
 		"IBM USB Memory Key",
-		US_SC_SCSI, US_PR_BULK, NULL,
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
 /* This Pentax still camera is not conformant
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/storage/usb.c linux-2.4.27-rc4/drivers/usb/storage/usb.c
--- linux-2.4.26/drivers/usb/storage/usb.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/storage/usb.c	2004-07-30 16:26:48.000000000 +0000
@@ -501,6 +501,9 @@ static int usb_stor_control_thread(void 
  * strucuture is current.  This includes the ep_int field, which gives us
  * the endpoint for the interrupt.
  * Returns non-zero on failure, zero on success
+ *
+ * ss->dev_semaphore is expected taken, except for a newly minted,
+ * unregistered device.
  */ 
 static int usb_stor_allocate_irq(struct us_data *ss)
 {
@@ -510,13 +513,9 @@ static int usb_stor_allocate_irq(struct 
 
 	US_DEBUGP("Allocating IRQ for CBI transport\n");
 
-	/* lock access to the data structure */
-	down(&(ss->irq_urb_sem));
-
 	/* allocate the URB */
 	ss->irq_urb = usb_alloc_urb(0);
 	if (!ss->irq_urb) {
-		up(&(ss->irq_urb_sem));
 		US_DEBUGP("couldn't allocate interrupt URB");
 		return 1;
 	}
@@ -537,12 +536,9 @@ static int usb_stor_allocate_irq(struct 
 	US_DEBUGP("usb_submit_urb() returns %d\n", result);
 	if (result) {
 		usb_free_urb(ss->irq_urb);
-		up(&(ss->irq_urb_sem));
 		return 2;
 	}
 
-	/* unlock the data structure and return success */
-	up(&(ss->irq_urb_sem));
 	return 0;
 }
 
@@ -772,7 +768,6 @@ static void * storage_probe(struct usb_d
 		init_completion(&(ss->notify));
 		init_MUTEX_LOCKED(&(ss->ip_waitq));
 		spin_lock_init(&(ss->queue_exclusion));
-		init_MUTEX(&(ss->irq_urb_sem));
 		init_MUTEX(&(ss->current_urb_sem));
 		init_MUTEX(&(ss->dev_semaphore));
 
@@ -1063,7 +1058,6 @@ static void storage_disconnect(struct us
 	down(&(ss->dev_semaphore));
 
 	/* release the IRQ, if we have one */
-	down(&(ss->irq_urb_sem));
 	if (ss->irq_urb) {
 		US_DEBUGP("-- releasing irq URB\n");
 		result = usb_unlink_urb(ss->irq_urb);
@@ -1071,7 +1065,6 @@ static void storage_disconnect(struct us
 		usb_free_urb(ss->irq_urb);
 		ss->irq_urb = NULL;
 	}
-	up(&(ss->irq_urb_sem));
 
 	/* free up the main URB for this device */
 	US_DEBUGP("-- releasing main URB\n");
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/storage/usb.h linux-2.4.27-rc4/drivers/usb/storage/usb.h
--- linux-2.4.26/drivers/usb/storage/usb.h	2003-08-25 11:44:42.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/storage/usb.h	2004-07-30 16:29:36.000000000 +0000
@@ -116,7 +116,7 @@ struct us_data {
 	struct us_data		*next;		 /* next device */
 
 	/* the device we're working with */
-	struct semaphore	dev_semaphore;	 /* protect pusb_dev */
+	struct semaphore	dev_semaphore;	 /* protect many things */
 	struct usb_device	*pusb_dev;	 /* this usb_device */
 
 	unsigned int		flags;		 /* from filter initially */
@@ -162,7 +162,6 @@ struct us_data {
 	atomic_t		ip_wanted[1];	 /* is an IRQ expected?	 */
 
 	/* interrupt communications data */
-	struct semaphore	irq_urb_sem;	 /* to protect irq_urb	 */
 	struct urb		*irq_urb;	 /* for USB int requests */
 	unsigned char		irqbuf[2];	 /* buffer for USB IRQ	 */
 	unsigned char		irqdata[2];	 /* data from USB IRQ	 */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/tiglusb.c linux-2.4.27-rc4/drivers/usb/tiglusb.c
--- linux-2.4.26/drivers/usb/tiglusb.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/tiglusb.c	2004-07-30 16:29:39.000000000 +0000
@@ -3,7 +3,7 @@
  * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver.
  * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
  *
- * Copyright (C) 2001-2002:
+ * Copyright (C) 2001-2004:
  *   Romain Lievin <roms@lpg.ticalc.org>
  *   Julien BLACHE <jb@technologeek.org>
  * under the terms of the GNU General Public License.
@@ -14,11 +14,14 @@
  * and the website at:  http://lpg.ticalc.org/prj_usb/
  * for more info.
  *
+ * History:
  *   1.0x, Romain & Julien: initial submit.
  *   1.03, Greg Kroah: modifications.
  *   1.04, Julien: clean-up & fixes; Romain: 2.4 backport.
  *   1.05, Randy Dunlap: bug fix with the timeout parameter (divide-by-zero).
  *   1.06, Romain: synched with 2.5, version/firmware changed (confusing).
+ *   1.07, Romain: fixed bad use of usb_clear_halt (invalid argument);
+ *          timeout argument checked in ioctl + clean-up.
  */
 
 #include <linux/module.h>
@@ -38,8 +41,8 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "1.06"
-#define DRIVER_AUTHOR  "Romain Lievin <roms@lpg.ticalc.org> & Julien Blache <jb@jblache.org>"
+#define DRIVER_VERSION "1.07"
+#define DRIVER_AUTHOR  "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
 #define DRIVER_DESC    "TI-GRAPH LINK USB (aka SilverLink) driver"
 #define DRIVER_LICENSE "GPL"
 
@@ -74,15 +77,15 @@ clear_pipes (struct usb_device *dev)
 {
 	unsigned int pipe;
 
-	pipe = usb_sndbulkpipe (dev, 1);
-	if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) {
-		err ("clear_pipe (r), request failed");
+	pipe = usb_sndbulkpipe (dev, 2);
+	if (usb_clear_halt (dev, pipe)) {
+		err ("clear_pipe (w), request failed");
 		return -1;
 	}
 
-	pipe = usb_sndbulkpipe (dev, 2);
-	if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) {
-		err ("clear_pipe (w), request failed");
+	pipe = usb_rcvbulkpipe (dev, 1);
+	if (usb_clear_halt (dev, pipe)) {
+		err ("clear_pipe (r), request failed");
 		return -1;
 	}
 
@@ -181,15 +184,14 @@ tiglusb_read (struct file *filp, char *b
 	result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
 			       &bytes_read, HZ * 10 / timeout);
 	if (result == -ETIMEDOUT) {	/* NAK */
-		ret = result;
-		if (!bytes_read) {
+		if (!bytes_read)
 			dbg ("quirk !");
-		}
 		warn ("tiglusb_read, NAK received.");
+		ret = result;
 		goto out;
 	} else if (result == -EPIPE) {	/* STALL -- shouldn't happen */
 		warn ("clear_halt request to remove STALL condition.");
-		if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe)))
+		if (usb_clear_halt (s->dev, pipe))
 			err ("clear_halt, request failed");
 		clear_device (s->dev);
 		ret = result;
@@ -244,7 +246,7 @@ tiglusb_write (struct file *filp, const 
 		goto out;
 	} else if (result == -EPIPE) {	/* STALL -- shouldn't happen */
 		warn ("clear_halt request to remove STALL condition.");
-		if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe)))
+		if (usb_clear_halt (s->dev, pipe))
 			err ("clear_halt, request failed");
 		clear_device (s->dev);
 		ret = result;
@@ -284,15 +286,16 @@ tiglusb_ioctl (struct inode *inode, stru
 
 	switch (cmd) {
 	case IOCTL_TIUSB_TIMEOUT:
-		timeout = arg;	// timeout value in tenth of seconds
+		if (arg > 0)
+			timeout = (int)arg;
+		else
+			ret = -EINVAL;
 		break;
 	case IOCTL_TIUSB_RESET_DEVICE:
-		dbg ("IOCTL_TIGLUSB_RESET_DEVICE");
 		if (clear_device (s->dev))
 			ret = -EIO;
 		break;
 	case IOCTL_TIUSB_RESET_PIPES:
-		dbg ("IOCTL_TIGLUSB_RESET_PIPES");
 		if (clear_pipes (s->dev))
 			ret = -EIO;
 		break;
@@ -430,7 +433,7 @@ static struct usb_driver tiglusb_driver 
 
 #ifndef MODULE
 /*
- * You can use 'tiusb=timeout'
+ * You can use 'tiusb=timeout' to set timeout.
  */
 static int __init
 tiglusb_setup (char *str)
@@ -440,10 +443,11 @@ tiglusb_setup (char *str)
 	str = get_options (str, ARRAY_SIZE (ints), ints);
 
 	if (ints[0] > 0) {
-		timeout = ints[1];
+		if (ints[1] > 0)
+			timeout = ints[1];
+		else
+			info ("tiglusb: wrong timeout value (0), using default value.");
 	}
-	if (!timeout)
-		timeout = TIMAXTIME;
 
 	return 1;
 }
@@ -466,8 +470,6 @@ tiglusb_init (void)
 		init_waitqueue_head (&s->wait);
 		init_waitqueue_head (&s->remove_ok);
 	}
-	if (timeout <= 0)
-               timeout = TIMAXTIME;
 
 	/* register device */
 	if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
@@ -487,12 +489,6 @@ tiglusb_init (void)
 
 	info (DRIVER_DESC ", version " DRIVER_VERSION);
 
-       if (timeout <= 0)
-               timeout = TIMAXTIME;
-
-	if (!timeout)
-		timeout = TIMAXTIME;
-
 	return 0;
 }
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/usb/vicam.c linux-2.4.27-rc4/drivers/usb/vicam.c
--- linux-2.4.26/drivers/usb/vicam.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/drivers/usb/vicam.c	2004-07-30 16:26:08.000000000 +0000
@@ -481,6 +481,7 @@ vicam_ioctl(struct video_device *dev, un
 			struct video_capability b;
 
 			DBG("VIDIOCGCAP\n");
+			memset(&b, 0, sizeof(b));
 			strcpy(b.name, "ViCam-based Camera");
 			b.type = VID_TYPE_CAPTURE;
 			b.channels = 1;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/riva/accel.c linux-2.4.27-rc4/drivers/video/riva/accel.c
--- linux-2.4.26/drivers/video/riva/accel.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/riva/accel.c	2004-07-30 16:32:18.000000000 +0000
@@ -300,8 +300,8 @@ static void fbcon_riva16_clear(struct vc
 
 static inline void convert_bgcolor_16(u32 *col)
 {
-	*col = ((*col & 0x00007C00) << 9)
-             | ((*col & 0x000003E0) << 6)
+	*col = ((*col & 0x0000F800) << 8)
+             | ((*col & 0x000007E0) << 5)
              | ((*col & 0x0000001F) << 3)
              |          0xFF000000;
 }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/riva/fbdev.c linux-2.4.27-rc4/drivers/video/riva/fbdev.c
--- linux-2.4.26/drivers/video/riva/fbdev.c	2003-06-13 14:51:37.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/riva/fbdev.c	2004-07-30 16:29:55.000000000 +0000
@@ -952,7 +952,7 @@ static void riva_load_video_mode(struct 
 	newmode.crtc[0x12] = Set8Bits (vDisplay);
 	newmode.crtc[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF;
 	newmode.crtc[0x15] = Set8Bits (vBlankStart);
-	newmode.crtc[0x16] = Set8Bits (vBlankEnd);
+	newmode.crtc[0x16] = Set8Bits (vBlankEnd + 1);
 
 	newmode.ext.bpp = bpp;
 	newmode.ext.width = width;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/300vtbl.h linux-2.4.27-rc4/drivers/video/sis/300vtbl.h
--- linux-2.4.26/drivers/video/sis/300vtbl.h	2004-04-14 13:05:39.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/300vtbl.h	2004-07-30 16:26:08.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Register settings for SiS 300 series
  *
@@ -75,93 +76,93 @@ static const SiS_StStruct  SiS300_SModeI
 
 static const SiS_ExtStruct  SiS300_EModeIDTable[] =
 {
-	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x? */
-	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x8 */
-	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},
-	{0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x8 */
-	{0x32,0x2a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x8 */
-	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x16 */
-	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x16 */
-	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11},  /* 720x480x32 */
-	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12},  /* 720x576x32 */
-	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x? */
-	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},  /* 1024x768x8 */
-	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},  /* 1280x1024x8 */
-	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x15 */
-	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x16 */
-	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x15 */
-	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x16 */
-	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x8  */
-	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x8  */
-	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x8  */
-	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x16 */
-	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x16 */
-	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x16 */
-	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x8  */
-	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26},  /* 512x384x32 */
-	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x16 */
- 	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10},  /* 640x400x32 */
-	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08},
-	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00},  /* 800x600x32 */
-	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13},
-	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e},
-	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27},
-	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x8 - not in BIOS! */
-	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28},  /* 2048x1536x16 - not in BIOS! */
-	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x8 */
-	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x8 */
-	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x16 */
-	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x16 */
-	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x32 */
-	{0x77,0x0a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30},  /* 1024x576x32 */
-	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x32 */
-	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33},  /* 1280x720x8 */
-	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d},  /* 800x480x16 */
-	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x8 */
-	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x16 */
-	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29},  /* 1280x960x32 */
-	{0x20,0x0a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},  /* 1024x600 */
-	{0x21,0x0a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x22,0x0a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b},
-	{0x23,0x0a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},  /* 1152x768 */
-	{0x24,0x0a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x25,0x0a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c},
-	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},  /* 1152x864 */
-	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36},
-	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},  /* 848x480 */
-	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38},
-	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},  /* 856x480 */
-	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a},
-	{0x48,0x223b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},  /* 1360x768 */
-	{0x4b,0x227d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4e,0x22ff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c},
-	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23},  /* 320x200x32 */
-	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24},  /* 320x240x32 */
-	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25},  /* 400x300x32 */
-	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},  /* 1280x768   */
-	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d},
-	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x8 */
-	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x16 */
-	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e},  /* 768x576x32 */
-	{0x67,0x2e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x8 (BARCO) */
-	{0x6f,0x2e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x16 (BARCO) */
-	{0x72,0x2eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f},  /* 1360x1024x32 (BARCO) */
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x2f,0x021b,0x0100,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},
+	{0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x8 */
+	{0x32,0x2a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x8 */
+	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x16 */
+	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x16 */
+	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x00,0x00,0x11,-1},  /* 720x480x32 */
+	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x00,0x00,0x12,-1},  /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},  /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},  /* 1280x1024x8 */
+	{0x3c,0x063b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x3d,0x067d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x40,0x921c,0x010d,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x15 */
+	{0x41,0x921d,0x010e,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x15 */
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x50,0x921b,0x0132,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x8  */
+	{0x51,0xb21b,0x0133,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x8  */
+	{0x52,0x921b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x8  */
+	{0x56,0x921d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x16 */
+	{0x57,0xb21d,0x0136,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x16 */
+	{0x58,0x921d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x16 */
+	{0x59,0x921b,0x0138,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x8  */
+	{0x5c,0x921f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x26,-1},  /* 512x384x32 */
+	{0x5d,0x021d,0x0139,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x16 */
+ 	{0x5e,0x021f,0x0000,SIS_RI_640x400,  0x00,0x00,0x00,0x00,0x10,-1},  /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x00,0x00,0x08,-1},
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x00,0x00,0x00,-1},  /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x00,0x00,0x13,-1},
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a,-1},
+	{0x66,0x06ff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,-1},
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6b,0x07ff,0x0000,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x27,-1},
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x8 - not in BIOS! */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x28,-1},  /* 2048x1536x16 - not in BIOS! */
+	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x8 */
+	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x8 */
+	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x16 */
+	{0x75,0x0e3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x16 */
+	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x32 */
+	{0x77,0x0a3f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x30,-1},  /* 1024x576x32 */
+	{0x78,0x0eff,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x32 */
+	{0x79,0x0e3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x33,-1},  /* 1280x720x8 */
+	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x00,0x2d,-1},  /* 800x480x16 */
+	{0x7c,0x0a3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x8 */
+	{0x7d,0x0a7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x16 */
+	{0x7e,0x0aff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x29,-1},  /* 1280x960x32 */
+	{0x20,0x0a1b,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},  /* 1024x600 */
+	{0x21,0x0a3d,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x22,0x0a7f,0x0000,SIS_RI_1024x600, 0x00,0x00,0x00,0x00,0x2b,-1},
+	{0x23,0x0a1b,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},  /* 1152x768 */
+	{0x24,0x0a3d,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x25,0x0a7f,0x0000,SIS_RI_1152x768, 0x00,0x00,0x00,0x00,0x2c,-1},
+	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},  /* 1152x864 */
+	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x36,-1},
+	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},  /* 848x480 */
+	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},
+	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x38,-1},
+	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},  /* 856x480 */
+	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},
+	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x3a,-1},
+	{0x48,0x223b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},  /* 1360x768 */
+	{0x4b,0x227d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},
+	{0x4e,0x22ff,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x3c,-1},
+	{0x4f,0x921f,0x0000,SIS_RI_320x200,  0x00,0x00,0x00,0x00,0x23,-1},  /* 320x200x32 */
+	{0x53,0x921f,0x0000,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x24,-1},  /* 320x240x32 */
+	{0x54,0xb21f,0x0000,SIS_RI_400x300,  0x00,0x00,0x00,0x00,0x25,-1},  /* 400x300x32 */
+	{0x55,0x2e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},  /* 1280x768   */
+	{0x5a,0x2e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x5b,0x2eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x3d,-1},
+	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x8 */
+	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x16 */
+	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x00,0x00,0x3e,-1},  /* 768x576x32 */
+	{0x67,0x2e3b,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x8 (BARCO) */
+	{0x6f,0x2e7d,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x16 (BARCO) */
+	{0x72,0x2eff,0x0000,SIS_RI_1360x1024,0x00,0x00,0x00,0x00,0x3f,-1},  /* 1360x1024x32 (BARCO) */
 	{0xff,0x0000,0xffff,0,               0x00,0x00,0x00,0x00,0x00}
 };
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/310vtbl.h linux-2.4.27-rc4/drivers/video/sis/310vtbl.h
--- linux-2.4.26/drivers/video/sis/310vtbl.h	2004-04-14 13:05:39.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/310vtbl.h	2004-07-30 16:29:20.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Register settings for SiS 315/330 series
  *
@@ -75,97 +76,97 @@ static const SiS_StStruct SiS310_SModeID
 
 static const SiS_ExtStruct  SiS310_EModeIDTable[]=
 {
-	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x? */
-	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x8 */
-        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10}, /* 640x400x8 */
-	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x8 */
-        {0x31,0x0a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x8 */
-	{0x32,0x0a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x8 */
-	{0x33,0x0a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x16 */
-	{0x34,0x2a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x16 */
-	{0x35,0x0a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11}, /* 720x480x32 */
-	{0x36,0x2a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12}, /* 720x576x32 */
-	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x? */
-	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x8 */
-	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x8 */
-	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x8 */
-	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x16 */
-	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x15 */
-	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x16 */
-	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08},
-	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x16 */
-	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00},
-	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x16 */
-	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13},
-	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x16 */
-	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a},
-	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x16 */
-	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x8  */
-	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x8  */
-  	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x8  */
-	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x16 */
-	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x16 */
- 	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x16 */
-	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x8  */
-	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x8  fstn */
-	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f}, /* 320x240x16 fstn */
-	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28}, /* 512x384x32 */
-	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10},
-	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10}, /* 640x400x32 */
-	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08}, /* 640x480x32 */
-	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00}, /* 800x600x32 */
-	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13}, /* 1024x768x32 */
-	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a}, /* 1280x1024x32 */
-	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e}, /* 1600x1200x32 */
-	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x8 */
-	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x16 */
-	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29}, /* 1920x1440x32 */
-	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x8 */
-	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x16 */
-	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f}, /* 2048x1536x32 */
-	{0x70,0x2a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x8 */
-	{0x71,0x0a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x8 */
-	{0x74,0x0a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x16 */
-	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x16 */
-	{0x76,0x2a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x32 */
-	{0x77,0x0a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37}, /* 1024x576x32 */
-	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x32 */
-	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a}, /* 1280x720x8 */
-	{0x7a,0x2a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34}, /* 800x480x16 */
-	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x8 */
-	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x16 */
-	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d}, /* 1280x960x32 */
-	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x8 */
-	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x16 */
-	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40}, /* 1280x768x32 */
-	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x8 */
-	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x16 */
-	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41}, /* 1400x1050x32*/
-	{0x29,0x0e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43}, /* 1152x864 */
-	{0x2a,0x0e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x2b,0x0e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43},
-	{0x39,0x2a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45}, /* 848x480 */
-	{0x3b,0x2a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3e,0x2a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45},
-	{0x3f,0x2a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47}, /* 856x480 */
-	{0x42,0x2a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x45,0x2a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47},
-	{0x48,0x2a1b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49}, /* 1360x768 */
-	{0x4b,0x2a3d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4e,0x2a7f,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49},
-	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25}, /* 320x200x32 */
-	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26}, /* 320x240x32 */
-	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27}, /* 400x300x32 */
-	{0x5f,0x2a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a}, /* 768x576 */
-	{0x60,0x2a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a},
-	{0x61,0x2a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a},
-	{0x14,0x0e1b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b}, /* 1280x800 */
-	{0x15,0x0e3d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b},
-	{0x16,0x0e7f,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b},
-	{0x17,0x0e1b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c}, /* 1680x1050 */
-	{0x18,0x0e3d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c},
-	{0x19,0x0e7f,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c},
-	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00}
+	{0x6a,0x2212,0x0102,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x? */
+	{0x2e,0x0a1b,0x0101,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x8 */
+        {0x2f,0x0a1b,0x0100,SIS_RI_640x400,  0x00,0x00,0x05,0x05,0x10, 0}, /* 640x400x8 */
+	{0x30,0x2a1b,0x0103,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x8 */
+        {0x31,0x4a1b,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x8 */
+	{0x32,0x4a1b,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x8 */
+	{0x33,0x4a1d,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x16 */
+	{0x34,0x6a1d,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x16 */
+	{0x35,0x4a1f,0x0000,SIS_RI_720x480,  0x00,0x00,0x06,0x06,0x11,-1}, /* 720x480x32 */
+	{0x36,0x6a1f,0x0000,SIS_RI_720x576,  0x00,0x00,0x06,0x06,0x12,-1}, /* 720x576x32 */
+	{0x37,0x0212,0x0104,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x? */
+	{0x38,0x0a1b,0x0105,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x8 */
+	{0x3a,0x0e3b,0x0107,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x8 */
+	{0x3c,0x0e3b,0x0130,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x8 */
+	{0x3d,0x0e7d,0x0131,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x16 */
+	{0x40,0x9a1c,0x010d,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x15 */
+	{0x41,0x9a1d,0x010e,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x16 */
+	{0x43,0x0a1c,0x0110,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2},
+	{0x44,0x0a1d,0x0111,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x16 */
+	{0x46,0x2a1c,0x0113,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3},
+	{0x47,0x2a1d,0x0114,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x16 */
+	{0x49,0x0a3c,0x0116,SIS_RI_1024x768, 0x00,0x00,0x00,0x07,0x13, 4},
+	{0x4a,0x0a3d,0x0117,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x16 */
+	{0x4c,0x0e7c,0x0119,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8},
+	{0x4d,0x0e7d,0x011a,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x16 */
+	{0x50,0x9a1b,0x0132,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x8  */
+	{0x51,0xba1b,0x0133,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x8  */
+  	{0x52,0xba1b,0x0134,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x8  */
+	{0x56,0x9a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x16 */
+	{0x57,0xba1d,0x0136,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x16 */
+ 	{0x58,0xba1d,0x0137,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x16 */
+	{0x59,0x9a1b,0x0138,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x8  */
+	{0x5a,0x021b,0x0138,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x8  fstn */
+	{0x5b,0x0a1d,0x0135,SIS_RI_320x240,  0x00,0x00,0x00,0x00,0x3f, 2}, /* 320x240x16 fstn */
+	{0x5c,0xba1f,0x0000,SIS_RI_512x384,  0x00,0x00,0x00,0x00,0x28, 4}, /* 512x384x32 */
+	{0x5d,0x0a1d,0x0139,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0},
+	{0x5e,0x0a1f,0x0000,SIS_RI_640x400,  0x00,0x00,0x05,0x07,0x10, 0}, /* 640x400x32 */
+	{0x62,0x0a3f,0x013a,SIS_RI_640x480,  0x00,0x00,0x05,0x05,0x08, 2}, /* 640x480x32 */
+	{0x63,0x2a3f,0x013b,SIS_RI_800x600,  0x00,0x00,0x07,0x06,0x00, 3}, /* 800x600x32 */
+	{0x64,0x0a7f,0x013c,SIS_RI_1024x768, 0x00,0x00,0x08,0x07,0x13, 4}, /* 1024x768x32 */
+	{0x65,0x0eff,0x013d,SIS_RI_1280x1024,0x00,0x00,0x00,0x00,0x1a, 8}, /* 1280x1024x32 */
+	{0x66,0x0eff,0x013e,SIS_RI_1600x1200,0x00,0x00,0x00,0x00,0x1e,10}, /* 1600x1200x32 */
+	{0x68,0x067b,0x013f,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x8 */
+	{0x69,0x06fd,0x0140,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x16 */
+	{0x6b,0x07ff,0x0141,SIS_RI_1920x1440,0x00,0x00,0x00,0x00,0x29,-1}, /* 1920x1440x32 */
+	{0x6c,0x067b,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x8 */
+	{0x6d,0x06fd,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x16 */
+	{0x6e,0x07ff,0x0000,SIS_RI_2048x1536,0x00,0x00,0x00,0x00,0x2f,-1}, /* 2048x1536x32 */
+	{0x70,0x6a1b,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x8 */
+	{0x71,0x4a1b,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x8 */
+	{0x74,0x4a1d,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x16 */
+	{0x75,0x0a3d,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x16 */
+	{0x76,0x6a1f,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x32 */
+	{0x77,0x4a1f,0x0000,SIS_RI_1024x576, 0x00,0x00,0x00,0x00,0x37,-1}, /* 1024x576x32 */
+	{0x78,0x0a3f,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x32 */
+	{0x79,0x0a3b,0x0000,SIS_RI_1280x720, 0x00,0x00,0x00,0x00,0x3a, 5}, /* 1280x720x8 */
+	{0x7a,0x6a1d,0x0000,SIS_RI_800x480,  0x00,0x00,0x07,0x07,0x34,-1}, /* 800x480x16 */
+	{0x7c,0x0e3b,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x8 */
+	{0x7d,0x0e7d,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x16 */
+	{0x7e,0x0eff,0x0000,SIS_RI_1280x960, 0x00,0x00,0x00,0x00,0x3d,-1}, /* 1280x960x32 */
+	{0x23,0x0e3b,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x8 */
+	{0x24,0x0e7d,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x16 */
+	{0x25,0x0eff,0x0000,SIS_RI_1280x768, 0x00,0x00,0x00,0x00,0x40, 6}, /* 1280x768x32 */
+	{0x26,0x0e3b,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x8 */
+	{0x27,0x0e7d,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x16 */
+	{0x28,0x0eff,0x0000,SIS_RI_1400x1050,0x00,0x00,0x00,0x00,0x41, 9}, /* 1400x1050x32*/
+	{0x29,0x4e1b,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1}, /* 1152x864 */
+	{0x2a,0x4e3d,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
+	{0x2b,0x4e7f,0x0000,SIS_RI_1152x864, 0x00,0x00,0x00,0x00,0x43,-1},
+	{0x39,0x6a1b,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1}, /* 848x480 */
+	{0x3b,0x6a3d,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1},
+	{0x3e,0x6a7f,0x0000,SIS_RI_848x480,  0x00,0x00,0x00,0x00,0x45,-1},
+	{0x3f,0x6a1b,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1}, /* 856x480 */
+	{0x42,0x6a3d,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1},
+	{0x45,0x6a7f,0x0000,SIS_RI_856x480,  0x00,0x00,0x00,0x00,0x47,-1},
+	{0x48,0x6a1b,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1}, /* 1360x768 */
+	{0x4b,0x6a3d,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1},
+	{0x4e,0x6a7f,0x0000,SIS_RI_1360x768, 0x00,0x00,0x00,0x00,0x49,-1},
+	{0x4f,0x9a1f,0x0000,SIS_RI_320x200,  0x00,0x00,0x04,0x04,0x25, 0}, /* 320x200x32 */
+	{0x53,0x9a1f,0x0000,SIS_RI_320x240,  0x00,0x00,0x04,0x04,0x26, 2}, /* 320x240x32 */
+	{0x54,0xba1f,0x0000,SIS_RI_400x300,  0x00,0x00,0x07,0x07,0x27, 3}, /* 400x300x32 */
+	{0x5f,0x6a1b,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1}, /* 768x576 */
+	{0x60,0x6a1d,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1},
+	{0x61,0x6a1f,0x0000,SIS_RI_768x576,  0x00,0x00,0x06,0x06,0x4a,-1},
+	{0x14,0x0e1b,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7}, /* 1280x800 */
+	{0x15,0x0e3d,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7},
+	{0x16,0x0e7f,0x0000,SIS_RI_1280x800, 0x00,0x00,0x00,0x00,0x4b, 7},
+	{0x17,0x0e1b,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9}, /* 1680x1050 */
+	{0x18,0x0e3d,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9},
+	{0x19,0x0e7f,0x0000,SIS_RI_1680x1050,0x00,0x00,0x00,0x00,0x4c, 9},
+	{0xff,0x0000,0x0000,0,               0x00,0x00,0x00,0x00,0x00,-1}
 };
 
 static const SiS_Ext2Struct SiS310_RefIndex[]=
@@ -187,8 +188,8 @@ static const SiS_Ext2Struct SiS310_RefIn
 	{0xc047,0x0b,0x0e,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xe */
 	{0xc047,0x0c,0x15,0x00,0x04,0x2e, 640, 480, 0x40}, /* 0xf */
 	{0x487f,0x04,0x00,0x00,0x00,0x2f, 640, 400, 0x30}, /* 0x10 */
-	{0xc04f,0x3c,0x01,0x06,0x00,0x31, 720, 480, 0x30}, /* 0x11 */
-	{0x004f,0x3d,0x03,0x06,0x00,0x32, 720, 576, 0x30}, /* 0x12 */
+	{0xc06f,0x3c,0x01,0x06,0x13,0x31, 720, 480, 0x30}, /* 0x11 */
+	{0x006f,0x3d,0x03,0x06,0x14,0x32, 720, 576, 0x30}, /* 0x12 */
 	{0x0087,0x15,0x06,0x00,0x06,0x37,1024, 768, 0x30}, /* 0x13 */
 	{0xc877,0x16,0x0b,0x06,0x06,0x37,1024, 768, 0x20}, /* 0x14 */
 	{0xc067,0x17,0x0f,0x49,0x06,0x37,1024, 768, 0x20}, /* 0x15 */
@@ -222,12 +223,12 @@ static const SiS_Ext2Struct SiS310_RefIn
 	{0x4007,0x2f,0x33,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x31 */
 	{0x4007,0x30,0x37,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x32 */
 	{0x4005,0x31,0x38,0x00,0x00,0x6c,2048,1536, 0x00}, /* 0x33 */
-	{0x0057,0x32,0x40,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x34 */
-	{0x0047,0x33,0x07,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x35 */
-	{0x0047,0x34,0x0a,0x08,0x00,0x70, 800, 480, 0x30}, /* 0x36 */
-	{0x0057,0x35,0x0b,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x37 */
-	{0x0047,0x36,0x11,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x38 */
-	{0x0047,0x37,0x16,0x09,0x00,0x71,1024, 576, 0x30}, /* 0x39 */
+	{0x0077,0x32,0x40,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x34 */
+	{0x0047,0x33,0x07,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x35 */
+	{0x0047,0x34,0x0a,0x08,0x18,0x70, 800, 480, 0x30}, /* 0x36 */
+	{0x0077,0x35,0x0b,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x37 */
+	{0x0047,0x36,0x11,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x38 */
+	{0x0047,0x37,0x16,0x09,0x19,0x71,1024, 576, 0x30}, /* 0x39 */
 	{0x1137,0x38,0x19,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3a */
 	{0x1107,0x39,0x1e,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3b */
 	{0x1307,0x3a,0x20,0x0a,0x0c,0x75,1280, 720, 0x30}, /* 0x3c */
@@ -237,14 +238,14 @@ static const SiS_Ext2Struct SiS310_RefIn
         {0x0077,0x42,0x5b,0x08,0x11,0x23,1280, 768, 0x30}, /* 0x40 */    /* 0x5b was 0x12 */
 	{0x0127,0x43,0x4d,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x41 */
 	{0x0207,0x4b,0x5a,0x08,0x0b,0x26,1400,1050, 0x30}, /* 0x42 1400x1050-75Hz */
-	{0x0107,0x44,0x19,0x00,0x00,0x29,1152, 864, 0x30}, /* 0x43 1152x864-75Hz  */
-	{0x0107,0x4a,0x1e,0x00,0x00,0x29,1152, 864, 0x30}, /* 0x44 1152x864-85Hz  */
-	{0x0087,0x45,0x57,0x00,0x00,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi  */
-	{0xc067,0x46,0x55,0x0b,0x00,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz   */
-	{0x0087,0x47,0x57,0x00,0x00,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi  */
-	{0xc047,0x48,0x57,0x00,0x00,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz   */
-	{0x0067,0x49,0x58,0x0c,0x00,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz  */
-	{0x004f,0x4d,0x03,0x06,0x00,0x5f, 768, 576, 0x30}, /* 0x4a 768x576-56Hz   */
+	{0x0127,0x44,0x19,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x43 1152x864-75Hz  */
+	{0x0127,0x4a,0x1e,0x00,0x1a,0x29,1152, 864, 0x30}, /* 0x44 1152x864-85Hz  */
+	{0x0087,0x45,0x57,0x00,0x16,0x39, 848, 480, 0x30}, /* 0x45 848x480-38Hzi  */
+	{0xc067,0x46,0x55,0x0b,0x16,0x39, 848, 480, 0x30}, /* 0x46 848x480-60Hz   */
+	{0x0087,0x47,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x47 856x480-38Hzi  */
+	{0xc067,0x48,0x57,0x00,0x17,0x3f, 856, 480, 0x30}, /* 0x48 856x480-60Hz   */
+	{0x0067,0x49,0x58,0x0c,0x1b,0x48,1360, 768, 0x30}, /* 0x49 1360x768-60Hz  */
+	{0x006f,0x4d,0x03,0x06,0x15,0x5f, 768, 576, 0x30}, /* 0x4a 768x576-56Hz   */
 	{0x0067,0x4f,0x5c,0x08,0x0d,0x14,1280, 800, 0x30}, /* 0x4b 1280x800-60Hz  */
 	{0x0067,0x50,0x5d,0x0c,0x0e,0x17,1680,1050, 0x30}, /* 0x4c 1680x1050-60Hz */
 	{0xffff,0x00,0x00,0x00,0x00,0x00,   0,   0,    0}
@@ -685,7 +686,12 @@ static SiS_VCLKDataStruct SiS310_VCLKDat
 	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
 	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
 	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
-	{ 0x5a,0x64, 65}  /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
 };
 
 static SiS_VBVCLKDataStruct SiS310_VBVCLKData[]=
@@ -788,14 +794,19 @@ static SiS_VBVCLKDataStruct SiS310_VBVCL
 	{ 0x52,0x07,149}, /* 0x59 1280x960-85  */
 	{ 0x56,0x07,156}, /* 0x5a 1400x1050-75 */
    	{ 0x70,0x29, 81}, /* 0x5b 1280x768 LCD */
-	{ 0x9c,0x62, 69}, /* 0x5c 1280x800 LCD - wrong? */
+	{ 0x45,0x25, 83}, /* 0x5c 1280x800 LCD - (was 0x9c,0x62, 69 - wrong?) */
 	{ 0xbe,0x44,121}, /* 0x5d 1680x1050 LCD */
 	{ 0x70,0x24,162}, /* 0x5e 1600x1200 LCD */
 	{ 0x52,0x27, 75}, /* 0x5f 1280x720 LCD TMDS + HDTV (correct) */
 	{ 0x63,0x46, 68}, /* 0x60 1280x768_2 */
 	{ 0x31,0x42, 79}, /* 0x61 1280x768_3 - temp */
 	{    0,   0,  0}, /* 0x62 - custom (will be filled out at run-time) */
-	{ 0x5a,0x64, 65}  /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x5a,0x64, 65}, /* 0x63 1280x720 (LCD LVDS) */
+	{ 0x70,0x28, 90}, /* 0x64 1152x864@60 */
+	{ 0x41,0xc4, 32}, /* 0x65 848x480@60 */
+	{ 0x5c,0xc6, 32}, /* 0x66 856x480@60 */
+	{ 0x76,0xe7, 27}, /* 0x67 720x480@60 */
+	{ 0x5f,0xc6, 33}, /* 0x68 720/768x576@60 */
 };
 
 static const DRAM4Type SiS310_SR15[8] = {
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/init.c linux-2.4.27-rc4/drivers/video/sis/init.c
--- linux-2.4.26/drivers/video/sis/init.c	2004-04-14 13:05:39.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/init.c	2004-07-30 16:26:57.000000000 +0000
@@ -1,8 +1,9 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Mode initializing code (CRT1 section) for
  * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661FX/740/741/M741/330/660/M660/760/M760
+ *     SiS 315/550/650/M650/651/661FX/M661FX/740/741(GX)/M741/330/660/M660/760/M760
  * (Universal module for Linux kernel framebuffer and XFree86 4.x)
  *
  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
@@ -635,47 +636,33 @@ SiS_GetModeID(int VGAEngine, ULONG VBFla
 	  else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
           break;
      case 720:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
-             else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
-          }
+          if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+          else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
           break;
      case 768:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
-          }
+          if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
 	  break;
      case 800:
-	  if(VDisplay == 600)    ModeIndex = ModeIndex_800x600[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
-	  }
+	  if(VDisplay == 600)      ModeIndex = ModeIndex_800x600[Depth];
+	  else if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
           break;
      case 848:
-          if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
-	  }
+	  if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
 	  break;
      case 856:
-          if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
-	  }
+	  if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
 	  break;
      case 1024:
-          if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
-	  else if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 576)    ModeIndex = ModeIndex_1024x576[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
-	        if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
-             }
+          if(VDisplay == 768)      ModeIndex = ModeIndex_1024x768[Depth];
+	  else if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	  else if((!(VBFlags & CRT1_LCDA)) && (VGAEngine == SIS_300_VGA)) {
+	     if(VDisplay == 600) ModeIndex = ModeIndex_1024x600[Depth];
 	  }
           break;
      case 1152:
-          if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 864)    ModeIndex = ModeIndex_1152x864[Depth];
-             else if(VGAEngine == SIS_300_VGA) {
-	        if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
-             }
+          if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+          if((!(VBFlags & CRT1_LCDA)) && (VGAEngine == SIS_300_VGA)) {
+	     if(VDisplay == 768) ModeIndex = ModeIndex_1152x768[Depth];
 	  }
 	  break;
      case 1280:
@@ -695,7 +682,7 @@ SiS_GetModeID(int VGAEngine, ULONG VBFla
 	        ModeIndex = ModeIndex_1280x720[Depth];
 	     }
 	  } else if(!(VBFlags & CRT1_LCDA)) {
-             if(VDisplay == 960)      ModeIndex = ModeIndex_1280x960[Depth];
+             if(VDisplay == 960) ModeIndex = ModeIndex_1280x960[Depth];
 	     else if(VDisplay == 768) {
 	        if(VGAEngine == SIS_300_VGA) {
 	           ModeIndex = ModeIndex_300_1280x768[Depth];
@@ -706,9 +693,9 @@ SiS_GetModeID(int VGAEngine, ULONG VBFla
 	  }
           break;
      case 1360:
+          if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
           if(!(VBFlags & CRT1_LCDA)) {
-	     if(VDisplay == 768)     ModeIndex = ModeIndex_1360x768[Depth];
-	     else if(VGAEngine == SIS_300_VGA) {
+	     if(VGAEngine == SIS_300_VGA) {
 	        if(VDisplay == 1024) ModeIndex = ModeIndex_300_1360x1024[Depth];
              }
 	  }
@@ -874,17 +861,49 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG V
 	     if(VDisplay == 480)      ModeIndex = ModeIndex_640x480[Depth];
 	     else if(VDisplay == 400) ModeIndex = ModeIndex_640x400[Depth];
 	     break;
+	case 720:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480)      ModeIndex = ModeIndex_720x480[Depth];
+		else if(VDisplay == 576) ModeIndex = ModeIndex_720x576[Depth];
+	     }
+	     break;
+	case 768:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 576) ModeIndex = ModeIndex_768x576[Depth];
+	     }
+	     break;
 	case 800:
 	     if(VDisplay == 600) ModeIndex = ModeIndex_800x600[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_800x480[Depth];
+	     }
+	     break;
+	case 848:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_848x480[Depth];
+	     }
+	     break;
+	case 856:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 480) ModeIndex = ModeIndex_856x480[Depth];
+	     }
 	     break;
 	case 1024:
 	     if(VDisplay == 768) ModeIndex = ModeIndex_1024x768[Depth];
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 576) ModeIndex = ModeIndex_1024x576[Depth];
+	     }
+	     break;
+	case 1152:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 864) ModeIndex = ModeIndex_1152x864[Depth];
+	     }
 	     break;
 	case 1280:
 	     if(VDisplay == 1024) ModeIndex = ModeIndex_1280x1024[Depth];
 	     else if(VDisplay == 768) {
-		if((LCDheight == 768) || (LCDwidth == 1680) ||
-		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		if((LCDheight == 768) ||  (LCDwidth == 1680) ||
+		   (VBFlags & VB_SISTMDS)) {
 		   if(VGAEngine == SIS_300_VGA) {
 		      ModeIndex = ModeIndex_300_1280x768[Depth];
 		   } else {
@@ -892,24 +911,28 @@ SiS_GetModeID_LCD(int VGAEngine, ULONG V
 		   }
 		}
 	     } else if(VDisplay == 960) {
-	        if((LCDheight == 960) ||
-		   ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+	        if((LCDheight == 960) || (VBFlags & VB_SISTMDS)) {
 		   ModeIndex = ModeIndex_1280x960[Depth];
 		}
 	     } else if(VGAEngine == SIS_315_VGA) {
 	        if(VDisplay == 800) {
 		   if((LCDheight == 800) || (LCDwidth == 1680) ||
-		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		      (VBFlags & VB_SISTMDS)) {
 		      ModeIndex = ModeIndex_1280x800[Depth];
 		   }
 		} else if(VDisplay == 720) {
-		   if((LCDheight == 720) || (LCDwidth == 1680) ||
-		      ((LCDheight == 1024) && (VBFlags & (VB_301|VB_301B|VB_301C|VB_302B)))) {
+		   if((LCDheight == 720) || (LCDwidth == 1680) || (LCDwidth == 1400) ||
+		      (VBFlags & VB_SISTMDS)) {
 		      ModeIndex = ModeIndex_1280x720[Depth];
 		   }
 		}
 	     }
 	     break;
+	case 1360:
+	     if(VGAEngine == SIS_315_VGA) {
+	        if(VDisplay == 768) ModeIndex = ModeIndex_1360x768[Depth];
+	     }
+	     break;
 	case 1400:
 	     if(VGAEngine == SIS_315_VGA) {
 	        if(VBFlags & (VB_301B | VB_301C | VB_302B | VB_302LV | VB_302ELV)) {
@@ -992,7 +1015,7 @@ SiS_GetModeID_TV(int VGAEngine, ULONG VB
 	case 720:
 	     if((!(VBFlags & TV_HIVISION)) && (!((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR1080I)))) {
                 if(VDisplay == 480) {
-		   if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM)))
+		   /* if((VBFlags & TV_YPBPR) || (VBFlags & (TV_NTSC | TV_PALM))) */
                       ModeIndex = ModeIndex_720x480[Depth];
                 } else if(VDisplay == 576) {
 		   if( ((VBFlags & TV_YPBPR) && (VBFlags & TV_YPBPR750P)) ||
@@ -1280,10 +1303,12 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSI
    /* (SR11 is used for DDC and in enable/disablebridge) */
    SiS_Pr->SiS_SensibleSR11 = FALSE;
    SiS_Pr->SiS_MyCR63 = 0x63;
-   if(HwInfo->jChipType >= SIS_661) {
-      SiS_Pr->SiS_SensibleSR11 = TRUE;
+   if(HwInfo->jChipType >= SIS_330) {
       SiS_Pr->SiS_MyCR63 = 0x53;
-   }
+      if(HwInfo->jChipType >= SIS_661) {
+         SiS_Pr->SiS_SensibleSR11 = TRUE;
+      }           
+   }   
 
    /* You should use the macros, not these flags directly */
 
@@ -1324,7 +1349,7 @@ SiS_GetSysFlags(SiS_Private *SiS_Pr, PSI
    }
    if(HwInfo->jChipType == SIS_760) {
       temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78);
-      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760UMA;
+      if(temp1 & 0x30) SiS_Pr->SiS_SysFlags |= SF_760LFB;
    }
 }
 
@@ -1387,7 +1412,7 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_
 void
 SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-   ULONG   temp;
+   USHORT temp;
 
    SiS_Pr->SiS_IF_DEF_LVDS = 0;
    SiS_Pr->SiS_IF_DEF_TRUMPION = 0;
@@ -1471,6 +1496,12 @@ SiSDetermineROMLayout661(SiS_Private *Si
    USHORT romversoffs, romvmaj = 1, romvmin = 0;
 
    if(HwInfo->jChipType >= SIS_661) {
+      if((ROMAddr[0x1a] == 'N') &&
+         (ROMAddr[0x1b] == 'e') &&
+         (ROMAddr[0x1c] == 'w') &&
+         (ROMAddr[0x1d] == 'V')) {
+	 return TRUE;
+      }
       romversoffs = ROMAddr[0x16] | (ROMAddr[0x17] << 8);
       if(romversoffs) {
 	 if((ROMAddr[romversoffs+1] == '.') || (ROMAddr[romversoffs+4] == '.')) {
@@ -1515,7 +1546,7 @@ SiSDetermineROMUsage(SiS_Private *SiS_Pr
 	  */
 	 SiS_Pr->SiS_UseROM = TRUE;
       } else {
-         /* 315/330 series stick to the standard */
+         /* 315/330 series stick to the standard(s) */
 	 SiS_Pr->SiS_UseROM = TRUE;
 	 if((SiS_Pr->SiS_ROMNew = SiSDetermineROMLayout661(SiS_Pr, HwInfo))) {
 	    /* Find out about LCD data table entry size */
@@ -1525,7 +1556,7 @@ SiSDetermineROMUsage(SiS_Private *SiS_Pr
 	       else if(ROMAddr[romptr + (34 * 16)] == 0xff)
 	          SiS_Pr->SiS661LCD2TableSize = 34;
 	       else if(ROMAddr[romptr + (36 * 16)] == 0xff)
-	          SiS_Pr->SiS661LCD2TableSize = 36;
+	          SiS_Pr->SiS661LCD2TableSize = 36;  /* 0.94 final */
 	    }
 	 }
       }
@@ -1641,7 +1672,7 @@ SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_
      if(rev >= 0xE0) {
 	flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x39);
 	if(flag == 0xff) SiS_Pr->SiS_VBType = VB_SIS302LV;
-	else 	 	 SiS_Pr->SiS_VBType = VB_SIS302ELV;
+	else 	 	 SiS_Pr->SiS_VBType = VB_SIS301C;  /* VB_SIS302ELV; */
      } else if(rev >= 0xD0) {
 	SiS_Pr->SiS_VBType = VB_SIS301LV;
      }
@@ -1649,95 +1680,6 @@ SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_
 }
 
 /*********************************************/
-/*            HELPER: GetDRAMSize            */
-/*********************************************/
-
-#ifndef LINUX_XF86
-static ULONG
-GetDRAMSize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
-{
-  ULONG   AdapterMemorySize = 0;
-#ifdef SIS315H
-  USHORT  counter;
-#endif
-
-  switch(HwInfo->jChipType) {
-#ifdef SIS315H
-  case SIS_315H:
-  case SIS_315:
-  case SIS_315PRO:
-    	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-	AdapterMemorySize = 1 << ((counter & 0xF0) >> 4);
-	counter >>= 2;
-	counter &= 0x03;
-	if(counter == 0x02) {
-		AdapterMemorySize += (AdapterMemorySize / 2);      /* DDR asymetric */
-	} else if(counter != 0) {
-		AdapterMemorySize <<= 1;                           /* SINGLE_CHANNEL_2_RANK or DUAL_CHANNEL_1_RANK */
-	}
-	AdapterMemorySize *= (1024*1024);
-        break;
-
-  case SIS_330:
-    	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14);
-	AdapterMemorySize = 1 << ((counter & 0xF0) >> 4);
-	counter &= 0x0c;
-	if(counter != 0) {
-		AdapterMemorySize <<= 1;
-	}
-	AdapterMemorySize *= (1024*1024);
-	break;
-
-  case SIS_550:
-  case SIS_650:
-  case SIS_740:
-  	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
-      	counter++;
-      	AdapterMemorySize = counter * 4;
-      	AdapterMemorySize *= (1024*1024);
-	break;
-
-  case SIS_661:
-  case SIS_741:
-        counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
-	AdapterMemorySize = 1 << counter;
-      	AdapterMemorySize *= (1024*1024);
-        break;
-
-  case SIS_660:
-  case SIS_760:
-        counter = (SiS_GetReg(SiS_Pr->SiS_P3c4,0x79) & 0xf0) >> 4;
-	if(counter) {
-	   AdapterMemorySize = 1 << counter;
-      	   AdapterMemorySize *= (1024*1024);
-	}
-	counter = SiS_GetReg(SiS_Pr->SiS_P3c4,0x78) & 0x30;
-	if(counter) {
-	   if(counter == 0x10) AdapterMemorySize += (32 * 1024 * 1024);
-	   else		       AdapterMemorySize += (64 * 1024 * 1024);
-	}
-	break;
-#endif
-
-#ifdef SIS300
-  case SIS_300:
-  case SIS_540:
-  case SIS_630:
-  case SIS_730:
-      	AdapterMemorySize = SiS_GetReg(SiS_Pr->SiS_P3c4,0x14) & 0x3F;
-      	AdapterMemorySize++;
-      	AdapterMemorySize *= (1024*1024);
-	break;
-#endif
-  default:
-        break;
-  }
-
-  return AdapterMemorySize;
-}
-#endif
-
-/*********************************************/
 /*           HELPER: Check RAM size          */
 /*********************************************/
 
@@ -1746,8 +1688,8 @@ static BOOLEAN
 SiS_CheckMemorySize(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
                     USHORT ModeNo, USHORT ModeIdIndex)
 {
+  USHORT AdapterMemSize = HwInfo->ulVideoMemorySize / (1024*1024);
   USHORT memorysize,modeflag;
-  ULONG  temp;
 
   if(SiS_Pr->UseCustomMode) {
      modeflag = SiS_Pr->CModeFlag;
@@ -1763,11 +1705,8 @@ SiS_CheckMemorySize(SiS_Private *SiS_Pr,
   memorysize >>= MemorySizeShift;		/* Get required memory size */
   memorysize++;
 
-  temp = GetDRAMSize(SiS_Pr, HwInfo);       	/* Get adapter memory size (in MB) */
-  temp /= (1024*1024);
-
-  if(temp < memorysize) return(FALSE);
-  else return(TRUE);
+  if(AdapterMemSize < memorysize) return FALSE;
+  return TRUE;
 }
 #endif
 
@@ -1781,14 +1720,14 @@ SiS_Get310DRAMType(SiS_Private *SiS_Pr, 
 {
    UCHAR data, temp;
 
-   if(*SiS_Pr->pSiS_SoftSetting & SoftDRAMType) {
-     data = *SiS_Pr->pSiS_SoftSetting & 0x03;
+   if((*SiS_Pr->pSiS_SoftSetting) & SoftDRAMType) {
+     data = (*SiS_Pr->pSiS_SoftSetting) & 0x03;
    } else {
-     if(HwInfo->jChipType >= SIS_660) {
-        /* data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; */
-	data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
-     } else if(HwInfo->jChipType >= SIS_661) {
-        data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07;
+     if(HwInfo->jChipType >= SIS_661) {
+        data = SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0x07; 
+	if(SiS_Pr->SiS_ROMNew) {
+	   data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
+	}
      } else if(IS_SIS550650740) {
         data = SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x07;
      } else {	/* 315, 330 */
@@ -1815,10 +1754,14 @@ SiS_Get310DRAMType(SiS_Private *SiS_Pr, 
 USHORT
 SiS_GetMCLK(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
+  UCHAR  *ROMAddr  = HwInfo->pjVirtualRomBase;
   USHORT index;
 
   index = SiS_Get310DRAMType(SiS_Pr, HwInfo);
   if(HwInfo->jChipType >= SIS_661) {
+     if(SiS_Pr->SiS_ROMNew) {
+        return((USHORT)(SISGETROMW((0x90 + (index * 5) + 3))));
+     }
      return(SiS_Pr->SiS_MCLKData_0[index].CLOCK);
   } else if(index >= 4) {
      index -= 4;
@@ -1844,20 +1787,17 @@ SiS_ClearBuffer(SiS_Private *SiS_Pr, PSI
 
   if(SiS_Pr->SiS_ModeType >= ModeEGA) {
      if(ModeNo > 0x13) {
-        AdapterMemorySize = GetDRAMSize(SiS_Pr, HwInfo);
-        SiS_SetMemory(VideoMemoryAddress,AdapterMemorySize,0);
+        SiS_SetMemory(VideoMemoryAddress, AdapterMemorySize, 0);
      } else {
         pBuffer = (USHORT *)VideoMemoryAddress;
-        for(i=0; i<0x4000; i++)
-           pBuffer[i] = 0x0000;
+        for(i=0; i<0x4000; i++) pBuffer[i] = 0x0000;
      }
   } else {
-     pBuffer = (USHORT *)VideoMemoryAddress;
      if(SiS_Pr->SiS_ModeType < ModeCGA) {
-        for(i=0; i<0x4000; i++)
-           pBuffer[i] = 0x0720;
+        pBuffer = (USHORT *)VideoMemoryAddress;
+        for(i=0; i<0x4000; i++) pBuffer[i] = 0x0720;
      } else {
-        SiS_SetMemory(VideoMemoryAddress,0x8000,0);
+        SiS_SetMemory(VideoMemoryAddress, 0x8000, 0);
      }
   }
 }
@@ -1913,10 +1853,10 @@ SiS_GetModePtr(SiS_Private *SiS_Pr, USHO
    UCHAR index;
 
    if(ModeNo <= 0x13) {
-     	index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
+      index = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_StTableIndex;
    } else {
-     	if(SiS_Pr->SiS_ModeType <= 0x02) index = 0x1B;    /* 02 -> ModeEGA  */
-     	else index = 0x0F;
+      if(SiS_Pr->SiS_ModeType <= ModeEGA) index = 0x1B;   
+      else index = 0x0F;
    }
    return index;
 }
@@ -1931,7 +1871,7 @@ SiS_DoLowModeTest(SiS_Private *SiS_Pr, U
     USHORT temp,temp1,temp2;
 
     if((ModeNo != 0x03) && (ModeNo != 0x10) && (ModeNo != 0x12))
-       return(1);
+       return(TRUE);
     temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x11);
     SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x11,0x80);
     temp1 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x00);
@@ -1941,13 +1881,13 @@ SiS_DoLowModeTest(SiS_Private *SiS_Pr, U
     SiS_SetReg(SiS_Pr->SiS_P3d4,0x11,temp);
     if((HwInfo->jChipType >= SIS_315H) ||
        (HwInfo->jChipType == SIS_300)) {
-       if(temp2 == 0x55) return(0);
-       else return(1);
+       if(temp2 == 0x55) return(FALSE);
+       else return(TRUE);
     } else {
-       if(temp2 != 0x55) return(1);
+       if(temp2 != 0x55) return(TRUE);
        else {
           SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x35,0x01);
-          return(0);
+          return(FALSE);
        }
     }
 }
@@ -3002,7 +2942,7 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
 
   data = 0;
   if(ModeNo > 0x13) {
-     if(SiS_Pr->SiS_ModeType > 0x02) {
+     if(SiS_Pr->SiS_ModeType > ModeEGA) {
         data |= 0x02;
         data |= ((SiS_Pr->SiS_ModeType - ModeVGA) << 2);
      }
@@ -3065,7 +3005,7 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
      SiS_SetReg(SiS_Pr->SiS_P3c4,0x17,data);
 
   } else if( (HwInfo->jChipType == SIS_330) ||
-             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760UMA))) {
+             ((HwInfo->jChipType == SIS_760) && (SiS_Pr->SiS_SysFlags & SF_760LFB))) {
 
      data = SiS_Get310DRAMType(SiS_Pr, HwInfo);
      if(HwInfo->jChipType == SIS_330) {
@@ -3109,7 +3049,7 @@ SiS_SetCRT1ModeRegs(SiS_Private *SiS_Pr,
 	      if(data2 >= 0x127)      data = 0xba;
 	      else                    data = 0x7a;
 	   }
-	} else {
+	} else {  /* 760+LFB */
 	   if     (data2 >= 0x190) data = 0xba;
 	   else if(data2 >= 0xff)  data = 0x7a;
 	   else if(data2 >= 0xd3)  data = 0x3a;
@@ -3379,8 +3319,6 @@ SiS_SetCRT1Group(SiS_Private *SiS_Pr, PS
   }
 }
 
-
-
 /*********************************************/
 /*         HELPER: RESET VIDEO BRIDGE        */
 /*********************************************/
@@ -5105,10 +5043,7 @@ sisfb_gettotalfrommode(SiS_Private *SiS_
 int
 sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 			 unsigned char modeno, unsigned char rateindex,
-			 ULONG *left_margin, ULONG *right_margin, 
-			 ULONG *upper_margin, ULONG *lower_margin,
-			 ULONG *hsync_len, ULONG *vsync_len,
-			 ULONG *sync, ULONG *vmode)
+			 struct fb_var_screeninfo *var)
 {
     USHORT ModeNo = modeno;
     USHORT ModeIdIndex = 0, index = 0;
@@ -5196,15 +5131,15 @@ sisfb_mode_rate_to_ddata(SiS_Private *Si
 	 /* Terrible hack, but the correct CRTC data for
 	  * these modes only produces a black screen...
 	  */
-       *left_margin = (400 - 376);
-       *right_margin = (328 - 320);
-       *hsync_len = (376 - 328);
+       var->left_margin = (400 - 376);
+       var->right_margin = (328 - 320);
+       var->hsync_len = (376 - 328);
 
     } else {
 
-       *left_margin = D * 8;
-       *right_margin = F * 8;
-       *hsync_len = C * 8;
+       var->left_margin = D * 8;
+       var->right_margin = F * 8;
+       var->hsync_len = C * 8;
 
     }
 
@@ -5266,47 +5201,47 @@ sisfb_mode_rate_to_ddata(SiS_Private *Si
 
     D = B - F - C;
       
-    *upper_margin = D;
-    *lower_margin = F;
-    *vsync_len = C;
+    var->upper_margin = D;
+    var->lower_margin = F;
+    var->vsync_len = C;
 
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x8000)
-       *sync &= ~FB_SYNC_VERT_HIGH_ACT;
+       var->sync &= ~FB_SYNC_VERT_HIGH_ACT;
     else
-       *sync |= FB_SYNC_VERT_HIGH_ACT;
+       var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x4000)       
-       *sync &= ~FB_SYNC_HOR_HIGH_ACT;
+       var->sync &= ~FB_SYNC_HOR_HIGH_ACT;
     else
-       *sync |= FB_SYNC_HOR_HIGH_ACT;
+       var->sync |= FB_SYNC_HOR_HIGH_ACT;
 		
-    *vmode = FB_VMODE_NONINTERLACED;
+    var->vmode = FB_VMODE_NONINTERLACED;
     if(SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].Ext_InfoFlag & 0x0080)
-       *vmode = FB_VMODE_INTERLACED;
+       var->vmode = FB_VMODE_INTERLACED;
     else {
-      j = 0;
-      while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
+       j = 0;
+       while(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID != 0xff) {
           if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeID ==
 	                  SiS_Pr->SiS_RefIndex[RefreshRateTableIndex].ModeID) {
               if(SiS_Pr->SiS_EModeIDTable[j].Ext_ModeFlag & DoubleScanMode) {
-	      	  *vmode = FB_VMODE_DOUBLE;
+	      	  var->vmode = FB_VMODE_DOUBLE;
               }
 	      break;
           }
 	  j++;
-      }
+       }
     }       
 
-    if((*vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+    if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
 #if 0  /* Do this? */
-       *upper_margin <<= 1;
-       *lower_margin <<= 1;
-       *vsync_len <<= 1;
-#endif
-    } else if((*vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-       *upper_margin >>= 1;
-       *lower_margin >>= 1;
-       *vsync_len >>= 1;
+       var->upper_margin <<= 1;
+       var->lower_margin <<= 1;
+       var->vsync_len <<= 1;
+#endif
+    } else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       var->upper_margin >>= 1;
+       var->lower_margin >>= 1;
+       var->vsync_len >>= 1;
     }
 
     return 1;       
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/init.h linux-2.4.27-rc4/drivers/video/sis/init.h
--- linux-2.4.26/drivers/video/sis/init.h	2004-04-14 13:05:39.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/init.h	2004-07-30 16:26:58.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Data and prototypes for init.c
  *
@@ -253,8 +254,8 @@ static const SiS_ModeResInfoStruct SiS_M
 	{ 1152, 768, 8,16},   /* 0x1a */
 	{  768, 576, 8,16},   /* 0x1b */
 	{ 1360,1024, 8,16},   /* 0x1c */
-	{ 1280, 800, 8,16},   /* 0x1d */
-	{ 1680,1050, 8,16}    /* 0x1e */
+	{ 1680,1050, 8,16},   /* 0x1d */
+	{ 1280, 800, 8,16}    /* 0x1e */ 
 };
 
 static SiS_StandTableStruct SiS_StandTable[]=
@@ -840,7 +841,8 @@ static const SiS_TVDataStruct  SiS_ExtPA
  {   36,  25,1060, 648,1270, 530, 438,   0, 438,0xeb,0x05,0x25,0x16},  /* 800x600, 400x300 - better */
  {    3,   2,1080, 619,1270, 540, 438,   0, 438,0xf3,0x00,0x1d,0x20},  /* 720x576 */
  {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 */
- {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20}   /* 1024x768 (for NTSC equ) */
+ {    1,   1,1170, 821,1270, 520, 686,   0, 686,0xF3,0x00,0x1D,0x20},  /* 1024x768 (for NTSC equ) */
+ {    9,   4, 848, 528,1270, 530,   0,   0,  50,0xf5,0xfb,0x1b,0x2a}   /* 720x480 test */
 };
 
 static const SiS_TVDataStruct  SiS_StNTSCData[] =
@@ -929,7 +931,10 @@ static const SiS_TVDataStruct  SiS_Ext75
  {  143,  70, 0x39c,0x189,0x4f6,0x1b8,0x05c,  0, 0x05c, 0x00,0x00,0x00,0x00},
  {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 640x480  */
  {    5,   4, 0x5d8,0x29e,0x500,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 800x600  */
+#if 0 
  {    2,   1, 0x35a,0x1f7,0x4f6,0x1e0,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x480  */
+#endif
+ {   99,  32, 0x320,0x1fe,0x500,0x2d0,   50,  0,     0, 0x00,0x00,0x00,0x00},  /* 720x480 test */ 
  {   68,  64, 0x55f,0x346,0x500,0x2a8,0x27e,  0,     0, 0x00,0x00,0x00,0x00},  /* 1024x768 */
  {    5,   2, 0x3a7,0x226,0x500,0x2a8,    0,128,     0, 0x00,0x00,0x00,0x00},  /* 720x576  */
  {   25,  24, 0x5d8,0x2f3,0x460,0x2a8,   50,  0,     0, 0x00,0x00,0x00,0x00}   /* 1280x720 */
@@ -1057,17 +1062,30 @@ static const SiS_LCDDataStruct  SiS_StLC
 	{   1,    1, 1688, 1066, 1688, 1066 }
 };
 
+#undef SISUSE6330MODES
+
 static const SiS_LCDDataStruct  SiS_ExtLCD1400x1050Data[] =
 {
-	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 */
+#ifdef SISUSE6330MODES
+	{ 211,   60, 1260,  410, 1688, 1066 }, /* 640x400 (6330) */
+#else	
+	{ 211,  100, 2100,  408, 1688, 1066 }, /* 640x400 (6325) WORKS */
+#endif	
 	{ 211,   64, 1536,  358, 1688, 1066 },
 	{ 211,  100, 2100,  408, 1688, 1066 },
 	{ 211,   64, 1536,  358, 1688, 1066 },
-	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 */
-	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 */
-	{ 211,  128, 1400,  776, 1688, 1066 },
-	{ 211,  205, 1680, 1041, 1688, 1066 },
-	{   1,    1, 1688, 1066, 1688, 1066 }
+#ifdef SISUSE6330MODES
+	{ 211,   80, 1400,  490, 1688, 1066 }, /* 640x480 (6330) */
+	{ 211,  117, 1638,  613, 1688, 1066 }, /* 800x600 (6330) */
+#else
+	{ 211,   48,  840,  488, 1688, 1066 }, /* 640x480 (6325) WORKS */
+	{ 211,   72, 1008,  609, 1688, 1066 }, /* 800x600 (6325) WORKS */
+#endif	
+	{ 211,  128, 1400,  776, 1688, 1066 }, /* 1024x768 */
+	{ 211,  205, 1680, 1041, 1688, 1066 }, /* 1280x1024 - not used (always unscaled) */
+	{   1,    1, 1688, 1066, 1688, 1066 }, /* 1400x1050 */
+	{   0,    0,    0,    0,    0,    0 }, /* kludge */
+	{ 211,  120, 1400,  730, 1688, 1066 }  /* 1280x720 */
 };
 
 static const SiS_LCDDataStruct  SiS_LCD1680x1050Data[] =
@@ -1097,21 +1115,29 @@ static const SiS_LCDDataStruct  SiS_StLC
 	{ 4,  1,1080, 625, 2160, 1250 },
 	{ 5,  2,1350, 800, 2160, 1250 },
 	{135,88,1600,1100, 2160, 1250 },
-	{135,88,1600,1100, 2160, 1250 },
+	{72, 49,1680,1092, 2160, 1250 }, 
 	{ 1,  1,2160,1250, 2160, 1250 }
 };
 
 static const SiS_LCDDataStruct  SiS_ExtLCD1600x1200Data[] =
 {
-	{27, 4, 800, 500, 2160, 1250 },
+#ifndef SISUSE6330MODES
+	{72,11, 990, 422, 2160, 1250 }, /* 640x400 (6330) */
+#else	
+	{27, 4, 800, 500, 2160, 1250 }, /* 640x400 (6235) */
+#endif	
 	{27, 4, 800, 500, 2160, 1250 },
 	{ 6, 1, 900, 500, 2160, 1250 },
 	{ 6, 1, 900, 500, 2160, 1250 },
-	{27, 1, 800, 500, 2160, 1250 },
+#ifndef SISUSE6330MODES
+	{45, 8, 960, 505, 2160, 1250 }, /* 640x480 (6330) */
+#else
+	{27, 1, 800, 500, 2160, 1250 }, /* 640x480 (6325) */
+#endif	
 	{ 4, 1,1080, 625, 2160, 1250 },
 	{ 5, 2,1350, 800, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 },
-	{27,16,1500,1064, 2160, 1250 },
+	{27,16,1500,1064, 2160, 1250 }, /* 1280x1024 */
+	{72,49,1680,1092, 2160, 1250 }, /* 1400x1050 (6330, was not supported on 6325) */
 	{ 1, 1,2160,1250, 2160, 1250 }
 };
 
@@ -1129,13 +1155,22 @@ static const SiS_LCDDataStruct  SiS_NoSc
         { 1, 1,2160,1250,2160,1250 },  /* 0x09: 1600x1200 */
 	{ 1, 1,1800,1000,1800,1000 },  /* 0x0a: 1280x960  */
 	{ 1, 1,1688,1066,1688,1066 },  /* 0x0b: 1400x1050 */
-	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS)  */
-	{ 1, 1,1408, 816,1408, 816 },  /* 0x0d: 1280x800  */
+	{ 1, 1,1650, 750,1650, 750 },  /* 0x0c: 1280x720 (TMDS, projector)  */
+	{ 1, 1,1656, 841,1656, 841 },  /* 0x0d: 1280x800 (was: 1408, 816) */
 	{ 1, 1,1900,1066,1900,1066 },  /* 0x0e: 1680x1050 (LVDS) */
 	{ 1, 1,1408, 806,1408, 806 },  /* 0x0f: 1280x768_2 */
 	{ 1, 1,1664, 798,1664, 798 },  /* 0x10: 1280x768_3 */
 	{ 1, 1,1688, 802,1688, 802 },  /* 0x11: 1280x768: Std, TMDS only */
-	{ 1, 1,1344, 806,1344, 806 }   /* 0x12: 1280x720 (LVDS)  */
+	{ 1, 1,1344, 806,1344, 806 },  /* 0x12: 1280x720 (LVDS)  */
+	{ 1, 1, 896, 497, 896, 497 },  /* 0x13: 720x480 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x14: 720x576 */
+	{ 1, 1, 912, 597, 912, 597 },  /* 0x15: 768x576 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x16: 848x480 */
+	{ 1, 1,1064, 497,1064, 497 },  /* 0x17: 856x480 */
+	{ 1, 1,1056, 497,1056, 497 },  /* 0x18: 800x480 */
+	{ 1, 1,1328, 739,1328, 739 },  /* 0x19: 1024x576 */
+	{ 1, 1,1680, 892,1680, 892 },  /* 0x1a: 1152x864 */
+	{ 1, 1,1808, 808,1808, 808 }   /* 0x1b: 1360x768 */
 };
 
 
@@ -2387,10 +2422,7 @@ int    sisfb_mode_rate_to_dclock(SiS_Pri
 			      unsigned char modeno, unsigned char rateindex);
 int    sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 			 unsigned char modeno, unsigned char rateindex,
-			 ULONG *left_margin, ULONG *right_margin,
-			 ULONG *upper_margin, ULONG *lower_margin,
-			 ULONG *hsync_len, ULONG *vsync_len,
-			 ULONG *sync, ULONG *vmode);
+			 struct fb_var_screeninfo *var);
 BOOLEAN sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/init301.c linux-2.4.27-rc4/drivers/video/sis/init301.c
--- linux-2.4.26/drivers/video/sis/init301.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/init301.c	2004-07-30 16:25:06.000000000 +0000
@@ -1,9 +1,10 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Mode initializing code (CRT2 section)
  * for SiS 300/305/540/630/730 and
- *     SiS 315/550/650/M650/651/661FX/M661xX/740/741/M741/330/660/M660/760/M760
- * (Universal module for Linux kernel framebuffer and XFree86 4.x)
+ *     SiS 315/550/650/M650/651/661FX/M661xX/740/741(GX)/M741/330/660/M660/760/M760
+ * (Universal module for Linux kernel framebuffer and XFree86/X.org 4.x)
  *
  * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
  *
@@ -115,7 +116,10 @@ SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_H
 static void
 SiS_SetRegSR11ANDOR(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT DataAND, USHORT DataOR)
 {
-   if(HwInfo->jChipType >= SIS_661) DataAND &= 0x0f;
+   if(HwInfo->jChipType >= SIS_661) {
+      DataAND &= 0x0f;
+      DataOR  &= 0x0f;
+   }
    SiS_SetRegANDOR(SiS_Pr->SiS_P3c4,0x11,DataAND,DataOR);
 }
 
@@ -137,7 +141,7 @@ GetLCDStructPtr661(SiS_Private *SiS_Pr, 
 
    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
       myptr = (UCHAR *)SiS_LCDStruct661;
-      romindex = SISGETROMW(0x100);  /* 10c, 0.93: 10e */
+      romindex = SISGETROMW(0x100);  
       if(romindex) {
          romindex += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x7d) & 0x1f) * 26);
          myptr = &ROMAddr[romindex];
@@ -157,7 +161,7 @@ GetLCDStructPtr661_2(SiS_Private *SiS_Pr
     */
 
    if((SiS_Pr->SiS_ROMNew) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
-      romptr = SISGETROMW(0x102);  /* 2ad */
+      romptr = SISGETROMW(0x102);  
       romptr += ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x36) >> 4) * SiS_Pr->SiS661LCD2TableSize);
    }
 
@@ -275,10 +279,11 @@ SiS_GetRatePtr(SiS_Private *SiS_Pr, USHO
   /* Do NOT check for UseCustomMode here, will skrew up FIFO */
   if(ModeNo == 0xfe) return 0;
 
-  if(ModeNo <= 0x13)
+  if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
-  else
+  } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+  }
 
   if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
@@ -474,7 +479,6 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
          Delay = 3;
       } else {
          if(DelayTime >= 2) DelayTime -= 2;
-
          if(!(DelayTime & 0x01)) {
        	    Delay = SiS_Pr->SiS_PanelDelayTbl[DelayIndex].timer[0];
          } else {
@@ -482,15 +486,12 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
          }
 	 if(SiS_Pr->SiS_UseROM) {
             if(ROMAddr[0x220] & 0x40) {
-               if(!(DelayTime & 0x01)) {
-	          Delay = (USHORT)ROMAddr[0x225];
-               } else {
-	    	  Delay = (USHORT)ROMAddr[0x226];
-               }
+               if(!(DelayTime & 0x01)) Delay = (USHORT)ROMAddr[0x225];
+               else 	    	       Delay = (USHORT)ROMAddr[0x226];
             }
          }
       }
-      SiS_ShortDelay(SiS_Pr,Delay);
+      SiS_ShortDelay(SiS_Pr, Delay);
 
 #endif  /* SIS300 */
 
@@ -498,7 +499,9 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
 
 #ifdef SIS315H
 
-      if(HwInfo->jChipType >= SIS_661) {
+      if((HwInfo->jChipType >= SIS_661)    ||
+         (HwInfo->jChipType <= SIS_315PRO) ||
+	 (HwInfo->jChipType == SIS_330)) {
 
          if(!(DelayTime & 0x01)) {
 	    SiS_DDC2Delay(SiS_Pr, 0x1000);
@@ -506,11 +509,9 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
 	    SiS_DDC2Delay(SiS_Pr, 0x4000);
          }
 
-      } else if(HwInfo->jChipType >= SIS_330) return;
-
-      if((SiS_Pr->SiS_IF_DEF_LVDS == 1) ||
+      } else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {			/* 315 series, LVDS; Special */
+	 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) {			/* 315 series, LVDS; Special */
 
          if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
             PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
@@ -541,7 +542,7 @@ SiS_PanelDelay(SiS_Private *SiS_Pr, PSIS
                   }
                }
             }
-	    SiS_ShortDelay(SiS_Pr,Delay);
+	    SiS_ShortDelay(SiS_Pr, Delay);
 	 }
 
       } else if(SiS_Pr->SiS_VBType & VB_SISVB) {			/* 315 series, all bridges */
@@ -584,7 +585,6 @@ SiS_WaitRetrace1(SiS_Private *SiS_Pr)
   USHORT watchdog;
 
   if(SiS_GetReg(SiS_Pr->SiS_P3c4,0x1f) & 0xc0) return;
-
   if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x17) & 0x80)) return;
 
   watchdog = 65535;
@@ -640,10 +640,10 @@ SiS_VBWait(SiS_Private *SiS_Pr)
        tempal = SiS_GetRegByte(SiS_Pr->SiS_P3da);
        if(temp & 0x01) {
           if((tempal & 0x08))  continue;
-          if(!(tempal & 0x08)) break;
+          else break;
        } else {
           if(!(tempal & 0x08)) continue;
-          if((tempal & 0x08))  break;
+          else break;
        }
     }
     temp ^= 0x01;
@@ -664,12 +664,14 @@ SiS_VBLongWait(SiS_Private *SiS_Pr)
 /*               HELPER: MISC                */
 /*********************************************/
 
+#ifdef SIS300
 static BOOLEAN
 SiS_Is301B(SiS_Private *SiS_Pr)
 {
   if(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01) >= 0xb0) return TRUE;
   return FALSE;
 }
+#endif
 
 static BOOLEAN
 SiS_CRT2IsLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
@@ -715,6 +717,16 @@ SiS_IsVAMode(SiS_Private *SiS_Pr, PSIS_H
   return FALSE;
 }
 
+#ifdef SIS315H
+static BOOLEAN
+SiS_IsVAorLCD(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
+{
+  if(SiS_IsVAMode(SiS_Pr,HwInfo))   return TRUE;
+  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) return TRUE;
+  return FALSE;  
+}
+#endif
+
 static BOOLEAN
 SiS_IsDualLink(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
@@ -754,11 +766,8 @@ SiS_LCDAEnabled(SiS_Private *SiS_Pr, PSI
 static BOOLEAN
 SiS_WeHaveBacklightCtrl(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT flag;
-
   if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
-     flag = SiS_GetReg(SiS_Pr->SiS_P3d4,0x79);
-     if(flag & 0x10) return TRUE;
+     if(SiS_GetReg(SiS_Pr->SiS_P3d4,0x79) & 0x10) return TRUE;
   }
   return FALSE;
 }
@@ -854,12 +863,12 @@ SiS_BridgeIsOn(SiS_Private *SiS_Pr)
   USHORT flag;
 
   if(SiS_Pr->SiS_IF_DEF_LVDS == 1) {
-     return FALSE;
+     return TRUE;
   } else if(SiS_Pr->SiS_VBType & VB_SISVB) {
      flag = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x00);
-     if((flag == 1) || (flag == 2)) return FALSE;
+     if((flag == 1) || (flag == 2)) return TRUE;
   }
-  return TRUE;
+  return FALSE;
 }
 
 static BOOLEAN
@@ -867,21 +876,21 @@ SiS_BridgeIsEnabled(SiS_Private *SiS_Pr,
 {
   USHORT flag;
 
-  if(!(SiS_BridgeIsOn(SiS_Pr))) {
+  if(SiS_BridgeIsOn(SiS_Pr)) {
      flag = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
      if(HwInfo->jChipType < SIS_315H) {
        flag &= 0xa0;
-       if((flag == 0x80) || (flag == 0x20)) return FALSE;
+       if((flag == 0x80) || (flag == 0x20)) return TRUE;
      } else {
        flag &= 0x50;
-       if((flag == 0x40) || (flag == 0x10)) return FALSE;
+       if((flag == 0x40) || (flag == 0x10)) return TRUE;
      }
   }
-  return TRUE;
+  return FALSE;
 }
 
 static BOOLEAN
-SiS_BridgeInSlave(SiS_Private *SiS_Pr)
+SiS_BridgeInSlavemode(SiS_Private *SiS_Pr)
 {
   USHORT flag1;
 
@@ -942,7 +951,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
   SiS_Pr->SiS_ModeType = modeflag & ModeInfoFlag;
 
   tempbx = 0;
-  if(SiS_BridgeIsOn(SiS_Pr) == 0) {
+  if(SiS_BridgeIsOn(SiS_Pr)) {
     	temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
 #if 0
    	if(HwInfo->jChipType < SIS_661) {
@@ -970,7 +979,7 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
 		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x31,0xbf);
 	      }
 	      if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & (DriverMode >> 8))) {
-	         /* Reset LCDA setting */
+	         /* Reset LCDA setting if not driver mode */
 		 SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x38,0xfc);
 	      }
 	      if(IS_SIS650) {
@@ -1125,9 +1134,9 @@ SiS_GetVBInfo(SiS_Private *SiS_Pr, USHOR
 	         }
               }
       	   } else {
-              if(!(SiS_BridgeIsEnabled(SiS_Pr,HwInfo))) {
+              if(SiS_BridgeIsEnabled(SiS_Pr,HwInfo)) {
           	 if(!(tempbx & DriverMode)) {
-            	    if(SiS_BridgeInSlave(SiS_Pr)) {
+            	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
 		       tempbx |= SetSimuScanMode;
             	    }
                  }
@@ -1437,21 +1446,49 @@ SiS_GetLCDInfoBIOS(SiS_Private *SiS_Pr, 
 {
 #ifdef SIS315H
    UCHAR  *ROMAddr;
+   USHORT temp;   
+   
+#ifdef TWDEBUG
+   xf86DrvMsg(0, X_INFO, "Paneldata driver: [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
+      	SiS_Pr->PanelHT, SiS_Pr->PanelVT, 
+	SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
+	SiS_Pr->PanelVRS, SiS_Pr->PanelVRE, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif   
 
    if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
-      SiS_Pr->PanelHT  = SISGETROMW(6);
-      SiS_Pr->PanelVT  = SISGETROMW(8);
+      if((temp = SISGETROMW(6)) != SiS_Pr->PanelHT) {
+         SiS_Pr->SiS_NeedRomModeData = TRUE;
+	 SiS_Pr->PanelHT  = temp;
+      }
+      if((temp = SISGETROMW(8)) != SiS_Pr->PanelVT) {
+         SiS_Pr->SiS_NeedRomModeData = TRUE;
+         SiS_Pr->PanelVT  = temp;
+      }
       SiS_Pr->PanelHRS = SISGETROMW(10);
       SiS_Pr->PanelHRE = SISGETROMW(12);
       SiS_Pr->PanelVRS = SISGETROMW(14);
       SiS_Pr->PanelVRE = SISGETROMW(16);
       SiS_Pr->PanelVCLKIdx315 = VCLK_CUSTOM_315;
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].CLOCK =
-	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)ROMAddr[18];
+	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].CLOCK = (USHORT)((UCHAR)ROMAddr[18]);
       SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
 	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_A = ROMAddr[19];
-      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2B =
+      SiS_Pr->SiS_VCLKData[VCLK_CUSTOM_315].SR2C =
 	 SiS_Pr->SiS_VBVCLKData[VCLK_CUSTOM_315].Part4_B = ROMAddr[20];
+	 
+#ifdef TWDEBUG
+      xf86DrvMsg(0, X_INFO, "Paneldata BIOS:  [%d %d] [H %d %d] [V %d %d] [C %d 0x%02x 0x%02x]\n",
+      	SiS_Pr->PanelHT, SiS_Pr->PanelVT, 
+	SiS_Pr->PanelHRS, SiS_Pr->PanelHRE,
+	SiS_Pr->PanelVRS, SiS_Pr->PanelVRE, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].CLOCK,
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_A, 
+	SiS_Pr->SiS_VBVCLKData[SiS_Pr->PanelVCLKIdx315].Part4_B);
+#endif	 
+
    }
 #endif
 }
@@ -1478,6 +1515,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
   SiS_Pr->PanelHRE        = 999; /* HSync end */
   SiS_Pr->PanelVRS        = 999; /* VSync start */
   SiS_Pr->PanelVRE        = 999; /* VSync end */
+  SiS_Pr->SiS_NeedRomModeData = FALSE;
 
   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))) return;
 
@@ -1491,6 +1529,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
   }
 
   temp = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
+  if(!temp) return;
 
   if((HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
      SiS_Pr->SiS_LCDTypeInfo = (SiS_GetReg(SiS_Pr->SiS_P3d4,0x39) & 0x7c) >> 2;
@@ -1628,10 +1667,10 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
 			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
 			    break;
      case Panel_1280x800:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  800;
-     			    SiS_Pr->PanelHT   = 1408; SiS_Pr->PanelVT   =  816;
-			    SiS_Pr->PanelHRS   =  21; SiS_Pr->PanelHRE  =   24;
-			    SiS_Pr->PanelVRS   =   4; SiS_Pr->PanelVRE  =    3;
-			    SiS_Pr->PanelVCLKIdx315 = VCLK69_315;
+     			    SiS_Pr->PanelHT   = 1656; SiS_Pr->PanelVT   =  841;  /* 1408, 816 */
+			    SiS_Pr->PanelHRS   =  32; SiS_Pr->PanelHRE  =  312;  /*   16,  64 */
+			    SiS_Pr->PanelVRS   =  16; SiS_Pr->PanelVRE  =    8;  /*    4,   3 */
+			    SiS_Pr->PanelVCLKIdx315 = VCLK83_315;
 			    SiS_GetLCDInfoBIOS(SiS_Pr, HwInfo);
 			    break;
      case Panel_1280x960:   SiS_Pr->PanelXRes = 1280; SiS_Pr->PanelYRes =  960;
@@ -1757,6 +1796,10 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
      if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+        if(modeflag & NoSupportLCDScale) {
+	   /* No scaling for this mode on any panel */
+	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	}
         switch(SiS_Pr->SiS_LCDResInfo) {
         case Panel_Custom:
 		/* For non-standard LCD resolution, we let the panel scale */
@@ -1774,7 +1817,7 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
 	 	SiS_Pr->SiS_LCDInfo &= ~DontExpandLCD;
 		break;
 	case Panel_1280x1024:
-	        if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	        if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
 		   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
 		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
 		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16) {
@@ -1791,13 +1834,30 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
 		}
 		break;
 	case Panel_1400x1050:
+	 	if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
+	  	   if(ModeNo == 0x7c || ModeNo == 0x7d || ModeNo == 0x7e ||
+		      ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78 ||
+		      ModeNo == 0x14 || ModeNo == 0x15 || ModeNo == 0x16 ||
+		      ModeNo == 0x23 || ModeNo == 0x24 || ModeNo == 0x25) {
+	      	      /* Do not scale to 1280x720/768/800/960 (B/C bridges only) */
+                      SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+	           }
+		}
+		if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		   if(ModeNo == 0x79 || ModeNo == 0x75 || ModeNo == 0x78) {
+		      if(SiS_Pr->UsePanelScaler == -1) {
+		         /* Do not scale to 1280x720 by default (LVDS bridges) */
+	      	         SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
+		      }
+		   }
+		}
 		if(ModeNo == 0x3a || ModeNo == 0x4d || ModeNo == 0x65) {
-	      	   /* We do not scale to 1280x1024 (all bridges) */
+	      	   /* Do not scale to 1280x1024 (all bridges) */
 	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 	   	}
 		break;
 	case Panel_1600x1200:
-		if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+		if(SiS_Pr->SiS_VBType & VB_SISTMDS) {
 	      	   /* No idea about the timing and zoom factors (C bridge only) */
 	      	   SiS_Pr->SiS_LCDInfo |= DontExpandLCD;
 	   	}
@@ -1832,6 +1892,10 @@ SiS_GetLCDResInfo(SiS_Private *SiS_Pr, U
   if(SiS_Pr->SiS_LCDResInfo == Panel_640x480) {
      SiS_Pr->SiS_LCDInfo |= LCDPass11;
   }
+  
+  if(SiS_Pr->UseCustomMode) {
+     SiS_Pr->SiS_LCDInfo |= (DontExpandLCD | LCDPass11);
+  }
 
   /* (In)validate LCDPass11 flag */
   if(!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) {
@@ -1975,10 +2039,25 @@ SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USH
 	      VCLKIndex = SiS_Pr->PanelVCLKIdx315;
 	      if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (SiS_Pr->SiS_LCDInfo & LCDPass11)) {
 	         VCLKIndex = VCLKIndexGEN;
-		 if(resinfo == SIS_RI_1280x720) VCLKIndex = VCLK_1280x720;
-		 if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
-		    if(SiS_Pr->PanelHT == 1344) VCLKIndex = VCLK_1280x720_2;
+		 switch(resinfo) {
+		 case SIS_RI_1280x720: VCLKIndex = VCLK_1280x720; 
+		 		       if(SiS_Pr->SiS_LCDResInfo == Panel_1280x720) {
+		                          if(SiS_Pr->PanelHT == 1344) {
+					     VCLKIndex = VCLK_1280x720_2;
+					  }
+				       }
+		 		       break;
+		 case SIS_RI_720x480:  VCLKIndex = VCLK_720x480;  break;
+		 case SIS_RI_720x576:  VCLKIndex = VCLK_720x576;  break;
+		 case SIS_RI_768x576:  VCLKIndex = VCLK_768x576;  break;
+		 case SIS_RI_848x480:  VCLKIndex = VCLK_848x480;  break;
+		 case SIS_RI_856x480:  VCLKIndex = VCLK_856x480;  break;
+		 case SIS_RI_800x480:  VCLKIndex = VCLK_800x480;  break;
+		 case SIS_RI_1024x576: VCLKIndex = VCLK_1024x576; break;
+		 case SIS_RI_1152x864: VCLKIndex = VCLK_1152x864; break;
+		 case SIS_RI_1360x768: VCLKIndex = VCLK_1360x768; break;
 		 }
+		 
 		 if(ModeNo <= 0x13) {
 		    if(HwInfo->jChipType <= SIS_315PRO) {
 		       if(SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_CRT2CRTC == 1) VCLKIndex = 0x42;
@@ -2150,12 +2229,10 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
                     PSIS_HW_INFO HwInfo)
 {
   USHORT i,j,modeflag;
-  USHORT tempcl,tempah=0;
-#ifdef SIS300
-  USHORT temp;
-#endif
+  USHORT tempbl,tempcl,tempah=0;
 #ifdef SIS315H
-  USHORT tempbl, tempah2, tempbl2;
+  UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+  USHORT tempah2, tempbl2;
 #endif
 
   if(ModeNo <= 0x13) {
@@ -2178,6 +2255,9 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
   } else {
 
      for(i=0,j=4; i<3; i++,j++) SiS_SetReg(SiS_Pr->SiS_Part1Port,j,0);
+     if(HwInfo->jChipType >= SIS_315H) {
+        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0x7F);
+     }
 
      tempcl = SiS_Pr->SiS_ModeType;
 
@@ -2187,14 +2267,14 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 
         /* For 301BDH: (with LCD via LVDS) */
         if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-	   temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
-	   temp &= 0xef;
-	   temp |= 0x02;
+	   tempbl = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32);
+	   tempbl &= 0xef;
+	   tempbl |= 0x02;
 	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTV) || (SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC)) {
-	      temp |= 0x10;
-	      temp &= 0xfd;
+	      tempbl |= 0x10;
+	      tempbl &= 0xfd;
 	   }
-	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	   SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,tempbl);
         }
 
         if(ModeNo > 0x13) {
@@ -2368,7 +2448,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 
 #ifdef SIS315H
 
-        unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);;
+        unsigned char bridgerev = SiS_GetReg(SiS_Pr->SiS_Part4Port,0x01);
 
 	/* The following is nearly unpreditable and varies from machine
 	 * to machine. Especially the 301DH seems to be a real trouble
@@ -2399,10 +2479,11 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 	 * in a 650 box (Jake). What is the criteria?
 	 */
 
-	if((IS_SIS740) || (HwInfo->jChipType >= SIS_661)) {
+	if((IS_SIS740) || (HwInfo->jChipType >= SIS_661) || (SiS_Pr->SiS_ROMNew)) {
 	   tempah = 0x30;
 	   tempbl = 0xc0;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
+	   if((SiS_Pr->SiS_VBInfo & DisableCRT2Display) ||
+	      ((SiS_Pr->SiS_ROMNew) && (!(ROMAddr[0x5b] & 0x04)))) {
 	      tempah = 0x00;
 	      tempbl = 0x00;
 	   }
@@ -2433,23 +2514,23 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 
 	if(IS_SIS740) {
 	   tempah = 0x80;
-	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) {
-	      tempah = 0x00;
-	   }
+	   if(SiS_Pr->SiS_VBInfo & DisableCRT2Display) tempah = 0x00;
 	   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,0x7f,tempah);
 	} else {
 	   tempah = 0x00;
            tempbl = 0x7f;
            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
               tempbl = 0xff;
-	      if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) {
-	         tempah = 0x80;
-	      }
+	      if(!(SiS_IsDualEdge(SiS_Pr, HwInfo))) tempah = 0x80;
            }
            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x23,tempbl,tempah);
 	}
-
-	/* 661: Sets p4 27 and 34 here, done in SetGroup4 here (old BIOS) */
+	
+#if 0	
+	if(SiS_Pr->SiS_VBType & VB_SIS301C) {
+	   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x3a,0xc0);
+	}
+#endif	
 
 #endif /* SIS315H */
 
@@ -2478,9 +2559,7 @@ SiS_SetCRT2ModeRegs(SiS_Private *SiS_Pr,
 	   tempbl = 0xfb;
            if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA)) {
               tempah = 0x00;
-	      if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
-	         tempbl = 0xff;
-	      }
+	      if(SiS_IsDualEdge(SiS_Pr, HwInfo)) tempbl = 0xff;
            }
 	   SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x13,tempbl,tempah);
 
@@ -2560,9 +2639,11 @@ SiS_GetCRT2ResInfo(SiS_Private *SiS_Pr,U
 
   if((SiS_Pr->SiS_VBType & VB_SISVB) && (!(SiS_Pr->SiS_VBType & VB_NoLCD))) {
 
+#if 0  
         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToLCDA | SetCRT2ToLCD | SetCRT2ToHiVision)) {
            if(xres == 720) xres = 640;
 	}
+#endif
 
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
 	   switch(SiS_Pr->SiS_LCDResInfo) {
@@ -2726,7 +2807,12 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
 
         tempbx = SiS_Pr->SiS_LCDResInfo;
 	if(!(SiS_Pr->SiS_SetFlag & LCDVESATiming)) tempbx += 32;
-
+	
+	if(SiS_Pr->SiS_LCDResInfo == Panel_1680x1050) {
+	   if     (resinfo == SIS_RI_1280x800)  tempal =  9;
+	   else if(resinfo == SIS_RI_1400x1050) tempal = 11;
+	}
+	
   	if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {  /* Pass 1:1 only (center-screen handled outside) */
 	   tempbx = 100;
 	   if(ModeNo >= 0x13) {
@@ -2783,6 +2869,9 @@ SiS_GetCRT2Ptr(SiS_Private *SiS_Pr,USHOR
 	      (resinfo == SIS_RI_720x576) ||
 	      (resinfo == SIS_RI_768x576)) {
 	      tempal = 6;
+	      if(SiS_Pr->SiS_TVMode & (TVSetPAL | TVSetPALN)) {
+	         if(resinfo == SIS_RI_720x480) tempal = 9;
+	      }
 	   }
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
               if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) {
@@ -3080,11 +3169,14 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
                    USHORT RefreshRateTableIndex,
 		   PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempbx,modeflag;
-  USHORT resinfo;
-  USHORT CRT2Index,ResIndex;
+  UCHAR  *ROMAddr = NULL;
+  USHORT tempax,tempbx,modeflag,romptr=0;
+  USHORT resinfo,CRT2Index,ResIndex;
   const SiS_LCDDataStruct *LCDPtr = NULL;
   const SiS_TVDataStruct  *TVPtr  = NULL;
+#ifdef SIS315H    
+  SHORT  resinfo661;
+#endif    
 
   if(ModeNo <= 0x13) {
      modeflag = SiS_Pr->SiS_SModeIDTable[ModeIdIndex].St_ModeFlag;
@@ -3095,6 +3187,20 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
   } else {
      modeflag = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_ModeFlag;
      resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
+#ifdef SIS315H     
+     resinfo661 = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].ROMMODEIDX661;
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToLCD)   &&
+         (SiS_Pr->SiS_SetFlag & LCDVESATiming) &&
+         (resinfo661 >= 0)                     && 
+	 (SiS_Pr->SiS_NeedRomModeData) ) {
+        if((ROMAddr = GetLCDStructPtr661(SiS_Pr, HwInfo))) {
+	   if((romptr = (SISGETROMW(21)))) {
+              romptr += (resinfo661 * 10);
+	      ROMAddr = HwInfo->pjVirtualRomBase;
+	   }
+	}
+     }
+#endif     
   }
   
   SiS_Pr->SiS_NewFlickerMode = 0;
@@ -3238,6 +3344,8 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
         SiS_Pr->SiS_VDE       = SiS_Pr->SiS_VGAVDE;
 
      } else {
+     
+        BOOLEAN gotit = FALSE;
 
         if((SiS_Pr->SiS_LCDInfo & DontExpandLCD) && (!(SiS_Pr->SiS_LCDInfo & LCDPass11))) {
 
@@ -3245,8 +3353,23 @@ SiS_GetCRT2Data301(SiS_Private *SiS_Pr,U
            SiS_Pr->SiS_VGAVT     = SiS_Pr->PanelVT;
            SiS_Pr->SiS_HT        = SiS_Pr->PanelHT;
            SiS_Pr->SiS_VT        = SiS_Pr->PanelVT;
+	   gotit = TRUE;
 
-	} else {
+	} else if( (!(SiS_Pr->SiS_LCDInfo & DontExpandLCD)) && (romptr) && (ROMAddr) ) {
+	
+#ifdef SIS315H	
+	   SiS_Pr->SiS_RVBHCMAX  = ROMAddr[romptr];
+           SiS_Pr->SiS_RVBHCFACT = ROMAddr[romptr+1];
+           SiS_Pr->SiS_VGAHT     = ROMAddr[romptr+2] | ((ROMAddr[romptr+3] & 0x0f) << 8);
+           SiS_Pr->SiS_VGAVT     = ROMAddr[romptr+4] | ((ROMAddr[romptr+3] & 0xf0) << 4);
+           SiS_Pr->SiS_HT        = ROMAddr[romptr+5] | ((ROMAddr[romptr+6] & 0x0f) << 8);
+           SiS_Pr->SiS_VT        = ROMAddr[romptr+7] | ((ROMAddr[romptr+6] & 0xf0) << 4);
+	   if(SiS_Pr->SiS_VGAHT) gotit = TRUE;
+#endif	   
+	
+	} 
+	
+	if(!gotit) {
 
            SiS_GetCRT2Ptr(SiS_Pr,ModeNo,ModeIdIndex,RefreshRateTableIndex,
                           &CRT2Index,&ResIndex,HwInfo);
@@ -3445,8 +3568,10 @@ SiS_GetLVDSDesData(SiS_Private *SiS_Pr, 
 #ifdef SIS315H
      if(SiS_Pr->SiS_LCDInfo & DontExpandLCD) {
         /* non-pass 1:1 only, see above */
-        if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
+        if(SiS_Pr->SiS_VGAHDE != SiS_Pr->PanelXRes) {
            SiS_Pr->SiS_LCDHDES = SiS_Pr->SiS_HT - ((SiS_Pr->PanelXRes - SiS_Pr->SiS_VGAHDE) / 2);
+	}
+	if(SiS_Pr->SiS_VGAVDE != SiS_Pr->PanelYRes) {
 	   SiS_Pr->SiS_LCDVDES = SiS_Pr->SiS_VT - ((SiS_Pr->PanelYRes - SiS_Pr->SiS_VGAVDE) / 2);
 	}
      }
@@ -3562,207 +3687,142 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
-      if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
+     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ===== For 30xB/LV ===== */
 
         if(HwInfo->jChipType < SIS_315H) {
 
 #ifdef SIS300	   /* 300 series */
 
-           if(HwInfo->jChipType == SIS_300) {  /* For 300+301LV (A907) */
-
-	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-		    SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		 }
+	   if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
 	      }
+	      SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	   }
+	   if(SiS_Is301B(SiS_Pr)) {
 	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
 	      SiS_ShortDelay(SiS_Pr,1);
-	      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	      SiS_DisplayOff(SiS_Pr);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	         if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-	             (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-		 }
-	      }
-
-	   } else {
-
-	      if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-	         SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x08);
-	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-	      }
-	      if(SiS_Is301B(SiS_Pr)) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0x3f);
-	         SiS_ShortDelay(SiS_Pr,1);
-	      }
-	      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	      SiS_DisplayOff(SiS_Pr);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	      SiS_UnLockCRT2(SiS_Pr,HwInfo);
+           }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
+	   SiS_DisplayOff(SiS_Pr);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	   SiS_UnLockCRT2(SiS_Pr,HwInfo);
+	   if(!(SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
 	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x01,0x80);
 	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x02,0x40);
-	      if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
-	          (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
-	         SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-                 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
-	      }
 	   }
-
+	   if( (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ||
+	       (!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) ) {
+	      SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+                 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+	      } else {
+		 SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x04);
+	      }
+	   }	        
+	      
 #endif  /* SIS300 */
 
         } else {
 
 #ifdef SIS315H	   /* 315 series */
+	   
+	   BOOLEAN custom1 = ((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
+	                      (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) ? TRUE : FALSE;
 
-           if(IS_SIS550650740660) {		/* 550, 650, 740, 660 */
-
-	      modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
+	   modenum = SiS_GetReg(SiS_Pr->SiS_P3d4,0x34) & 0x7f;
 
-              if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {			/* LV */
+           if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {	
+	   		
 #ifdef SET_EMI
-	         if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-		    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
-	               SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		    }
+	      if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		 if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+	            SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
 		 }
+	      }
 #endif
-		 if( (modenum <= 0x13) ||
-		     (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ||
-		     (SiS_IsVAMode(SiS_Pr,HwInfo)) ) {
-	     	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
-		    if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		       (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		       SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		    }
-	         }
-
-		 if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		    (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-		    SiS_DDC2Delay(SiS_Pr,0xff00);
-		    SiS_DDC2Delay(SiS_Pr,0xe000);
-
-	            SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-
-                    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-
-		    if(IS_SIS740) {
-		       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-		    }
-
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      if( (modenum <= 0x13)                  ||
+		  (SiS_IsVAMode(SiS_Pr,HwInfo))      ||
+		  (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
+	     	 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFE);
+		 if(custom1) SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      }
 
-		    if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
-	               tempah = 0xef;
-	               if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	                  tempah = 0xf7;
-                       }
-	               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	            }
+	      if(!custom1) {
+		 SiS_DDC2Delay(SiS_Pr,0xff00);
+		 SiS_DDC2Delay(SiS_Pr,0xe000);
+	         SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+                 pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+		 if(IS_SIS740) {
+		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
 		 }
+	         SiS_PanelDelay(SiS_Pr, HwInfo, 3);
+	      }
 
-              } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {			/* B-DH */
-
-	         if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,0xef);
-	         }
+           } 
+	      
+	   if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+	      tempah = 0xef;
+	      if(SiS_IsVAMode(SiS_Pr,HwInfo)) tempah = 0xf7;
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	   }
+	      
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,~0x10);
+	   }
+              
+	   tempah = 0x3f;
+	   if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
+	      tempah = 0x7f;
+	      if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) tempah = 0xbf;
+	   }
+	   SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-	      }
+           if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
+	      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
 
-	      if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,0xef);
+	      SiS_DisplayOff(SiS_Pr);
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	      }
-
-              if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	         (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		 (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	         tempah = 0x3f;
-	         if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	            tempah = 0x7f;
-	            if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		       tempah = 0xbf;
-                    }
-	         }
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
+		 
+	   } 
+	      
+	   if((!(SiS_IsVAMode(SiS_Pr,HwInfo))) ||
+	      ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
+
+	      if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
+		 SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
+		 SiS_DisplayOff(SiS_Pr);
 	      }
-
-              if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	         ((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13))) {
-
-	         if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-		    (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-		    SiS_DisplayOff(SiS_Pr);
-		    SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-		 } else {
-	            SiS_DisplayOff(SiS_Pr);
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	            SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x1E,0xDF);
-		    if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) && (modenum <= 0x13)) {
-		       SiS_DisplayOff(SiS_Pr);
-	               SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	               SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	               temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	               SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	               SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-		    }
-		 }
-
-	      } else {
-
-	         if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-		    (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
-		       SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
-		       SiS_DisplayOff(SiS_Pr);
-		    }
-		    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-		 } else {
-                    SiS_DisplayOff(SiS_Pr);
-	            SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-	            SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-		 }
-
-		 SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	         temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	         SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	         SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
+	      SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
+		 
+	      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+		 SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	      }
 
-	      if((SiS_Pr->SiS_VBType & VB_SIS301LV302LV) &&
-	         (SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		 (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-
-		 SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,~0x10);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
+	      temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
+              SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
+	      SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
+	      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
 
-	         tempah = 0x3f;
-	         if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	            tempah = 0x7f;
-	            if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		       tempah = 0xbf;
-                    }
-	         }
-	         SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	   }
+	      
+	   if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
+	      SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	   }
 
-		 if(SiS_IsNotM650orLater(SiS_Pr,HwInfo)) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-		 }
+	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	      
+	      if(!custom1) {
 
 	         if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	            SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xdf);
 	            if(!(SiS_CRT2IsLCD(SiS_Pr,HwInfo))) {
 	               if(!(SiS_IsDualEdge(SiS_Pr,HwInfo))) {
 		          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
@@ -3773,89 +3833,31 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 	         SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
 
 		 if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	            if( (SiS_IsVAMode(SiS_Pr, HwInfo)) ||
-	                (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
+	            if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
 		       SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 20);
 		    }
 	         }
-
-  	      } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-
-	         /* NIL */
-
-	      } else if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	                (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-			(SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-
-		 if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	            tempah = 0xef;
-	            if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-		       if(modenum > 0x13) {
-	                  tempah = 0xf7;
-		       }
-                    }
-	            SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-		 }
-		 if((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		    (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-		    if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-		       (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
-		       if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
-		          (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
-			  SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	     	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
-			  SiS_PanelDelay(SiS_Pr, HwInfo, 4);
-	               }
+	      
+	      } else {
+	      
+		 if((SiS_IsVAMode(SiS_Pr,HwInfo)) ||
+		    (!(SiS_IsDualEdge(SiS_Pr,HwInfo)))) {
+		    if((!(SiS_WeHaveBacklightCtrl(SiS_Pr, HwInfo))) ||
+		       (!(SiS_CRT2IsLCD(SiS_Pr, HwInfo)))) {
+		       SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	     	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x26,0xFD);
+		       SiS_PanelDelay(SiS_Pr, HwInfo, 4);
 		    }
 		 }
 
 	      }
-
-	  } else {			/* 315, 330 - all bridge types */
-
-	     if(SiS_Is301B(SiS_Pr)) {
-	        tempah = 0x3f;
-	        if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	           tempah = 0x7f;
-	           if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-		      tempah = 0xbf;
-                   }
-	        }
-	        SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-	        if(SiS_IsVAMode(SiS_Pr,HwInfo)) {
-	           SiS_DisplayOff(SiS_Pr);
-		   SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-	        }
-	     }
-	     if( (!(SiS_Is301B(SiS_Pr))) ||
-	         (!(SiS_IsVAMode(SiS_Pr,HwInfo))) ) {
-
- 	 	if( (!(SiS_Is301B(SiS_Pr))) ||
-		    (!(SiS_IsDualEdge(SiS_Pr,HwInfo))) ) {
-
-	           SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xDF);
-	           SiS_DisplayOff(SiS_Pr);
-
-		}
-
-                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x80);
-
-                SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x32,0xDF);
-
-	        temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00);
-                SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x00,0x10);
-	        SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x1E,0xDF);
-	        SiS_SetReg(SiS_Pr->SiS_Part1Port,0x00,temp);
-
-	     }
-
-	  }    /* 315/330 */
+           }
 
 #endif /* SIS315H */
 
 	}
 
-      } else {     /* ============ For 301 ================ */
+     } else {     /* ============ For 301 ================ */
 
         if(HwInfo->jChipType < SIS_315H) {
 #ifdef SIS300
@@ -3947,6 +3949,10 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, P
 
 #ifdef SIS315H	/* 315 series */
 
+        if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
+          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x4c,~0x18);
+        }
+
 	if(SiS_Pr->SiS_IF_DEF_CH70xx != 0) {
 
 	   if(HwInfo->jChipType == SIS_740) {
@@ -4077,7 +4083,6 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
   BOOLEAN delaylong = FALSE;
 #endif
 
-
   if(SiS_Pr->SiS_VBType & VB_SISVB) {
 
     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {   /* ====== For 301B et al  ====== */
@@ -4086,28 +4091,55 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 
 #ifdef SIS300     /* 300 series */
 
-         if(HwInfo->jChipType == SIS_300) {
-
-	    if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	       if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-	          if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
-	             SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-	          }
+	 if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
+	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
+	    }
+	    if(SiS_Pr->SiS_VBType & (VB_SIS301LV302LV | VB_NoLCD)) {
+	       if(!(SiS_CR36BIOSWord23d(SiS_Pr, HwInfo))) {
+	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
 	       }
 	    }
+	 }
+	    
+	 if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
+	    (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
+	       
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   		/* Enable CRT2 */
+            SiS_DisplayOn(SiS_Pr);
+	    SiS_UnLockCRT2(SiS_Pr,HwInfo);
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+      	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
+      	    } else {
+      	       SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
+            }
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
+	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
+		  if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
+		     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
+                  }
+		  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+                  SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
+               }
+	    }
+	       
+	 } else {
+	    
 	    temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-            if(SiS_BridgeInSlave(SiS_Pr)) {
+            if(SiS_BridgeInSlavemode(SiS_Pr)) {
                tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-               if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
+               if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
             }
             SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
 	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
 	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
 	    SiS_DisplayOn(SiS_Pr);
-	    if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
-	       if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	          if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
 		     if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
 		        SiS_PanelDelay(SiS_Pr, HwInfo, 1);
@@ -4116,441 +4148,279 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 	 	  }
 	       }
 	    }
+	       
+	 }
 
-	 } else {
-
-	    if((SiS_Pr->SiS_VBType & VB_NoLCD) &&
-	       (SiS_CRT2IsLCD(SiS_Pr, HwInfo))) {
-	       /* This is only for LCD output on 301B-DH via LVDS */
-	       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
-	       if(!(SiS_CR36BIOSWord23d(SiS_Pr,HwInfo))) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-	       }
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);   /* Enable CRT2 */
-               SiS_DisplayOn(SiS_Pr);
-	       SiS_UnLockCRT2(SiS_Pr,HwInfo);
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-      		  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
-      	       } else {
-      		  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
-               }
-	       if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x13) & 0x40)) {
-	           if(!(SiS_GetReg(SiS_Pr->SiS_P3c4,0x16) & 0x10)) {
-		       if(!(SiS_CR36BIOSWord23b(SiS_Pr,HwInfo))) {
-		           SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-                       }
-		       SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-                       SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xF7,0x00);
-                   }
-	       }
-            } else {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;             /* lock mode */
-               if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);
-	       SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1F,0x20);        /* enable VB processor */
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0);
-	       SiS_DisplayOn(SiS_Pr);
-	    }
-
-         }
+	 
 #endif /* SIS300 */
 
       } else {
 
 #ifdef SIS315H    /* 315 series */
 
-	 if(IS_SIS550650740660) {		/* 550, 650, 740, 660 */
-
-	    UCHAR r30=0, r31=0, r32=0, r33=0, cr36=0;
-
-	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	 UCHAR   r30=0, r31=0, r32=0, r33=0, cr36=0;
+	 /* USHORT  emidelay=0; */
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x1f,0xef);
 #ifdef SET_EMI
-		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  }
+	    if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	       SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	    }
 #endif
-	       }
-
-               if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          tempah = 0x10;
-		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-		     else 			       tempah = 0x08;
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	       }
-
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
-	          SiS_DisplayOff(SiS_Pr);
-	          pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
-	          if(IS_SIS740) {
-	             SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
-	          }
-	       }
-
-	       if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	           (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-                  if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
-		     if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-		        (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-			SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-			if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-			   SiS_GenericDelay(SiS_Pr, 0x4500);
-			}
-	                SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
-		     } else {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
-			SiS_PanelDelay(SiS_Pr, HwInfo, 0);
-		     }
-	          }
-	       }
-
-               if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
-                     SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		     delaylong = TRUE;
-		  }
-	       }
-
-	    } else if(SiS_Pr->SiS_VBType & VB_NoLCD) {
-
-	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x10);
-	       }
-
-  	    } else if(SiS_Pr->SiS_VBType & VB_SIS301B302B) {
+	 }
 
-	       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
-	          tempah = 0x10;
-		  if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
-		     if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
-		     else 			       tempah = 0x08;
-		  }
-		  SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
-	       }
-	       
+         if(!(SiS_IsNotM650orLater(SiS_Pr, HwInfo))) {
+	    tempah = 0x10;
+	    if(SiS_LCDAEnabled(SiS_Pr, HwInfo)) {
+	       if(SiS_TVEnabled(SiS_Pr, HwInfo)) tempah = 0x18;
+	       else 			         tempah = 0x08;
 	    }
+	    SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4c,tempah);
+	 }
 
-	    if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-               temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC)) {
-		     if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
-		  }
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	    
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0x00);
+	    SiS_DisplayOff(SiS_Pr);
+	    pushax = SiS_GetReg(SiS_Pr->SiS_P3c4,0x06);
+	    if(IS_SIS740) {
+	       SiS_SetRegAND(SiS_Pr->SiS_P3c4,0x06,0xE3);
+	    }
 
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
-	       
-	       if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	          (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-		  (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	          SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
-		  temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2e);
-		  if(!(temp & 0x80)) {
-		     SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+	    if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
+               if(!(SiS_GetReg(SiS_Pr->SiS_Part4Port,0x26) & 0x02)) {
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
+		  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x02);
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 2);
+		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		     SiS_GenericDelay(SiS_Pr, 0x4500);
 		  }
-	       } else {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
 	       }
-	    } else {
-	       SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
 	    }
 
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
-
-	    if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	       (SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	       (SiS_Pr->SiS_CustomT == CUT_CLEVO1400)) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2e);
-	       if(!(temp & 0x80)) {
-		  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-	       }
+	    if(!(SiS_GetReg(SiS_Pr->SiS_P3d4,0x31) & 0x40)) {
+               SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+	       delaylong = TRUE;
 	    }
 
-	    tempah = 0xc0;
-	    if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
-	       tempah = 0x80;
-	       if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) {
-	          tempah = 0x40;
-               }
-	    }
-            SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
+	 } 
 
-	    if((SiS_Pr->SiS_VBType & VB_SIS301B302B) ||
-	       (((SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
-	         (SiS_Pr->SiS_CustomT == CUT_CLEVO1400))     &&
-	        (!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))))) {
-               SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	    }
+	 if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
+	 
+            temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
+	    if(SiS_BridgeInSlavemode(SiS_Pr)) {
+               tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
+               if(!(tempah & SetCRT2ToRAMDAC)) {
+		  if(!(SiS_LCDAEnabled(SiS_Pr, HwInfo))) temp |= 0x20;
+	       }
+            }
+            SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
+	    SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
+	    
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x2e,0x7f);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+	    
 	    if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
+	       SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+	    }
+	    
+	 } else {
+	 
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x1e,0x20);
+	    
+	 }
 
-	       if((SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) &&
-	          (SiS_Pr->SiS_CustomT != CUT_CLEVO1400)) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-#ifdef COMPAQ_HACK
-	       if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-	          SiS_PanelDelay(SiS_Pr, HwInfo, 2);
-	       }
-#endif
+	 SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
+	 SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+	 
+	 tempah = 0xc0;
+	 if(SiS_IsDualEdge(SiS_Pr, HwInfo)) {
+	    tempah = 0x80;
+	    if(!(SiS_IsVAMode(SiS_Pr, HwInfo))) tempah = 0x40;
+	 }
+         SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
 
-	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	 if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 
-	       if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
+	    SiS_PanelDelay(SiS_Pr, HwInfo, 2);
+
+	    SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1f,0x10);
+	    SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
+
+	    if(SiS_Pr->SiS_CustomT != CUT_CLEVO1400) {
 #ifdef SET_EMI
-	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
-		  }
+	       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	          SiS_SetRegAND(SiS_Pr->SiS_Part4Port,0x30,0x0c);
+	       }
 #endif
-	          SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
+	       SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x27,0x0c);
 #ifdef SET_EMI
-	          if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	       if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
 
-		     cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
-
-		     /*                                              (P4_30|0x40)  */
-		     /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
-		     /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
-		     /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
-		     /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
-		     /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
-		     /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
-		     /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
-		     /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
-		     /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
-
-		     if(SiS_Pr->HaveEMI) {
-		        r30 = SiS_Pr->EMI_30;
-			r31 = SiS_Pr->EMI_31;
-			r32 = SiS_Pr->EMI_32;
-			r33 = SiS_Pr->EMI_33;
-		     } else {
-		        r30 = 0;
+		  cr36 = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36); 
+		     
+		  if(SiS_Pr->SiS_ROMNew) {
+		     UCHAR  *ROMAddr = HwInfo->pjVirtualRomBase;
+		     USHORT romptr   = GetLCDStructPtr661_2(SiS_Pr, HwInfo);
+		     if(romptr) {
+		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
+			SiS_Pr->EMI_30 = 0;
+			SiS_Pr->EMI_31 = ROMAddr[romptr + 14];
+			SiS_Pr->EMI_32 = ROMAddr[romptr + 15];
+			SiS_Pr->EMI_33 = ROMAddr[romptr + 16];
+			if(ROMAddr[romptr + 1] & 0x10) SiS_Pr->EMI_30 = 0x40;
+			/* emidelay = SISGETROMW((romptr + 0x22)); */
+			SiS_Pr->HaveEMI = SiS_Pr->HaveEMILCD = SiS_Pr->OverruleEMI = TRUE;
 		     }
+		  }
 
-		     /* EMI_30 is read at driver start; however, the BIOS sets this
-		      * (if it is used) only if the LCD is in use. In case we caught
-		      * the machine while on TV output, this bit is not set and we
-		      * don't know if it should be set - hence our detection is wrong.
-		      * Work-around this here:
-		      */
-
-		     if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
-		        if((cr36 & 0x0f) == 0x02) {			/* 1024x768 */
-		           r30 |= 0x40;
-			   if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) {
-			      r30 &= ~0x40;
-			   }
-		        } else if((cr36 & 0x0f) == 0x03) {		/* 1280x1024 */
-		           r30 |= 0x40;
-			   if(SiS_Pr->SiS_CustomT != CUT_COMPAQ1280) {
-			      r30 &= ~0x40;
-			   }
-		        } else if((cr36 & 0x0f) == 0x09) {		/* 1400x1050 */
-		           r30 |= 0x40;
-		        } else if((cr36 & 0x0f) == 0x0b) {		/* 1600x1200 - unknown */
-		           r30 |= 0x40;
-		        }
-                     }
+		  /*                                              (P4_30|0x40)  */
+		  /* Compal 1400x1050: 0x05, 0x60, 0x00                YES  (1.10.7w;  CR36=69)      */
+		  /* Compal 1400x1050: 0x0d, 0x70, 0x40                YES  (1.10.7x;  CR36=69)      */
+		  /* Acer   1280x1024: 0x12, 0xd0, 0x6b                NO   (1.10.9k;  CR36=73)      */
+		  /* Compaq 1280x1024: 0x0d, 0x70, 0x6b                YES  (1.12.04b; CR36=03)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33                NO   (1.10.8e;  CR36=12, DL!) */
+		  /* Clevo   1024x768: 0x0d, 0x70, 0x40 (if type == 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Clevo   1024x768: 0x05, 0x60, 0x33 (if type != 3) YES  (1.10.8y;  CR36=?2)      */
+		  /* Asus    1024x768: ?                                ?   (1.10.8o;  CR36=?2)      */
+		  /* Asus    1024x768: 0x08, 0x10, 0x3c (problematic)  YES  (1.10.8q;  CR36=22)      */
+
+		  if(SiS_Pr->HaveEMI) {
+		     r30 = SiS_Pr->EMI_30; r31 = SiS_Pr->EMI_31;
+		     r32 = SiS_Pr->EMI_32; r33 = SiS_Pr->EMI_33;
+		  } else {
+		     r30 = 0;
+		  }
 
-		     if(!SiS_Pr->HaveEMI) {
-		        if((cr36 & 0x0f) == 0x02) {
+		  /* EMI_30 is read at driver start; however, the BIOS sets this
+		   * (if it is used) only if the LCD is in use. In case we caught
+		   * the machine while on TV output, this bit is not set and we
+		   * don't know if it should be set - hence our detection is wrong.
+		   * Work-around this here:
+		   */
+
+		  if((!SiS_Pr->HaveEMI) || (!SiS_Pr->HaveEMILCD)) {
+		     switch((cr36 & 0x0f)) {
+		     case 2:  
+			r30 |= 0x40;
+			if(SiS_Pr->SiS_CustomT == CUT_CLEVO1024) r30 &= ~0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x33;
 			   if((cr36 & 0xf0) == 0x30) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;
-			   } else {
-			      r31 = 0x05; r32 = 0x60; r33 = 0x33;
-			   }
-		        } else if((cr36 & 0x0f) == 0x03) {
+			   } 
+			}
+			break;
+		     case 3:  /* 1280x1024 */
+			if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			   if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x6b;
-			   } else {
-			      r31 = 0x12; r32 = 0xd0; r33 = 0x6b;
 			   }
-			} else if((cr36 & 0x0f) == 0x09) {
+			}
+			break;
+		     case 9:  /* 1400x1050 */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
+			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			   if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
 			      r31 = 0x0d; r32 = 0x70; r33 = 0x40;  /* BIOS values */
-			   } else {
-			      r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			   }
-			} else {
+			}
+			break;
+		     case 11: /* 1600x1200 - unknown */
+			r30 |= 0x40;
+			if(!SiS_Pr->HaveEMI) {
 			   r31 = 0x05; r32 = 0x60; r33 = 0x00;
 			}
 		     }
+                  }
 
-		     /* BIOS values don't work so well sometimes */
-		     if(!SiS_Pr->OverruleEMI) {
+		  /* BIOS values don't work so well sometimes */
+		  if(!SiS_Pr->OverruleEMI) {
 #ifdef COMPAL_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
-		           if((cr36 & 0x0f) == 0x09) {
-			      r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
-			   }
- 		        }
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAL1400_2) {
+		        if((cr36 & 0x0f) == 0x09) {
+			   r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x00;
+			}
+ 		     }
 #endif
 #ifdef COMPAQ_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-		           if((cr36 & 0x0f) == 0x03) {
-			      r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;     /* rev 1 */
-			   }
+		     if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
+		        if((cr36 & 0x0f) == 0x03) {
+			   r30 = 0x20; r31 = 0x12; r32 = 0xd0; r33 = 0x6b;    
 			}
+		     }
 #endif
 #ifdef ASUS_HACK
-		        if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-		           if((cr36 & 0x0f) == 0x02) {
-			      /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
-			      /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
-			      /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
-			      /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
-			   }
+		     if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
+		        if((cr36 & 0x0f) == 0x02) {
+			   /* r30 = 0x60; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 2 */
+			   /* r30 = 0x20; r31 = 0x05; r32 = 0x60; r33 = 0x33;  */   /* rev 3 */
+			   /* r30 = 0x60; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 4 */
+			   /* r30 = 0x20; r31 = 0x0d; r32 = 0x70; r33 = 0x40;  */   /* rev 5 */
 			}
-#endif
- 		     }
-		     if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
-		     }
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
-		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
-		     if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
-		        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
-		     } else {
-		        SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x00);
-		     }
-		     if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	                 (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-	                if(r30 & 0x40) {
-		           SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
-			   if(delaylong) {
-			      SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
-			      delaylong = FALSE;
-			   }
-			   SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-			   if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
-			      SiS_GenericDelay(SiS_Pr, 0x500);
-			   }
-	                   SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);
-	                }
 		     }
-		  }
 #endif
-	       }
-
-	       if(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) {
-
-	          if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	              (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-		     SiS_DisplayOn(SiS_Pr);
-		     SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		     SiS_WaitVBRetrace(SiS_Pr, HwInfo);
-		     SiS_PanelDelay(SiS_Pr, HwInfo, 3);
-		     if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-	  	     }
+ 		  }
+		     
+		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
+		     SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x20);
 		  }
-
-	       } else if(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) {
-
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             if( (SiS_IsVAMode(SiS_Pr, HwInfo)) ||
-	                 (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {
-		        SiS_DisplayOn(SiS_Pr);
-		        SiS_PanelDelay(SiS_Pr, HwInfo, 1);
-		        SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
-		     }
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x31,r31);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x32,r32);
+		  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x33,r33);
+		  if(!(SiS_Pr->OverruleEMI && (!r30) && (!r31) && (!r32) && (!r33))) {
+		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x10);
+		  } else {
+		     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x34,0x00);
 		  }
-
-	       } else {
-
-	          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2e,0x80);
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             if( (SiS_IsVAMode(SiS_Pr,HwInfo)) ||
-	                 ((SiS_CRT2IsLCD(SiS_Pr, HwInfo))) ) {
-		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		        if(delaylong) {
-			   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
-		        }
-                        SiS_WaitVBRetrace(SiS_Pr,HwInfo);
-			if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+		     
+		  if( (SiS_LCDAEnabled(SiS_Pr, HwInfo)) || 
+	              (SiS_CRT2IsLCD(SiS_Pr, HwInfo)) ) {  
+	             if(r30 & 0x40) {
+		        SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+			if(delaylong) {
+			   SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 5);
+			   delaylong = FALSE;
+			}
+			SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+			if(SiS_Pr->SiS_CustomT == CUT_ASUSA2H_2) {
 			   SiS_GenericDelay(SiS_Pr, 0x500);
 			}
-		        SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
+	                SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x30,0x40);   
 	             }
-	          }
-
-	          SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
-	          SiS_DisplayOn(SiS_Pr);
-	          SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
-
-	          if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
-	             SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-	          }
-
+		  }
 	       }
-
+#endif
 	    }
 
-	 } else {			/* 315, 330 */
-
-	    if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	       temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;
-	       if(SiS_BridgeInSlave(SiS_Pr)) {
-                  tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-                  if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
-               }
-               SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
-
-	       SiS_SetRegOR(SiS_Pr->SiS_P3c4,0x1E,0x20);                   /* enable CRT2 */
-
-	       temp = SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-               if(!(temp & 0x80))
-                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
-            }
-
-	    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x00,0x1f,0x20);
-
-	    if(SiS_Is301B(SiS_Pr)) {
-
-	       temp=SiS_GetReg(SiS_Pr->SiS_Part1Port,0x2E);
-               if(!(temp & 0x80))
-                  SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x2E,0x80);
-
-	       tempah = 0xc0;
-	       if(SiS_IsDualEdge(SiS_Pr,HwInfo)) {
-	          tempah = 0x80;
-	          if(!(SiS_IsVAMode(SiS_Pr,HwInfo))) {
-	             tempah = 0x40;
-                  }
+	    if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+	       if(SiS_IsVAorLCD(SiS_Pr, HwInfo)) {
+		  SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+		  if(delaylong) {
+		     SiS_PanelDelayLoop(SiS_Pr, HwInfo, 3, 10);
+		  }
+                  SiS_WaitVBRetrace(SiS_Pr,HwInfo);
+		  if(SiS_Pr->SiS_VBType & (VB_SIS302LV | VB_SIS302ELV)) {
+	 	     SiS_GenericDelay(SiS_Pr, 0x500);
+		  }
+		  SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x26,0x01);
 	       }
-               SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x1F,tempah);
-
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
-
-	    } else {
-
-	       SiS_VBLongWait(SiS_Pr);
-               SiS_DisplayOn(SiS_Pr);
-	       SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7F);
-               SiS_VBLongWait(SiS_Pr);
-
 	    }
 
-	 }   /* 315, 330 */
+	    SiS_SetReg(SiS_Pr->SiS_P3c4,0x06,pushax);
+	    SiS_DisplayOn(SiS_Pr);
+	    SiS_SetRegByte(SiS_Pr->SiS_P3c6,0xff);
+
+	 }
+	 
+	 if(!(SiS_WeHaveBacklightCtrl(SiS_Pr,HwInfo))) {
+	    SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x00,0x7f);
+	 }
 
 #endif /* SIS315H */
 
@@ -4566,9 +4436,9 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
        }
 
        temp = SiS_GetReg(SiS_Pr->SiS_P3c4,0x32) & 0xDF;          /* lock mode */
-       if(SiS_BridgeInSlave(SiS_Pr)) {
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
           tempah = SiS_GetReg(SiS_Pr->SiS_P3d4,0x30);
-          if(!(tempah & SetCRT2ToRAMDAC))  temp |= 0x20;
+          if(!(tempah & SetCRT2ToRAMDAC)) temp |= 0x20;
        }
        SiS_SetReg(SiS_Pr->SiS_P3c4,0x32,temp);
 
@@ -4621,7 +4491,7 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
        SiS_DisplayOn(SiS_Pr);
        SiS_UnLockCRT2(SiS_Pr,HwInfo);
        SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x02,0xBF);
-       if(SiS_BridgeInSlave(SiS_Pr)) {
+       if(SiS_BridgeInSlavemode(SiS_Pr)) {
       	  SiS_SetRegAND(SiS_Pr->SiS_Part1Port,0x01,0x1F);
        } else {
       	  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x01,0x1F,0x40);
@@ -4653,6 +4523,10 @@ SiS_EnableBridge(SiS_Private *SiS_Pr, PS
 
 #ifdef SIS315H    /* 315 series */
 
+       if(!(SiS_IsNotM650orLater(SiS_Pr,HwInfo))) {
+          SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x4c,0x18);
+       }
+
        if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
 	  if(SiS_CRT2IsLCD(SiS_Pr, HwInfo)) {
 	     SiS_SetRegSR11ANDOR(SiS_Pr,HwInfo,0xFB,0x00);
@@ -5234,14 +5108,22 @@ SiS_SetCRT2FIFO_300(SiS_Private *SiS_Pr,
 static void
 SiS_SetCRT2FIFO_310(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo)
 {
-  USHORT temp;
-
   SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3B);
-  temp = 0x04;
-  if(HwInfo->jChipType >= SIS_661) {
-     if((SiS_GetReg(SiS_Pr->SiS_P3d4,0x5c) & 0xf8) == 0x80) temp = 0x44;
+  if( (HwInfo->jChipType == SIS_760)      &&
+      (SiS_Pr->SiS_SysFlags & SF_760LFB)  &&
+      (SiS_Pr->SiS_ModeType == Mode32Bpp) &&
+      (SiS_Pr->SiS_VGAHDE >= 1280)	  &&
+      (SiS_Pr->SiS_VGAVDE >= 1024) ) {
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x03);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x01,0x3b);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x2f,0x01);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x4d,0xc0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x02,0x6e);
+  } else {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,0x04);  
   }
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x02,~0x3f,temp);
+  
 }
 #endif
 
@@ -5250,10 +5132,10 @@ SiS_GetVGAHT2(SiS_Private *SiS_Pr)
 {
   ULONG tempax,tempbx;
 
-  tempbx = ((SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX) & 0xFFFF;
+  tempbx = (SiS_Pr->SiS_VGAVT - SiS_Pr->SiS_VGAVDE) * SiS_Pr->SiS_RVBHCMAX;
   tempax = (SiS_Pr->SiS_VT - SiS_Pr->SiS_VDE) * SiS_Pr->SiS_RVBHCFACT;
   tempax = (tempax * SiS_Pr->SiS_HT) / tempbx;
-  return((USHORT) tempax);
+  return((USHORT)tempax);
 }
 
 /* Set Part 1 / SiS bridge slave mode */
@@ -6143,7 +6025,7 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
               PSIS_HW_INFO HwInfo, USHORT RefreshRateTableIndex)
 {
   UCHAR   *ROMAddr = HwInfo->pjVirtualRomBase;
-  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0;
+  USHORT  temp=0, tempax=0, tempbx=0, tempcx=0, bridgeadd=0;
   USHORT  pushbx=0, CRT1Index=0, modeflag, resinfo=0;
 #ifdef SIS315H
   USHORT  tempbl=0;
@@ -6200,40 +6082,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
     	tempbx = pushbx + tempcx;
     	tempcx <<= 1;
     	tempcx += tempbx;
-
-    	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
-	   if(SiS_Pr->UseCustomMode) {
-	      tempbx = SiS_Pr->CHSyncStart + 12;
-	      tempcx = SiS_Pr->CHSyncEnd + 12;
-	   }
-
-      	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	      unsigned char cr4, cr14, cr5, cr15;
-	      if(SiS_Pr->UseCustomMode) {
-	         cr4  = SiS_Pr->CCRT1CRTC[4];
-		 cr14 = SiS_Pr->CCRT1CRTC[14];
-		 cr5  = SiS_Pr->CCRT1CRTC[5];
-		 cr15 = SiS_Pr->CCRT1CRTC[15];
-	      } else {
-	         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-		 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-		 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-		 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-	      }
-              tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 1) << 3;
-              tempcx = (((cr5 & 0x1F) | ((cr15 & 0x04) << (6-2))) - 1) << 3;
-      	   }
-
-    	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-      	      tempbx = 1040;
-      	      tempcx = 1044;
-    	   }
-
-	}
-
-    	temp = tempbx & 0x00FF;
-    	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
+	
+	bridgeadd = 12;
 
 #endif /* SIS300 */
 
@@ -6254,11 +6104,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
 	   }
 	}
 	tempcx--;
-
-	temp = tempcx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,temp);              /* CRT2 Horizontal Total */
-
-	temp = ((tempcx & 0xff00) >> 8) << 4;
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x08,tempcx);            /* CRT2 Horizontal Total */
+	temp = (tempcx >> 4) & 0xF0;
 	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x09,0x0F,temp);    /* CRT2 Horizontal Total Overflow [7:4] */
 
 	tempcx = SiS_Pr->SiS_VGAHT;				  /* BTVGA2HDEE 0x0A,0x0C */
@@ -6270,85 +6117,83 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
 	   tempcx >>= 1;
 	}
 	tempbx += 16;
-
-	temp = tempbx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,temp);              /* CRT2 Horizontal Display Enable End */
+	
+	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0A,tempbx);            /* CRT2 Horizontal Display Enable End */
 
 	pushbx = tempbx;
 	tempcx >>= 1;
 	tempbx += tempcx;
 	tempcx += tempbx;
+	
+	bridgeadd = 16;
 
 	if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
 	   if(HwInfo->jChipType >= SIS_661) {
 	      if((SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
 		 (SiS_Pr->SiS_LCDResInfo == Panel_1280x1024)) {
 		 if(resinfo == SIS_RI_1280x1024) {
-		    tempcx = 0x30;
+		    tempcx = (tempcx & 0xff00) | 0x30;
 		 } else if(resinfo == SIS_RI_1600x1200) {
-		    tempcx = 0xff;
+		    tempcx = (tempcx & 0xff00) | 0xff;
 		 }
 	      }
 	   }
-
-	   if(SiS_Pr->UseCustomMode) {
-	      tempbx = SiS_Pr->CHSyncStart + 16;
-	      tempcx = SiS_Pr->CHSyncEnd + 16;
-	      tempax = SiS_Pr->SiS_VGAHT;
-	      if(modeflag & HalfDCLK) tempax >>= 1;
-	      tempax--;
-	      if(tempcx > tempax)  tempcx = tempax;
-	   }
-
-           if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	      unsigned char cr4, cr14, cr5, cr15;
-	      if(SiS_Pr->UseCustomMode) {
-	         cr4  = SiS_Pr->CCRT1CRTC[4];
-		 cr14 = SiS_Pr->CCRT1CRTC[14];
-		 cr5  = SiS_Pr->CCRT1CRTC[5];
-		 cr15 = SiS_Pr->CCRT1CRTC[15];
-	      } else {
-	         cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
-		 cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
-		 cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
-		 cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
-	      }
-              tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		/* (VGAHRS-3)*8 */
-              tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3; 	/* (VGAHRE-3)*8 */
-	      tempcx &= 0x00FF;
-	      tempcx |= (tempbx & 0xFF00);
-              tempbx += 16;
-              tempcx += 16;
-	      tempax = SiS_Pr->SiS_VGAHT;
-	      if(modeflag & HalfDCLK) tempax >>= 1;
-	      tempax--;
-	      if(tempcx > tempax)  tempcx = tempax;
-           }
-
-	   if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
-      	      tempbx = 1040;
-      	      tempcx = 1044;   /* HWCursor bug! */
-      	   }
-
         }
 
-	temp = tempbx & 0xff;
-	SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,temp);              /* CRT2 Horizontal Retrace Start */
 #endif  /* SIS315H */
 
      }  /* 315/330 series */
-
-     tempax = tempbx & 0xFF00;
-     tempbx = pushbx;
-     tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
-     tempax |= (tempbx & 0xFF00);
-     temp = (tempax & 0xFF00) >> 8;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);
-
-     temp = tempcx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,temp);                 /* CRT2 Horizontal Retrace End */
-
+     
+     if(SiS_Pr->SiS_VBType & VB_SISVB) {
+     
+        if(SiS_Pr->UseCustomMode) {
+	   tempbx = SiS_Pr->CHSyncStart + bridgeadd;
+	   tempcx = SiS_Pr->CHSyncEnd + bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+	}
+	
+	if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
+	   unsigned char cr4, cr14, cr5, cr15;
+	   if(SiS_Pr->UseCustomMode) {
+	      cr4  = SiS_Pr->CCRT1CRTC[4];
+	      cr14 = SiS_Pr->CCRT1CRTC[14];
+	      cr5  = SiS_Pr->CCRT1CRTC[5];
+	      cr15 = SiS_Pr->CCRT1CRTC[15];
+	   } else {
+	      cr4  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[4];
+	      cr14 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[14];
+	      cr5  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[5];
+	      cr15 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[15];
+	   }
+           tempbx = ((cr4 | ((cr14 & 0xC0) << 2)) - 3) << 3; 		    /* (VGAHRS-3)*8 */
+           tempcx = (((cr5 & 0x1f) | ((cr15 & 0x04) << (5-2))) - 3) << 3;   /* (VGAHRE-3)*8 */
+	   tempcx &= 0x00FF;
+	   tempcx |= (tempbx & 0xFF00);
+           tempbx += bridgeadd;
+           tempcx += bridgeadd;
+	   tempax = SiS_Pr->SiS_VGAHT;
+	   if(modeflag & HalfDCLK) tempax >>= 1;
+	   tempax--;
+	   if(tempcx > tempax) tempcx = tempax;
+        }
+     
+        if(SiS_Pr->SiS_TVMode & TVSetNTSC1024) {
+      	   tempbx = 1040;
+      	   tempcx = 1044;   /* HWCursor bug! */
+        }
+	
+     }
+     
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0B,tempbx);            	  /* CRT2 Horizontal Retrace Start */
+     
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0D,tempcx);               /* CRT2 Horizontal Retrace End */
+     
+     temp = ((tempbx >> 8) & 0x0F) | ((pushbx >> 4) & 0xF0);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0C,temp);		  /* Overflow */
+     
      /* 2. Vertical setup */
 
      tempcx = SiS_Pr->SiS_VGAVT - 1;
@@ -6372,12 +6217,10 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0E,temp);                 /* CRT2 Vertical Total */
 
      tempbx = SiS_Pr->SiS_VGAVDE - 1;
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,temp);                 /* CRT2 Vertical Display Enable End */
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x0F,tempbx);               /* CRT2 Vertical Display Enable End */
 
-     temp = ((tempbx & 0xFF00) << 3) >> 8;
-     temp |= ((tempcx & 0xFF00) >> 8);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow (and HWCursor Test Mode) */
+     temp = ((tempbx >> 5) & 0x38) | ((tempcx >> 8) & 0x07);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x12,temp);                 /* Overflow */
 
      if((HwInfo->jChipType >= SIS_315H) && (HwInfo->jChipType < SIS_661)) {
         tempbx++;
@@ -6396,37 +6239,33 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
      }
 
      if(SiS_Pr->SiS_VBType & VB_SISVB) {
-
 	if(SiS_Pr->UseCustomMode) {
 	   tempbx = SiS_Pr->CVSyncStart;
-	   tempcx = (tempcx & 0xFF00) | (SiS_Pr->CVSyncEnd & 0x00FF);
+	   tempcx = SiS_Pr->CVSyncEnd;
 	}
-
         if(SiS_Pr->SiS_VBInfo & SetCRT2ToRAMDAC) {
-	   unsigned char cr8, cr7, cr13, cr9;
+	   unsigned char cr8, cr7, cr13;
 	   if(SiS_Pr->UseCustomMode) {
-	      cr8  = SiS_Pr->CCRT1CRTC[8];
-	      cr7  = SiS_Pr->CCRT1CRTC[7];
-	      cr13 = SiS_Pr->CCRT1CRTC[13];
-	      cr9  = SiS_Pr->CCRT1CRTC[9];
+	      cr8    = SiS_Pr->CCRT1CRTC[8];
+	      cr7    = SiS_Pr->CCRT1CRTC[7];
+	      cr13   = SiS_Pr->CCRT1CRTC[13];
+	      tempcx = SiS_Pr->CCRT1CRTC[9];
 	   } else {
-	      cr8  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
-	      cr7  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
-	      cr13 = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
-	      cr9  = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
+	      cr8    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[8];
+	      cr7    = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[7];
+	      cr13   = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[13];
+	      tempcx = SiS_Pr->SiS_CRT1Table[CRT1Index].CR[9];
 	   }
       	   tempbx = cr8;
-      	   if(cr7 & 0x04)  tempbx |= 0x0100;
-      	   if(cr7 & 0x80)  tempbx |= 0x0200;
+      	   if(cr7  & 0x04) tempbx |= 0x0100;
+      	   if(cr7  & 0x80) tempbx |= 0x0200;
       	   if(cr13 & 0x08) tempbx |= 0x0400;
-      	   tempcx = (tempcx & 0xFF00) | (cr9 & 0x00FF);
-    	}
+       	}
      }
      SiS_SetReg(SiS_Pr->SiS_Part1Port,0x10,tempbx);               /* CRT2 Vertical Retrace Start */
 
-     temp = ((tempbx & 0xFF00) >> 8) << 4;
-     temp |= (tempcx & 0x000F);
-     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow; "Enable CRTC Check" */
+     temp = ((tempbx >> 4) & 0x70) | (tempcx & 0x0F);
+     SiS_SetReg(SiS_Pr->SiS_Part1Port,0x11,temp);                 /* CRT2 Vert. Retrace End; Overflow */
 
      /* 3. Panel delay compensation */
 
@@ -6436,7 +6275,6 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
 
 	if(SiS_Pr->SiS_VBType & VB_SISVB) {
 	   temp = 0x20;
-
 	   if(HwInfo->jChipType == SIS_300) {
 	      temp = 0x10;
 	      if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768)  temp = 0x2c;
@@ -6447,10 +6285,10 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
 	   }
 	   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x960)     temp = 0x24;
 	   if(SiS_Pr->SiS_LCDResInfo == Panel_Custom)       temp = 0x2c;
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 		temp = 0x08;
+	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) 	    temp = 0x08;
 	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
-      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	temp = 0x2c;
-      	      else 					temp = 0x20;
+      	      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) 	    temp = 0x2c;
+      	      else 					    temp = 0x20;
     	   }
 	   if(SiS_Pr->SiS_UseROM) {
 	      if(ROMAddr[0x220] & 0x80) {
@@ -6521,8 +6359,8 @@ SiS_SetGroup1(SiS_Private *SiS_Pr, USHOR
 	} /* < 661 */
 
     	tempax = 0;
-    	if (modeflag & DoubleScanMode) tempax |= 0x80;
-    	if (modeflag & HalfDCLK)       tempax |= 0x40;
+    	if(modeflag & DoubleScanMode) tempax |= 0x80;
+    	if(modeflag & HalfDCLK)       tempax |= 0x40;
     	SiS_SetRegANDOR(SiS_Pr->SiS_Part1Port,0x2C,0x3f,tempax);
 
 #endif  /* SIS315H */
@@ -6585,7 +6423,6 @@ SiS_GetGroup2CLVXPtr(SiS_Private *SiS_Pr
 	 if(SiS_Pr->SiS_TVMode & TVSetYPbPr525i) 	tableptr = SiS_Part2CLVX_3;
 	 else if(SiS_Pr->SiS_TVMode & TVSetYPbPr525p) 	tableptr = SiS_Part2CLVX_3;
 	 else 				         	tableptr = SiS_Part2CLVX_5;
-
       } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
 	 tableptr = SiS_Part2CLVX_6;
       }
@@ -6865,9 +6702,9 @@ static void
 SiS_SetGroup2(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,USHORT RefreshRateTableIndex,
 	      PSIS_HW_INFO HwInfo)
 {
-  USHORT      i, j, tempax, tempbx, tempcx, temp;
-  USHORT      push1, push2, modeflag, crt2crtc, bridgeoffset;
-  ULONG       longtemp, tempeax;
+  USHORT      i, j, tempax, tempbx, tempcx, tempch, tempcl, temp;
+  USHORT      push2, modeflag, crt2crtc, bridgeoffset;
+  ULONG       longtemp;
   const       UCHAR *PhasePoint;
   const       UCHAR *TimingPoint;
 #ifdef SIS315H
@@ -7034,47 +6871,38 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx--;
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx--;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,(tempcx & 0xff));
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1B,tempcx);
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0xF0,((tempcx >> 8) & 0x0f));
-
-  tempcx++;
-  if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) tempcx++;
-  tempcx >>= 1;
-
-  push1 = tempcx;
-
+  
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   tempcx += 7;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x22,0x0F,((tempcx << 4) & 0xf0));
 
   tempbx = TimingPoint[j] | (TimingPoint[j+1] << 8);
   tempbx += tempcx;
-
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x24,tempbx);
-  temp = ((tempbx & 0xFF00) >> 8) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0x0F,((tempbx >> 4) & 0xf0));
 
   tempbx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      tempbx -= 4;
      tempcx = tempbx;
   }
-  temp = (tempbx & 0x00FF) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x29,0x0F,((tempbx << 4) & 0xf0));
 
   j += 2;
   tempcx += (TimingPoint[j] | (TimingPoint[j+1] << 8));
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,temp);
-  temp = ((tempcx & 0xFF00) >> 8) << 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x27,tempcx);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x28,0x0F,((tempcx >> 4) & 0xf0));
 
   tempcx += 8;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) tempcx -= 4;
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2A,0x0F,((tempcx << 4) & 0xf0));
 
-  tempcx = push1;
-
+  tempcx = SiS_Pr->SiS_HT >> 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempcx >>= 1;
   j += 2;
   tempcx -= (TimingPoint[j] | ((TimingPoint[j+1]) << 8));
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2D,0x0F,((tempcx << 4) & 0xf0));
@@ -7086,54 +6914,47 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2E,tempcx);
 
   tempbx = SiS_Pr->SiS_VDE;
-  if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
-  if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
-  if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
-  if(HwInfo->jChipType < SIS_315H) {
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) tempbx >>= 1;
-  } else {
-     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
-         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
-	tempbx >>= 1;
-	if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
-	   if(ModeNo <= 0x13) {
-	      if(crt2crtc == 1) tempbx++;
-	   }
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+     if(SiS_Pr->SiS_VGAVDE == 360) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 375) tempbx = 746;
+     if(SiS_Pr->SiS_VGAVDE == 405) tempbx = 853;
+  } else if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+             (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p|TVSetYPbPr750p))) ) {
+     tempbx >>= 1;
+     if(HwInfo->jChipType >= SIS_315H) {
+        if(SiS_Pr->SiS_TVMode & TVSetTVSimuMode) {
+	   if((ModeNo <= 0x13) && (crt2crtc == 1)) tempbx++;
 	} else if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-	   if(crt2crtc == 4) {
-              if(SiS_Pr->SiS_ModeType <= 3) tempbx++;
+	   if(SiS_Pr->SiS_ModeType <= ModeVGA) {
+	      if(crt2crtc == 4) tempbx++;
 	   }
 	}
      }
-  }
-  tempbx -= 2;
-  temp = tempbx & 0x00FF;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-        if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) temp++;
-     }
-  }
-
-  if(HwInfo->jChipType < SIS_661) {
-     /* From 1.10.7w - doesn't make sense */
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
-           if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
-	      if(ModeNo == 0x03) temp++;
-	   }
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+	   if((ModeNo == 0x2f) || (ModeNo == 0x5d) || (ModeNo == 0x5e)) tempbx++;
+	} 
+	if(!(SiS_Pr->SiS_TVMode & TVSetPAL)) {
+	   if(ModeNo == 0x03) tempbx++; /* From 1.10.7w - doesn't make sense */
         }
      }
   }
-  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,temp);
+  tempbx -= 2;
+  SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2F,tempbx);
 
   temp = (tempcx >> 8) & 0x0F;
-  temp |= (((tempbx >> 8) << 6) & 0xC0);
+  temp |= ((tempbx >> 2) & 0xC0);
   if(SiS_Pr->SiS_VBInfo & (SetCRT2ToSVIDEO | SetCRT2ToAVIDEO)) {
      temp |= 0x10;
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToAVIDEO) temp |= 0x20;
   }
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x30,temp);
+  
+  if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xdf,((tempbx & 0x0400) >> 5));
+  }
 
+#if 0  
   /* TEST qqqq */
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
      for(i=0x01, j=0; i<=0x2D; i++, j++) {
@@ -7143,86 +6964,64 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
         SiS_SetReg(SiS_Pr->SiS_Part2Port,i,TimingPoint[j]);
      }
   }
+#endif
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
      tempbx = SiS_Pr->SiS_VDE;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-        if(!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) {
-           tempbx >>= 1;
-	}
+     if( (SiS_Pr->SiS_VBInfo & SetCRT2ToTV) &&
+         (!(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p))) ) {
+        tempbx >>= 1;
      }
      tempbx -= 3;
-     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  /* Why not 301B/LV? */
-        if(HwInfo->jChipType >= SIS_661) {
-           temp = 0;
-	   if(tempcx & 0x0400) temp |= 0x20;
-	   if(tempbx & 0x0400) temp |= 0x40;
-	   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x10,temp);
-	} else {
-	   if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-              if((SiS_Pr->SiS_LCDResInfo == Panel_1400x1050) ||
-                 (SiS_Pr->SiS_LCDResInfo == Panel_1600x1200) ||
-	         (SiS_Pr->SiS_LCDResInfo == Panel_1680x1050)) {
-                 SiS_SetRegOR(SiS_Pr->SiS_Part4Port,0x10,0x60);
-	      }
-           }
-	}
-     }
-     tempbx &= 0x03ff;
-     temp = ((tempbx & 0xFF00) >> 8) << 5;
-     temp |= 0x18;
+     temp = ((tempbx >> 3) & 0x60) | 0x18;
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x46,temp);
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x47,tempbx);
+     
+     if(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302LV | VB_SIS302ELV)) {  
+	SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x10,0xbf,((tempbx & 0x0400) >> 4));
+     }
   }
 
   tempbx = 0;
   if(!(modeflag & HalfDCLK)) {
      if(SiS_Pr->SiS_VGAHDE >= SiS_Pr->SiS_HDE) {
         tempax = 0;
-        tempbx |= 0x2000;
+        tempbx |= 0x20;
      }
   }
 
-  tempcx = 0x0101;
+  tempch = tempcl = 0x01;
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
      if(SiS_Pr->SiS_VGAHDE >= 1024) {
         if((!(modeflag & HalfDCLK)) || (HwInfo->jChipType < SIS_315H)) {
-           tempcx = 0x1920;
+           tempch = 0x19; 
+	   tempcl = 0x20;
            if(SiS_Pr->SiS_VGAHDE >= 1280) {
-              tempcx = 0x1420;
-              tempbx &= ~0x2000;
+              tempch = 0x14; 
+              tempbx &= ~0x20;
            }
         }
      }
   }
 
-  if(!(tempbx & 0x2000)) {
-     if(modeflag & HalfDCLK) {
-        tempcx = (tempcx & 0xFF00) | ((tempcx << 1) & 0x00FF);
-     }
-     longtemp = (SiS_Pr->SiS_VGAHDE * ((tempcx & 0xFF00) >> 8)) / (tempcx & 0x00FF);
-     longtemp <<= 13;
-     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
-     	longtemp <<= 3;
-     }
-     tempeax = longtemp / SiS_Pr->SiS_HDE;
-     if(longtemp % SiS_Pr->SiS_HDE) tempeax++;
-     tempax = (USHORT)tempeax;
-     tempbx |= (tempax & 0x1F00);
-     tempcx = (tempax & 0xFF00) >> (8 + 5);
+  if(!(tempbx & 0x20)) {
+     if(modeflag & HalfDCLK) tempcl <<= 1;
+     longtemp = ((SiS_Pr->SiS_VGAHDE * tempch) / tempcl) << 13;
+     if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) longtemp <<= 3;
+     tempax = longtemp / SiS_Pr->SiS_HDE;
+     if(longtemp % SiS_Pr->SiS_HDE) tempax++;
+     tempbx |= ((tempax >> 8) & 0x1F);
+     tempcx = tempax >> 13;
   }
 
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x44,tempax);
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,(tempbx >> 8));
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x45,0xC0,tempbx);
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 
-     temp = tempcx & 0x0007;
-     if(tempbx & 0x2000) temp = 0;
-     if((HwInfo->jChipType < SIS_661) || (!(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD))) {
-        temp |= 0x18;
-     }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xE0,temp);
+     tempcx &= 0x07;
+     if(tempbx & 0x20) tempcx = 0;
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x46,0xF8,tempcx);
 
      if(SiS_Pr->SiS_TVMode & TVSetPAL) {
         tempbx = 0x0382;
@@ -7233,7 +7032,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
      }
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4B,tempbx);
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4C,tempcx);
-     temp = (tempcx & 0x0300) >> (8 - 2);
+     temp = (tempcx & 0x0300) >> 6;
      temp |= ((tempbx >> 8) & 0x03);
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToYPbPr525750) {
         temp |= 0x10;
@@ -7243,7 +7042,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
      SiS_SetReg(SiS_Pr->SiS_Part2Port,0x4D,temp);
 
      temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x43);
-     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(USHORT)(temp - 3));
+     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x43,(temp - 3));
 
      SiS_SetTVSpecial(SiS_Pr, ModeNo);
 
@@ -7258,7 +7057,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   if(SiS_Pr->SiS_TVMode & TVSetPALM) {
      if(!(SiS_Pr->SiS_TVMode & TVSetNTSC1024)) {
         temp = SiS_GetReg(SiS_Pr->SiS_Part2Port,0x01);
-        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,temp - 1);
+        SiS_SetReg(SiS_Pr->SiS_Part2Port,0x01,(temp - 1));
      }
      SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x00,0xEF);
   }
@@ -7277,8 +7076,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
   if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
   tempbx--;			         	/* RHACTE = HDE - 1 */
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x2C,tempbx);
-  temp = (tempbx & 0xFF00) >> 4;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x2B,0x0F,((tempbx >> 4) & 0xf0));
 
   temp = 0x01;
   if(SiS_Pr->SiS_LCDResInfo == Panel_1280x1024) {
@@ -7297,21 +7095,17 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 
   tempbx = SiS_Pr->SiS_VDE - 1;
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x03,tempbx);
-  temp = ((tempbx & 0xFF00) >> 8) & 0x07;
-  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,temp);
+  SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x0C,0xF8,((tempbx >> 8) & 0x07));
 
   tempcx = SiS_Pr->SiS_VT - 1;
   SiS_SetReg(SiS_Pr->SiS_Part2Port,0x19,tempcx);
-
-  temp = ((tempcx & 0xFF00) >> 8) << 5;
-
-  /* Enable dithering; only do this for 32bpp mode */
+  temp = (tempcx >> 3) & 0xE0;    
   if(SiS_Pr->SiS_LCDInfo & LCDRGB18Bit) {
+     /* Enable dithering; only do this for 32bpp mode */
      if(SiS_GetReg(SiS_Pr->SiS_Part1Port,0x00) & 0x01) {
         temp |= 0x10;
      }
   }
-
   SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1A,0x0f,temp);
 
   SiS_SetRegAND(SiS_Pr->SiS_Part2Port,0x09,0xF0);
@@ -7380,7 +7174,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
        tempbx -= tempax; /* lcdvdee */
     }
 
-    /* Non-expanding: lcdvdees = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
+    /* Non-expanding: lcdvdes = tempcx = VT-1; lcdvdee = tempbx = VDE-1 */
 
 #ifdef TWDEBUG
     xf86DrvMsg(0, X_INFO, "lcdvdes 0x%x lcdvdee 0x%x\n", tempcx, tempbx);
@@ -7389,8 +7183,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x05,tempcx);	/* lcdvdes  */
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x06,tempbx);	/* lcdvdee  */
 
-    temp = ((tempbx & 0xFF00) >> 8) << 3;
-    temp |= ((tempcx & 0xFF00) >> 8);
+    temp = (tempbx >> 5) & 0x38;
+    temp |= ((tempcx >> 8) & 0x07);
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x02,temp);
 
     tempax = SiS_Pr->SiS_VDE;
@@ -7412,7 +7206,10 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 	     if(tempax % 4) { tempax >>= 2; tempax++; }
 	     else           { tempax >>= 2;           }
              tempbx -= (tempax - 1);
-	  } else tempbx -= 10;
+	  } else {
+	     tempbx -= 10;
+	     if(tempbx <= SiS_Pr->SiS_VDE) tempbx = SiS_Pr->SiS_VDE + 1;
+	  }
        }
     }
     if(SiS_Pr->SiS_LCDResInfo == Panel_1024x768) {
@@ -7437,9 +7234,9 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x04,tempbx);	    /* lcdvrs */
 
-    temp = ((tempbx & 0xFF00) >> 8) << 4;
+    temp = (tempbx >> 4) & 0xF0;
     tempbx += (tempcx + 1);
-    temp |= (tempbx & 0x000F);
+    temp |= (tempbx & 0x0F);
 
     if(SiS_Pr->UseCustomMode) {
        temp &= 0xf0;
@@ -7469,9 +7266,8 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
        }
     }
     temp += bridgeoffset;
-    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	    /* lcdhdes[7:0] */
-    temp = (temp >> 4) & 0xf0;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,temp);  /* lcdhdes [11:8] */
+    SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1F,temp);  	     /* lcdhdes */
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x20,0x0F,((temp >> 4) & 0xf0));
 
     tempcx = SiS_Pr->SiS_HT;
     tempax = tempbx = SiS_Pr->SiS_HDE;
@@ -7494,8 +7290,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
     tempbx += bridgeoffset;
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x23,tempbx);	    /* lcdhdee */
-    temp = (tempbx >> 8) & 0x0f;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,temp);
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x25,0xF0,((tempbx >> 8) & 0x0f));
 
     tempcx = (tempcx - tempax) >> 2;
 
@@ -7521,8 +7316,7 @@ SiS_SetGroup2(SiS_Private *SiS_Pr, USHOR
 #endif
 
     SiS_SetReg(SiS_Pr->SiS_Part2Port,0x1C,tempbx);	    /* lcdhrs */
-    temp = (tempbx & 0x0F00) >> 4;
-    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,temp);
+    SiS_SetRegANDOR(SiS_Pr->SiS_Part2Port,0x1D,0x0F,((tempbx >> 4) & 0xf0));
 
     tempbx = push2;
 
@@ -7646,7 +7440,8 @@ SiS_SetGroup4_C_ELV(SiS_Private *SiS_Pr,
 {
    USHORT temp, temp1, resinfo = 0;
 
-   if(!(SiS_Pr->SiS_VBType & (VB_SIS301C | VB_SIS302ELV))) return;
+   if(!(SiS_Pr->SiS_VBType & VB_SIS301C)) return;
+   if(!(SiS_Pr->SiS_VBInfo & (SetCRT2ToHiVision | SetCRT2ToYPbPr525750))) return;
 
    if(ModeNo > 0x13) {
       resinfo = SiS_Pr->SiS_EModeIDTable[ModeIdIndex].Ext_RESINFO;
@@ -7737,7 +7532,7 @@ static void
 SiS_SetGroup4(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex,
   	      USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo)
 {
-  USHORT tempax,tempcx,tempbx,modeflag,temp,temp2,resinfo;
+  USHORT tempax,tempcx,tempbx,modeflag,temp,resinfo;
   ULONG tempebx,tempeax,templong;
 
   if(ModeNo <= 0x13) {
@@ -7783,167 +7578,138 @@ SiS_SetGroup4(SiS_Private *SiS_Pr, USHOR
      }
   }
 
-  temp = SiS_Pr->SiS_RVBHCFACT;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,temp);
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x13,SiS_Pr->SiS_RVBHCFACT);
 
   tempbx = SiS_Pr->SiS_RVBHCMAX;
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x14,tempbx);
 
-  temp2 = (tempbx >> 1) & 0x0080;
+  temp = (tempbx >> 1) & 0x80;
 
   tempcx = SiS_Pr->SiS_VGAHT - 1;
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x16,tempcx);
 
-  temp2 |= (((tempcx & 0xFF00) >> 8) << 3) & 0x00ff;
+  temp |= ((tempcx >> 5) & 0x78);
 
   tempcx = SiS_Pr->SiS_VGAVT - 1;
   if(!(SiS_Pr->SiS_VBInfo & SetCRT2ToTV)) tempcx -= 5;
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x17,tempcx);
 
-  temp = temp2 | (tempcx >> 8);
+  temp |= ((tempcx >> 8) & 0x07);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x15,temp);
 
   tempbx = SiS_Pr->SiS_VGAHDE;
-  if(modeflag & HalfDCLK) tempbx >>= 1;
-  if(HwInfo->jChipType >= SIS_661) {
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
-  }
-
-  temp = 0xA0;
-  if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+  if(modeflag & HalfDCLK)            tempbx >>= 1;
+  if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
+    
+  if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
      temp = 0;
-     if(tempbx > 800) {
-        temp = 0xA0;
-        if(tempbx != 1024) {
-           temp = 0xC0;
-           if(tempbx != 1280) temp = 0;
-	}
-     }
-  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
-     if(tempbx <= 800) {
-        temp = 0x80;
-     }
+     if(tempbx > 800)        temp = 0x60;
+  } else if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
+     temp = 0;
+     if(tempbx == 1024)      temp = 0xA0;
+     else if(tempbx > 1024)  temp = 0xC0;
+  } else if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
+     temp = 0;
+     if(tempbx >= 1280)      temp = 0x40;
+     else if(tempbx >= 1024) temp = 0x20;
   } else {
      temp = 0x80;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-        temp = 0;
-        if(tempbx > 800) temp = 0x60;
-     }
-  }
-
-  if(SiS_Pr->SiS_TVMode & (TVSetYPbPr525p | TVSetYPbPr750p)) {
-     temp = 0;
-     if(SiS_Pr->SiS_VGAHDE == 1024) temp = 0x20;
-  }
-
-  if(HwInfo->jChipType < SIS_661) {
-     if(SiS_IsDualLink(SiS_Pr, HwInfo)) temp = 0;
+     if(tempbx >= 1024)      temp = 0xA0;
   }
 
   if(SiS_Pr->SiS_VBType & VB_SIS301) {
-     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024)
-        temp |= 0x0A;
+     if(SiS_Pr->SiS_LCDResInfo != Panel_1280x1024) temp |= 0x0A;
   }
 
   SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0E,0x10,temp);
-
+  
+  tempeax = SiS_Pr->SiS_VGAVDE;  
   tempebx = SiS_Pr->SiS_VDE;
-
   if(SiS_Pr->SiS_VBInfo & SetCRT2ToHiVision) {
      if(!(temp & 0xE0)) tempebx >>=1;
-  }
-
+  }  
+  
   tempcx = SiS_Pr->SiS_RVBHRS;
-  temp = tempcx & 0x00FF;
-  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,temp);
-
-  tempeax = SiS_Pr->SiS_VGAVDE;
-  tempcx |= 0x4000;
+  SiS_SetReg(SiS_Pr->SiS_Part4Port,0x18,tempcx);
+  tempcx >>= 8;
+  tempcx |= 0x40;
+  
   if(tempeax <= tempebx) {
-     tempcx ^= 0x4000;
+     tempcx ^= 0x40;
   } else {
      tempeax -= tempebx;
   }
 
-  templong = (tempeax * 256 * 1024) % tempebx;
-  tempeax = (tempeax * 256 * 1024) / tempebx;
-  tempebx = tempeax;
-  if(templong != 0) tempebx++;
+  tempeax *= (256 * 1024);
+  templong = tempeax % tempebx;
+  tempeax /= tempebx;
+  if(templong) tempeax++;
 
-  temp = (USHORT)(tempebx & 0x000000FF);
+  temp = (USHORT)(tempeax & 0x000000FF);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1B,temp);
-  temp = (USHORT)((tempebx & 0x0000FF00) >> 8);
+  temp = (USHORT)((tempeax & 0x0000FF00) >> 8);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1A,temp);
-
-  tempbx = (USHORT)(tempebx >> 16);
-  temp = tempbx & 0x00FF;
-  temp <<= 4;
-  temp |= ((tempcx & 0xFF00) >> 8);
+  temp = (USHORT)((tempeax >> 12) & 0x70); /* sic! */
+  temp |= (tempcx & 0x4F);
   SiS_SetReg(SiS_Pr->SiS_Part4Port,0x19,temp);
 
   if(SiS_Pr->SiS_VBType & VB_SIS301BLV302BLV) {
 
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1C,0x28);
 
+     /* Calc Linebuffer max address and set/clear decimode */
      tempbx = 0;
+     if(SiS_Pr->SiS_TVMode & (TVSetHiVision | TVSetYPbPr750p)) tempbx = 0x08;
      tempax = SiS_Pr->SiS_VGAHDE;
-     if(modeflag & HalfDCLK) 		tempax >>= 1;
+     if(modeflag & HalfDCLK)            tempax >>= 1;
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempax >>= 1;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
-	if(tempax > 800) tempax -= 800;
-     } else /* if(SiS_Pr->SiS_VBInfo & TvNoHiviNoYPbPr) */ {    /* 651+301C */
-        if(tempax > 800) {
-	   tempbx = 8;
+     if(tempax > 800) {
+        if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+	   tempax -= 800;
+	} else {  /* 651+301C: Only if TVNoHiviNoYPbPr */
+	   tempbx = 0x08;
            if(tempax == 1024) tempax *= 25;
            else	              tempax *= 20;
 	   temp = tempax % 32;
 	   tempax /= 32;
-	   tempax--;
-	   if (temp!=0) tempax++;
-        }
-     }
+	   if(temp) tempax++;
+	   tempax++;
+	   if((SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) || 
+	      (SiS_Pr->SiS_TVMode & TVSetYPbPr525i)) {
+	      if(resinfo == SIS_RI_1024x768) {
+	         /* Otherwise white line at right edge */
+	         tempax = (tempax & 0xff00) | 0x20;
+	      }
+	   }
+	}
+     }    
      tempax--;
-     temp = ((tempax & 0xFF00) >> 8) & 0x03;
-     if(SiS_Pr->SiS_VBInfo & SetCRT2ToTVNoYPbPrHiVision) {	/* From 1.10.7w */
-	if(ModeNo > 0x13) {					/* From 1.10.7w */
-	   if(resinfo == SIS_RI_1024x768) tempax = 0x1f;	/* From 1.10.7w */
-	   /* ax normally 0x1e */				/* From 1.10.7w */
-	}							/* From 1.10.7w */
-     }								/* From 1.10.7w */
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax & 0x00FF);
-     temp <<= 4;
-     temp |= tempbx;
+     temp = ((tempax >> 4) & 0x30) | tempbx;    
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1D,tempax);
      SiS_SetReg(SiS_Pr->SiS_Part4Port,0x1E,temp);
 
-     if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
-	if(IS_SIS550650740660) {
-	   temp = 0x0026;  /* 1.10.7w; 1.10.8r; needs corresponding code in Dis/EnableBridge! */
-	} else {
-	   temp = 0x0036;
-	}
-     } else {
-	temp = 0x0036;
+     temp = 0x0036; tempbx = 0xD0;
+     if((IS_SIS550650740660) && (SiS_Pr->SiS_VBType & VB_SIS301LV302LV)) {
+	temp = 0x0026; tempbx = 0xC0; /* See En/DisableBridge() */
      }
      if(SiS_Pr->SiS_VBInfo & SetCRT2ToTV) {
         if(!(SiS_Pr->SiS_TVMode & (TVSetNTSC1024 | TVSetHiVision | TVSetYPbPr750p | TVSetYPbPr525p))) {
 	   temp |= 0x01;
 	   if(SiS_Pr->SiS_VBInfo & SetInSlaveMode) {
 	      if(!(SiS_Pr->SiS_TVMode & TVSetTVSimuMode)) {
-  	         temp &= 0xFE;
+  	         temp &= ~0x01;
 	      }
 	   }
 	}
      }
-     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,0xC0,temp);
+     SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x1F,tempbx,temp);
 
-     tempbx = SiS_Pr->SiS_HT;
+     tempbx = SiS_Pr->SiS_HT >> 1;
      if(SiS_IsDualLink(SiS_Pr, HwInfo)) tempbx >>= 1;
-     tempbx >>= 1;
      tempbx -= 2;
-     temp = ((tempbx & 0x0700) >> 8) << 3;
+     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,tempbx);
+     temp = (tempbx >> 5) & 0x38;
      SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x21,0xC0,temp);
-     temp = tempbx & 0x00FF;
-     SiS_SetReg(SiS_Pr->SiS_Part4Port,0x22,temp);
 
      if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 	if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
@@ -9881,7 +9647,7 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
 	        }
 	        break;
 	    case 1280:
-	        if(yres == 1024) {
+	        if(yres == 1024) {	
 	     	   paneltype = Panel_1280x1024;
 		   checkexpand = TRUE;
 	        } else if(yres == 960) {
@@ -10328,14 +10094,17 @@ SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SIS
        if(!SiS_Pr->CP_PreferredX) SiS_Pr->CP_PreferredX = SiS_Pr->CP_MaxX;
        if(!SiS_Pr->CP_PreferredY) SiS_Pr->CP_PreferredY = SiS_Pr->CP_MaxY;
        SiS_SetRegOR(SiS_Pr->SiS_P3d4,0x32,0x08);
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x36,0xf0,paneltype);
+       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,paneltype);
        cr37 &= 0xf1;
-       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0xf3,cr37);
+       SiS_SetRegANDOR(SiS_Pr->SiS_P3d4,0x37,0x0c,cr37);
        SiS_Pr->PanelSelfDetected = TRUE;
 #ifdef TWDEBUG
        xf86DrvMsgVerb(pSiS->pScrn->scrnIndex, X_PROBED, 3, 
-       	"CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
+       	   "CRT2: [DDC LCD results: 0x%02x, 0x%02x]\n", paneltype, cr37);
 #endif	
+   } else {
+       SiS_SetRegAND(SiS_Pr->SiS_P3d4,0x32,~0x08);
+       SiS_SetReg(SiS_Pr->SiS_P3d4,0x36,0x00);
    }
    return 0;
 }
@@ -10944,6 +10713,7 @@ SetDelayComp(SiS_Private *SiS_Pr, PSIS_H
            delay = SiS310_LCDDelayCompensation_301[myindex];
 	   if(SiS_Pr->SiS_VBType & VB_SIS301LV302LV) {
 	      if(IS_SIS740) delay = 0x01;
+	      else if(HwInfo->jChipType <= SIS_315PRO) delay = SiS310_LCDDelayCompensation_3xx301LV[myindex];
 	      else          delay = SiS310_LCDDelayCompensation_650301LV[myindex];
 	   } else if(SiS_Pr->SiS_VBType & VB_SIS301C) {
 	      if(IS_SIS740) delay = 0x01;  /* ? */
@@ -11329,7 +11099,9 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSI
          }
 	 if(index < 25) index = 25;
          index = ((index / 25) - 1) << 1;
-         if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) index++;
+         if((ROMAddr[0x5b] & 0x80) || (SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD))) {
+	    index++;
+	 }
 	 romptr = SISGETROMW(0x104);  /* 0x4ae */
          delay = ROMAddr[romptr + index];
          if(SiS_Pr->SiS_VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD)) {
@@ -11386,16 +11158,18 @@ SetDelayComp661(SiS_Private *SiS_Pr, PSI
             } else
 	       delay = 0x0000;
          }
+	 
+	 /* Override by detected or user-set values */
+	 /* (but only if, for some reason, we can't read value from BIOS) */
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
+            delay = SiS_Pr->PDC & 0x1f;
+         }
+         if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
+            delay = (SiS_Pr->PDCA & 0x1f) << 8;
+         }
 
       }
-
-      /* Override by detected or user-set values */
-      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) && (SiS_Pr->PDC != -1)) {
-         delay = SiS_Pr->PDC & 0x1f;
-      }
-      if((SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) && (SiS_Pr->PDCA != -1)) {
-         delay = (SiS_Pr->PDCA & 0x1f) << 8;
-      }
+     
    }
 
    if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCDA) {
@@ -11477,8 +11251,10 @@ SetPanelParms661(SiS_Private *SiS_Pr, PS
 	    }
 	    SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x24,temp2,temp1);
          }
-         temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
-         SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
+	 if(SiS_Pr->SiS_VBInfo & SetCRT2ToLCD) {
+            temp1 = (ROMAddr[romptr + 1] & 0x80) >> 1;
+            SiS_SetRegANDOR(SiS_Pr->SiS_Part4Port,0x0d,0xbf,temp1);
+	 }
       }
 
    }
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/init301.h linux-2.4.27-rc4/drivers/video/sis/init301.h
--- linux-2.4.26/drivers/video/sis/init301.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/init301.h	2004-07-30 16:28:34.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Data and prototypes for init301.c
  *
@@ -88,8 +89,8 @@ const UCHAR SiS_YPbPrTable[3][64] = {
     0x06,0x14,0x0d,0x04,0x0a,0x00,0x85,0x1b,
     0x0c,0x50,0x00,0x97,0x00,0xda,0x4a,0x17,
     0x7d,0x05,0x4b,0x00,0x00,0xe2,0x00,0x02,
-    0x03,0x0a,0x65,0x8d /*0x9d*/,0x08,0x92,0x8f,0x40,
-    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x50 /*0x53*/,
+    0x03,0x0a,0x65,0x9d /*0x8d*/,0x08,0x92,0x8f,0x40,
+    0x60,0x80,0x14,0x90,0x8c,0x60,0x14,0x53 /*0x50*/,
     0x00,0x40,0x44,0x00,0xdb,0x02,0x3b,0x00
   },
   {
@@ -217,49 +218,44 @@ static const UCHAR SiS_Part2CLVX_6[] = {
     0x00,0x04,
     0x04,0x1A,0x04,0x7E,0x02,0x1B,0x05,0x7E,0x01,0x1A,0x07,0x7E,0x00,0x1A,0x09,0x7D,
     0x7F,0x19,0x0B,0x7D,0x7E,0x18,0x0D,0x7D,0x7D,0x17,0x10,0x7C,0x7D,0x15,0x12,0x7C,
-    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x1D /* 0x7D? */ ,0x7C,0x0D,0x18,0x7F,
+    0x7C,0x14,0x14,0x7C,0x7C,0x12,0x15,0x7D,0x7C,0x10,0x17,0x7D /* 0x1D(6330)? */ ,0x7C,0x0D,0x18,0x7F,
     0x7D,0x0B,0x19,0x7F,0x7D,0x09,0x1A,0x00,0x7D,0x07,0x1A,0x02,0x7E,0x05,0x1B,0x02,
     0xFF,0xFF,
 };
 
-
 #ifdef SIS315H
-/* 661 et al LCD data structure */
+/* 661 et al LCD data structure (0.94.0) */
 static const UCHAR SiS_LCDStruct661[] = {
     /* 1024x768 */
 /*  type|CR37|   HDE   |   VDE   |    HT   |    VT   |   hss    | hse   */
     0x02,0xC0,0x00,0x04,0x00,0x03,0x40,0x05,0x26,0x03,0x10,0x00,0x88,
-    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x37,0x6E,0x05,0x6E,0x04,
+    0x00,0x02,0x00,0x06,0x00,0x41,0x5A,0x64,0x00,0x00,0x00,0x00,0x04,
     /*  | vss      |   vse  |clck|  clock  |CRT2DataP|CRT2DataP|idx     */
     /*					      VESA    non-VESA  noscale */
     /* 1280x1024 */
-    0x03,0xE0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
-    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x5F,0x6F,0xDB,0x6F,0x08,
+    0x03,0xC0,0x00,0x05,0x00,0x04,0x98,0x06,0x2A,0x04,0x30,0x00,0x70,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x08,
     /* 1400x1050 */
     0x09,0x20,0x78,0x05,0x1A,0x04,0x98,0x06,0x2A,0x04,0x18,0x00,0x38,
-    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x35,0x70,0x00,0x00,0x09,
+    0x00,0x01,0x00,0x03,0x00,0x6C,0xF8,0x2F,0x00,0x00,0x00,0x00,0x09,
     /* 1600x1200 */
-    0x0B,0xE0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
-    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x07,0x71,0x00,0x00,0x0B,
+    0x0B,0xC0,0x40,0x06,0xB0,0x04,0x70,0x08,0xE2,0x04,0x40,0x00,0xC0,
+    0x00,0x01,0x00,0x03,0x00,0xA2,0x70,0x24,0x00,0x00,0x00,0x00,0x0B,
     /* 1280x768 */
     0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x05,0x26,0x03,0x10,0x00,0x40,
-    0x00,0x03,0x00,0x06,0x00,0x44,0x63,0x46,0xEB,0x6E,0xA5,0x6E,0x06,
+    0x00,0x03,0x00,0x06,0x00,0x44,0x63,0x46,0x00,0x00,0x00,0x00,0x06,
     /* 1280x720 */
-    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x40,0x05,0x26,0x03,0x10,0x00,0x02,
-    0x00,0x01,0x00,0x06,0x00,0x41,0x5A,0x64,0x69,0x6E,0x00,0x00,0x05,
-#if 0 /* 0.92: */
-    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x72,0x06,0xEE,0x02,0x2A,0x00,0x3F,
-    0x00,0x01,0x00,0x06,0x00,0x41,0x00,0x00,0xA7,0x6A,0x00,0x00,0x05,
-#endif
+    0x0E,0xE0,0x00,0x05,0xD0,0x02,0x80,0x05,0x26,0x03,0x10,0x00,0x02,
+    0x00,0x01,0x00,0x06,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x05,
     /* 1280x800 */
-    0x0C,0xE0,0x00,0x05,0x20,0x03,0x80,0x05,0x30,0x03,0x15,0x00,0x18,
-    0x00,0x04,0x00,0x03,0x00,0x45,0x9C,0x62,0x31,0x6F,0x00,0x00,0x07,
+    0x0C,0xE0,0x00,0x05,0x20,0x03,0x80,0x05,0x30,0x03,0x10,0x00,0x40,
+    0x00,0x04,0x00,0x03,0x00,0x45,0x9C,0x62,0x00,0x00,0x00,0x00,0x07,
     /* 1680x1050 */
     0x0D,0xE0,0x90,0x06,0x1A,0x04,0x6C,0x07,0x2A,0x04,0x1A,0x00,0x4C,
-    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x99,0x70,0x00,0x00,0x0A, /* 0.93: 0x0A=0x06 - WRONG? */
+    0x00,0x03,0x00,0x06,0x00,0x79,0xBE,0x44,0x00,0x00,0x00,0x00,0x06, 
     /* 1280x768 (not in 0.93) */
     0x0A,0xC0,0x00,0x05,0x00,0x03,0x80,0x06,0x1E,0x03,0x40,0x00,0x80,
-    0x00,0x03,0x00,0x07,0x00,0x4F,0x00,0x00,0x6F,0x6B,0x00,0x00,0x06
+    0x00,0x03,0x00,0x07,0x00,0x4F,0x00,0x00,0x00,0x00,0x00,0x00,0x06
 };
 #endif
 
@@ -347,46 +343,45 @@ USHORT  SiS_GetTrumpReg(SiS_Private *SiS
 static  BOOLEAN SiS_SetTrumpionBlock(SiS_Private *SiS_Pr, UCHAR *dataptr);
 #endif
 
-
-USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
-void     SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
-USHORT   SiS_SetStart(SiS_Private *SiS_Pr);
-USHORT   SiS_SetStop(SiS_Private *SiS_Pr);
-void     SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
-USHORT   SiS_SetSCLKLow(SiS_Private *SiS_Pr);
-USHORT   SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
-USHORT   SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT   SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
-USHORT   SiS_CheckACK(SiS_Private *SiS_Pr);
-
-USHORT   SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-                         USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
-USHORT   SiS_WriteDABDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_PrepareDDC(SiS_Private *SiS_Pr);
-void     SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
-USHORT   SiS_DoProbeDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_ProbeDDC(SiS_Private *SiS_Pr);
-USHORT   SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer);
-USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
-		       USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
+USHORT  SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);
+void    SiS_SetSwitchDDC2(SiS_Private *SiS_Pr);
+USHORT  SiS_SetStart(SiS_Private *SiS_Pr);
+USHORT  SiS_SetStop(SiS_Private *SiS_Pr);
+void    SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
+USHORT  SiS_SetSCLKLow(SiS_Private *SiS_Pr);
+USHORT  SiS_SetSCLKHigh(SiS_Private *SiS_Pr);
+USHORT  SiS_ReadDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
+USHORT  SiS_WriteDDC2Data(SiS_Private *SiS_Pr, USHORT tempax);
+USHORT  SiS_CheckACK(SiS_Private *SiS_Pr);
+
+USHORT  SiS_InitDDCRegs(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
+                        USHORT adaptnum, USHORT DDCdatatype, BOOLEAN checkcr32);
+USHORT  SiS_WriteDABDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_PrepareReadDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_PrepareDDC(SiS_Private *SiS_Pr);
+void    SiS_SendACK(SiS_Private *SiS_Pr, USHORT yesno);
+USHORT  SiS_DoProbeDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_ProbeDDC(SiS_Private *SiS_Pr);
+USHORT  SiS_ReadDDC(SiS_Private *SiS_Pr, USHORT DDCdatatype, unsigned char *buffer);
+USHORT  SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
+		      USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
 #ifdef LINUX_XF86
-USHORT   SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
-USHORT   SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+USHORT  SiS_SenseLCDDDC(SiS_Private *SiS_Pr, SISPtr pSiS);
+USHORT  SiS_SenseVGA2DDC(SiS_Private *SiS_Pr, SISPtr pSiS);
 #endif
 
 #ifdef SIS315H
-void     SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo,USHORT ModeIdIndex);
-void     SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
-void     SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
+void    SiS_OEM310Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo,USHORT ModeIdIndex);
+void    SiS_OEM661Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo,USHORT ModeIdIndex, USHORT RRTI);
+void    SiS_FinalizeLCD(SiS_Private *, USHORT, USHORT, PSIS_HW_INFO);
 #endif
 #ifdef SIS300
-void     SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-                           USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
-void     SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
-			USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
+void    SiS_OEM300Setting(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+                          USHORT ModeNo, USHORT ModeIdIndex, USHORT RefTabindex);
+void    SetOEMLCDData2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo,
+		       USHORT ModeNo, USHORT ModeIdIndex,USHORT RefTableIndex);
 #endif
 
 extern void     SiS_SetReg(SISIOADDRESS, USHORT, USHORT);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/initdef.h linux-2.4.27-rc4/drivers/video/sis/initdef.h
--- linux-2.4.26/drivers/video/sis/initdef.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/initdef.h	2004-07-30 16:29:23.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * Global definitions for init.c and init301.c
  *
@@ -84,6 +85,8 @@
 #define VB_SIS301B302B          (VB_SIS301B|VB_SIS301C|VB_SIS302B)
 #define VB_SIS301LV302LV        (VB_SIS301LV|VB_SIS302LV|VB_SIS302ELV)
 #define VB_SISVB		(VB_SIS301 | VB_SIS301BLV302BLV)
+#define VB_SISTMDS		(VB_SIS301 | VB_SIS301B302B)
+#define VB_SISLVDS		VB_SIS301LV302LV
 
 /* VBInfo */
 #define SetSimuScanMode         0x0001   /* CR 30 */
@@ -136,6 +139,7 @@
 #define CRT2Mode                0x0800
 #define HalfDCLK                0x1000
 #define NoSupportSimuTV         0x2000
+#define NoSupportLCDScale	0x4000 /* TMDS: No scaling possible (no matter what panel) */
 #define DoubleScanMode          0x8000
 
 /* Infoflag */
@@ -200,7 +204,7 @@
 #define SF_IsM661		0x0020
 #define SF_IsM741		0x0040
 #define SF_IsM760		0x0080
-#define SF_760UMA		0x8000
+#define SF_760LFB		0x8000  /* 760: We have LFB */
 
 /* CR32 (Newer 630, and 315 series)
 
@@ -478,13 +482,23 @@
 #define VCLK100_315             0x46   /* Index in VBVCLKData table (315) */
 #define VCLK34_315              0x55
 #define VCLK68_315		0x0d
-#define VCLK69_315		0x5c   /* Index in VBVCLKData table (315) */
+#define VCLK69_315		0x5c   /* deprecated ! Index in VBVCLKData table (315) */
+#define VCLK83_315		0x5c   /* Index in VBVCLKData table (315) */
 #define VCLK121_315		0x5d   /* Index in VBVCLKData table (315) */
 #define VCLK_1280x720		0x5f
 #define VCLK_1280x768_2		0x60
 #define VCLK_1280x768_3		0x61
 #define VCLK_CUSTOM_315		0x62
 #define VCLK_1280x720_2		0x63
+#define VCLK_720x480		0x67 
+#define VCLK_720x576		0x68
+#define VCLK_768x576		0x68
+#define VCLK_848x480		0x65
+#define VCLK_856x480		0x66
+#define VCLK_800x480		0x65
+#define VCLK_1024x576		0x51
+#define VCLK_1152x864		0x64
+#define VCLK_1360x768		0x58
 
 #define TVCLKBASE_300		0x21   /* Indices on TV clocks in VCLKData table (300) */
 #define TVCLKBASE_315	        0x3a   /* Indices on TV clocks in (VB)VCLKData table (315) */
@@ -595,7 +609,7 @@
 
 /*
   =============================================================
-   			  for 315 series
+   		  for 315 series (old data layout)
   =============================================================
 */
 #define SoftDRAMType        0x80
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/oem300.h linux-2.4.27-rc4/drivers/video/sis/oem300.h
--- linux-2.4.26/drivers/video/sis/oem300.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/oem300.h	2004-07-30 16:26:58.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OEM Data for 300 series
  *
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/oem310.h linux-2.4.27-rc4/drivers/video/sis/oem310.h
--- linux-2.4.26/drivers/video/sis/oem310.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/oem310.h	2004-07-30 16:24:24.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OEM Data for 315/330 series
  *
@@ -126,7 +127,7 @@ static const UCHAR SiS310_LCDDelayCompen
 		 0x33,0x33,0x33
 };
 
-static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB,LV */
+static const UCHAR SiS310_LCDDelayCompensation_3xx301B[] =	   	/* 30xB */
 {
 		 0x01,0x01,0x01,    /*   800x600 */
 		 0x0C,0x0C,0x0C,    /*  1024x768 */
@@ -145,6 +146,25 @@ static const UCHAR SiS310_LCDDelayCompen
 		 0x02,0x02,0x02
 };
 
+static const UCHAR SiS310_LCDDelayCompensation_3xx301LV[] =	   	/* 315+30xLV */
+{
+		 0x01,0x01,0x01,    /*   800x600 */
+		 0x04,0x04,0x04,    /*  1024x768 (A531/BIOS 1.14.05f: 4 - works with 6 */
+		 0x0C,0x0C,0x0C,    /* 1280x1024 */
+                 0x08,0x08,0x08,    /*   640x480 */
+		 0x0C,0x0C,0x0C,    /*  1024x600 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x864 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x960 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1152x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1400x1050 (guessed) */
+		 0x0C,0x0C,0x0C,    /*  1280x768 (guessed) */
+		 0x0C,0x0C,0x0C,    /* 1600x1200 (guessed) */
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02,
+		 0x02,0x02,0x02
+};
+
 static const UCHAR SiS310_TVDelayCompensation_301[] = 		/* 301 */
 {
 		 0x02,0x02,    /* NTSC Enhanced, Standard */
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/osdef.h linux-2.4.27-rc4/drivers/video/sis/osdef.h
--- linux-2.4.26/drivers/video/sis/osdef.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/osdef.h	2004-07-30 16:24:26.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * OS depending defines
  *
@@ -84,7 +85,6 @@
 
 #ifdef LINUX_KERNEL
 #include <linux/config.h>
-#include <linux/version.h>
 
 #ifdef CONFIG_FB_SIS_300
 #define SIS300
@@ -94,10 +94,6 @@
 #define SIS315H
 #endif
 
-#if 1
-#define SISFBACCEL	/* Include 2D acceleration */
-#endif
-
 #define OutPortByte(p,v) outb((u8)(v),(SISIOADDRESS)(p))
 #define OutPortWord(p,v) outw((u16)(v),(SISIOADDRESS)(p))
 #define OutPortLong(p,v) outl((u32)(v),(SISIOADDRESS)(p))
@@ -108,7 +104,7 @@
 #endif
 
 /**********************************************************************/
-/*  XFree86                                                           */
+/*  XFree86, X.org                                                    */
 /**********************************************************************/
 
 #ifdef LINUX_XF86
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/sis.h linux-2.4.27-rc4/drivers/video/sis/sis.h
--- linux-2.4.26/drivers/video/sis/sis.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/sis.h	2004-07-30 16:26:48.000000000 +0000
@@ -1,10 +1,512 @@
+/*
+ * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330/760
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
+ *
+ * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
+ *
+ * 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 named License,
+ * or 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 _SIS_H
 #define _SIS_H
 
-#if 1
-#define TWDEBUG(x)
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include "osdef.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <video/sisfb.h>
 #else
+#include <linux/sisfb.h>
+#endif
+
+#include "vgatypes.h"
+#include "vstruct.h"
+
+#define VER_MAJOR                 1
+#define VER_MINOR                 7
+#define VER_LEVEL                 10
+
+#undef SIS_CONFIG_COMPAT
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/spinlock.h>
+#ifdef CONFIG_COMPAT
+#include <linux/ioctl32.h>
+#define SIS_CONFIG_COMPAT
+#endif
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,19)
+#ifdef __x86_64__
+/* Shouldn't we check for CONFIG_IA32_EMULATION here? */
+#include <asm/ioctl32.h>
+#define SIS_CONFIG_COMPAT
+#endif
+#endif
+
+#undef SISFBDEBUG
+
+#ifdef SISFBDEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #define TWDEBUG(x) printk(KERN_INFO x "\n");
+#else
+#define DPRINTK(fmt, args...)
+#define TWDEBUG(x)
+#endif
+
+#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
+
+/* To be included in pci_ids.h */
+#ifndef PCI_DEVICE_ID_SI_650_VGA
+#define PCI_DEVICE_ID_SI_650_VGA  0x6325
+#endif
+#ifndef PCI_DEVICE_ID_SI_650
+#define PCI_DEVICE_ID_SI_650      0x0650
+#endif
+#ifndef PCI_DEVICE_ID_SI_651
+#define PCI_DEVICE_ID_SI_651      0x0651
 #endif
+#ifndef PCI_DEVICE_ID_SI_740
+#define PCI_DEVICE_ID_SI_740      0x0740
+#endif
+#ifndef PCI_DEVICE_ID_SI_330
+#define PCI_DEVICE_ID_SI_330      0x0330
+#endif
+#ifndef PCI_DEVICE_ID_SI_660_VGA
+#define PCI_DEVICE_ID_SI_660_VGA  0x6330
+#endif
+#ifndef PCI_DEVICE_ID_SI_661
+#define PCI_DEVICE_ID_SI_661      0x0661
+#endif
+#ifndef PCI_DEVICE_ID_SI_741
+#define PCI_DEVICE_ID_SI_741      0x0741
+#endif
+#ifndef PCI_DEVICE_ID_SI_660
+#define PCI_DEVICE_ID_SI_660      0x0660
+#endif
+#ifndef PCI_DEVICE_ID_SI_760
+#define PCI_DEVICE_ID_SI_760      0x0760
+#endif
+
+/* To be included in fb.h */
+#ifndef FB_ACCEL_SIS_GLAMOUR_2
+#define FB_ACCEL_SIS_GLAMOUR_2	  40	/* SiS 315, 65x, 740, 661, 741  */
+#endif
+#ifndef FB_ACCEL_SIS_XABRE
+#define FB_ACCEL_SIS_XABRE        41	/* SiS 330 ("Xabre"), 760 	*/
+#endif
+
+#define MAX_ROM_SCAN              0x10000
+
+/* ivideo->caps */
+#define HW_CURSOR_CAP             0x80
+#define TURBO_QUEUE_CAP           0x40
+#define AGP_CMD_QUEUE_CAP         0x20
+#define VM_CMD_QUEUE_CAP          0x10
+#define MMIO_CMD_QUEUE_CAP        0x08
+
+/* For 300 series */
+#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
+#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
+
+/* For 315/Xabre series */
+#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
+#define COMMAND_QUEUE_THRESHOLD   0x1F
+#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
+
+#define SIS_OH_ALLOC_SIZE         4000
+#define SENTINEL                  0x7fffffff
+
+#define SEQ_ADR                   0x14
+#define SEQ_DATA                  0x15
+#define DAC_ADR                   0x18
+#define DAC_DATA                  0x19
+#define CRTC_ADR                  0x24
+#define CRTC_DATA                 0x25
+#define DAC2_ADR                  (0x16-0x30)
+#define DAC2_DATA                 (0x17-0x30)
+#define VB_PART1_ADR              (0x04-0x30)
+#define VB_PART1_DATA             (0x05-0x30)
+#define VB_PART2_ADR              (0x10-0x30)
+#define VB_PART2_DATA             (0x11-0x30)
+#define VB_PART3_ADR              (0x12-0x30)
+#define VB_PART3_DATA             (0x13-0x30)
+#define VB_PART4_ADR              (0x14-0x30)
+#define VB_PART4_DATA             (0x15-0x30)
+
+#define SISSR			  ivideo->SiS_Pr.SiS_P3c4
+#define SISCR                     ivideo->SiS_Pr.SiS_P3d4
+#define SISDACA                   ivideo->SiS_Pr.SiS_P3c8
+#define SISDACD                   ivideo->SiS_Pr.SiS_P3c9
+#define SISPART1                  ivideo->SiS_Pr.SiS_Part1Port
+#define SISPART2                  ivideo->SiS_Pr.SiS_Part2Port
+#define SISPART3                  ivideo->SiS_Pr.SiS_Part3Port
+#define SISPART4                  ivideo->SiS_Pr.SiS_Part4Port
+#define SISPART5                  ivideo->SiS_Pr.SiS_Part5Port
+#define SISDAC2A                  SISPART5
+#define SISDAC2D                  (SISPART5 + 1)
+#define SISMISCR                  (ivideo->SiS_Pr.RelIO + 0x1c)
+#define SISMISCW                  ivideo->SiS_Pr.SiS_P3c2
+#define SISINPSTAT		  (ivideo->SiS_Pr.RelIO + 0x2a)
+#define SISPEL			  ivideo->SiS_Pr.SiS_P3c6
+
+#define IND_SIS_PASSWORD          0x05  /* SRs */
+#define IND_SIS_COLOR_MODE        0x06
+#define IND_SIS_RAMDAC_CONTROL    0x07
+#define IND_SIS_DRAM_SIZE         0x14
+#define IND_SIS_MODULE_ENABLE     0x1E
+#define IND_SIS_PCI_ADDRESS_SET   0x20
+#define IND_SIS_TURBOQUEUE_ADR    0x26
+#define IND_SIS_TURBOQUEUE_SET    0x27
+#define IND_SIS_POWER_ON_TRAP     0x38
+#define IND_SIS_POWER_ON_TRAP2    0x39
+#define IND_SIS_CMDQUEUE_SET      0x26
+#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
+
+#define IND_SIS_AGP_IO_PAD        0x48
+
+#define SIS_CRT2_WENABLE_300 	  0x24  /* Part1 */
+#define SIS_CRT2_WENABLE_315 	  0x2F
+
+#define SIS_PASSWORD              0x86  /* SR05 */
+#define SIS_INTERLACED_MODE       0x20  /* SR06 */
+#define SIS_8BPP_COLOR_MODE       0x0
+#define SIS_15BPP_COLOR_MODE      0x1 
+#define SIS_16BPP_COLOR_MODE      0x2 
+#define SIS_32BPP_COLOR_MODE      0x4 
+
+#define SIS_ENABLE_2D             0x40  /* SR1E */
+
+#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
+#define SIS_PCI_ADDR_ENABLE       0x80
+
+#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/330 series SR26 */
+#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
+#define SIS_MMIO_CMD_ENABLE       0x20
+#define SIS_CMD_QUEUE_SIZE_512k   0x00
+#define SIS_CMD_QUEUE_SIZE_1M     0x04
+#define SIS_CMD_QUEUE_SIZE_2M     0x08
+#define SIS_CMD_QUEUE_SIZE_4M     0x0C
+#define SIS_CMD_QUEUE_RESET       0x01
+#define SIS_CMD_AUTO_CORR	  0x02
+
+#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
+#define SIS_MODE_SELECT_CRT2      0x02
+#define SIS_VB_OUTPUT_COMPOSITE   0x04
+#define SIS_VB_OUTPUT_SVIDEO      0x08
+#define SIS_VB_OUTPUT_SCART       0x10
+#define SIS_VB_OUTPUT_LCD         0x20
+#define SIS_VB_OUTPUT_CRT2        0x40
+#define SIS_VB_OUTPUT_HIVISION    0x80
+
+#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
+#define SIS_DRIVER_MODE           0x40
+
+#define SIS_VB_COMPOSITE          0x01  /* CR32 */
+#define SIS_VB_SVIDEO             0x02
+#define SIS_VB_SCART              0x04
+#define SIS_VB_LCD                0x08
+#define SIS_VB_CRT2               0x10
+#define SIS_CRT1                  0x20
+#define SIS_VB_HIVISION           0x40
+#define SIS_VB_YPBPR              0x80
+#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
+                                   SIS_VB_SCART | SIS_VB_HIVISION | SIS_VB_YPBPR)
+
+#define SIS_EXTERNAL_CHIP_MASK    	   0x0E  /* CR37 (< SiS 660) */
+#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
+#define SIS_EXTERNAL_CHIP_LVDS             0x02  
+#define SIS_EXTERNAL_CHIP_TRUMPION         0x03  
+#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04  
+#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05  
+#define SIS310_EXTERNAL_CHIP_LVDS          0x02  
+#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03  
+
+#define SIS_AGP_2X                0x20  /* CR48 */
+
+#define HW_DEVICE_EXTENSION	  SIS_HW_INFO
+#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
+
+/* Useful macros */
+#define inSISREG(base)          inb(base)
+#define outSISREG(base,val)     outb(val,base)
+#define orSISREG(base,val)      do { \
+                                  u8 __Temp = inb(base); \
+                                  outSISREG(base, __Temp | (val)); \
+                                } while (0)
+#define andSISREG(base,val)     do { \
+                                  u8 __Temp = inb(base); \
+                                  outSISREG(base, __Temp & (val)); \
+                                } while (0)
+#define inSISIDXREG(base,idx,var)   do { \
+                                      outb(idx,base); var=inb((base)+1); \
+                                    } while (0)
+#define outSISIDXREG(base,idx,val)  do { \
+                                      outb(idx,base); outb((val),(base)+1); \
+                                    } while (0)
+#define orSISIDXREG(base,idx,val)   do { \
+                                      u8 __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)|(val); \
+                                      outSISIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define andSISIDXREG(base,idx,and)  do { \
+                                      u8 __Temp; \
+                                      outb(idx,base);   \
+                                      __Temp = inb((base)+1)&(and); \
+                                      outSISIDXREG(base,idx,__Temp); \
+                                    } while (0)
+#define setSISIDXREG(base,idx,and,or)   do { \
+                                          u8 __Temp; \
+                                          outb(idx,base);   \
+                                          __Temp = (inb((base)+1)&(and))|(or); \
+                                          outSISIDXREG(base,idx,__Temp); \
+                                        } while (0)
+
+/* MMIO access macros */
+#define MMIO_IN8(base, offset)  readb((base+offset))
+#define MMIO_IN16(base, offset) readw((base+offset))
+#define MMIO_IN32(base, offset) readl((base+offset))
+
+#define MMIO_OUT8(base, offset, val)  writeb(((u8)(val)), (base+offset))
+#define MMIO_OUT16(base, offset, val) writew(((u16)(val)), (base+offset))
+#define MMIO_OUT32(base, offset, val) writel(((u32)(val)), (base+offset))
+
+/* Queue control MMIO registers */
+#define Q_BASE_ADDR		0x85C0  /* Base address of software queue */
+#define Q_WRITE_PTR		0x85C4  /* Current write pointer */
+#define Q_READ_PTR		0x85C8  /* Current read pointer */
+#define Q_STATUS		0x85CC  /* queue status */
+
+#define MMIO_QUEUE_PHYBASE      Q_BASE_ADDR
+#define MMIO_QUEUE_WRITEPORT    Q_WRITE_PTR
+#define MMIO_QUEUE_READPORT     Q_READ_PTR
+
+#if !defined(__i386__) && !defined(__x86_64__)
+#ifndef ioremap_nocache
+#define ioremap_nocache(X, Y) ioremap(X, Y)
+#endif
+#endif
+					
+enum _SIS_CMDTYPE {
+	MMIO_CMD = 0,
+	AGP_CMD_QUEUE,
+	VM_CMD_QUEUE,
+};
+typedef unsigned int SIS_CMDTYPE;
+
+/* Our "par" */
+struct sis_video_info {
+	int		cardnumber;
+	struct fb_info  *memyselfandi;
+	
+	SIS_HW_INFO 	sishw_ext;	
+	SiS_Private  	SiS_Pr;	
+	
+	sisfb_info 	sisfbinfo;	/* For ioctl SISFB_GET_INFO */
+	
+	struct fb_var_screeninfo default_var;
+	
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	struct fb_fix_screeninfo sisfb_fix;
+	u32 		pseudo_palette[17];
+#endif	
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	struct display 		 sis_disp;
+	struct display_switch 	 sisfb_sw;	
+	struct { 
+		u16 red, green, blue, pad; 
+	} 		sis_palette[256];
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u32 cfb32[16];
+#endif
+	} 		sis_fbcon_cmap;
+#endif	
+
+        struct sisfb_monitor {
+		u16 hmin;
+		u16 hmax;
+		u16 vmin;
+		u16 vmax;
+		u32 dclockmax;
+		u8  feature;
+		BOOLEAN datavalid;
+	} 		sisfb_thismonitor;
+	
+	int           	chip_id;
+	char		myid[40];
+	
+	struct pci_dev  *nbridge;
+	
+	int		mni;	/* Mode number index */
+	
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+	int  		currcon;
+#endif	
+
+	unsigned long	video_size;
+	unsigned long 	video_base;
+	unsigned long	mmio_size;
+	unsigned long 	mmio_base;
+	unsigned long 	vga_base;
+	
+	unsigned long  	video_vbase;
+	unsigned long 	mmio_vbase;
+	char  *	      	bios_vbase;
+	char  *	      	bios_abase;
+	
+	int 		mtrr;
+	
+	u32		sisfb_mem;
+	
+	u32 		sisfb_parm_mem;
+	int 	   	sisfb_accel;
+	int 		sisfb_ypan;
+	int 		sisfb_max;
+	int 		sisfb_userom;
+	int 		sisfb_useoem;
+	int		sisfb_mode_idx;
+	int		sisfb_parm_rate;
+	int		sisfb_crt1off;
+	int		sisfb_forcecrt1;
+	int		sisfb_crt2type;
+	int		sisfb_crt2flags;
+	int 		sisfb_dstn;
+	int 		sisfb_fstn;
+	int		sisfb_tvplug;
+	int		sisfb_tvstd;
+	int		sisfb_filter;
+	int		sisfb_nocrt2rate;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+	int		sisfb_inverse;
+#endif	
+	
+	u32 		heapstart;        /* offset  */
+	unsigned long  	sisfb_heap_start; /* address */
+	unsigned long  	sisfb_heap_end;   /* address */
+	u32 	      	sisfb_heap_size;
+	int		havenoheap;
+#if 0	
+	SIS_HEAP       	sisfb_heap;
+#endif	
+	
+
+	int    		video_bpp;
+	int    		video_cmap_len;
+	int    		video_width;
+	int    		video_height;
+	int    		video_vwidth;		/* DEPRECATED - use var instead */
+	int    		video_vheight;		/* DEPRECATED - use var instead */
+	int    		org_x;			/* DEPRECATED - use var instead */
+	int    		org_y;			/* DEPRECATED - use var instead */
+	int    		video_linelength;
+	unsigned int 	refresh_rate;
+
+	unsigned int 	chip;
+	u8   		revision_id;
+
+        u16 		DstColor;		/* For 2d acceleration */
+	u32  		SiS310_AccelDepth;
+	u32  		CommandReg;
+	int		cmdqueuelength;
+
+	spinlock_t     	lockaccel;		/* Do not use outside of kernel! */
+
+        unsigned int   	pcibus;
+	unsigned int   	pcislot;
+	unsigned int   	pcifunc;
+
+	int 	       	accel;
+
+	u16 		subsysvendor;
+	u16 		subsysdevice;
+
+	u32  		vbflags;		/* Replacing deprecated stuff from above */
+	u32  		currentvbflags;
+	
+	int		lcdxres, lcdyres;
+	int		lcddefmodeidx, tvdefmodeidx, defmodeidx;
+
+	int    		current_bpp;
+	int    		current_width;
+	int    		current_height;
+	int    		current_htotal;
+	int    		current_vtotal;
+	__u32  		current_pixclock;
+	int    		current_refresh_rate;
+	
+	u8  		mode_no;
+	u8  		rate_idx;
+	int    		modechanged;
+	unsigned char 	modeprechange;
+	
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	u8 		sisfb_lastrates[128];
+#endif
+	
+	int  		newrom;
+	int  		registered;
+#ifdef SIS_CONFIG_COMPAT
+	int		ioctl32registered;
+	int		ioctl32vblankregistered;
+#endif	
+	
+	int 		sisvga_engine;
+	int 		hwcursor_size;
+	int 		CRT2_write_enable;
+	u8            	caps;
+	
+	u8 		detectedpdc;
+	u8 		detectedpdca;
+	u8 		detectedlcda;
+	
+	unsigned long 	hwcursor_vbase;
+	
+	int 		chronteltype;
+	int    		tvxpos, tvypos;
+	u8              p2_1f,p2_20,p2_2b,p2_42,p2_43,p2_01,p2_02;
+	int		tvx, tvy;
+	
+	u8 		sisfblocked;
+	
+	struct sis_video_info *next;
+};
+
+typedef struct _SIS_OH {
+	struct _SIS_OH *poh_next;
+	struct _SIS_OH *poh_prev;
+	u32            offset;
+	u32            size;
+} SIS_OH;
+
+typedef struct _SIS_OHALLOC {
+	struct _SIS_OHALLOC *poha_next;
+	SIS_OH aoh[1];
+} SIS_OHALLOC;
+
+typedef struct _SIS_HEAP {
+	SIS_OH      oh_free;
+	SIS_OH      oh_used;
+	SIS_OH      *poh_freelist;
+	SIS_OHALLOC *poha_chain;
+	u32         max_freesize;
+	struct sis_video_info *vinfo;
+} SIS_HEAP;
 
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/sis_accel.c linux-2.4.27-rc4/drivers/video/sis/sis_accel.c
--- linux-2.4.26/drivers/video/sis/sis_accel.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/sis_accel.c	2004-07-30 16:29:03.000000000 +0000
@@ -18,9 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
  *
- * Based on the XFree86 driver's sis300_accel.c which is
- *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
- * and sis310_accel.c which is
+ * Based on the XFree86/X.org driver which is
  *     Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria
  *
  * Author: Thomas Winischhofer <thomas@winischhofer.net>
@@ -33,36 +31,16 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
 #include <linux/selection.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/agp_backend.h>
-
 #include <linux/types.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include <linux/sisfb.h>
-#else
-#include <video/sisfb.h>
-#endif
-
 #include <asm/io.h>
 
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
@@ -71,16 +49,10 @@
 #include <video/fbcon-cfb32.h>
 #endif
 
-#include "osdef.h"
-#include "vgatypes.h"
-#include "vstruct.h"
-#include "sis_accel.h"
 #include "sis.h"
+#include "sis_accel.h"
 
-extern struct   video_info ivideo;
-extern int 	sisfb_accel;
-
-static const int sisALUConv[] =
+static const u8 sisALUConv[] =
 {
     0x00,       /* dest = 0;            0,      GXclear,        0 */
     0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
@@ -100,7 +72,7 @@ static const int sisALUConv[] =
     0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
 };
 /* same ROP but with Pattern as Source */
-static const int sisPatALUConv[] =
+static const u8 sisPatALUConv[] =
 {
     0x00,       /* dest = 0;            0,      GXclear,        0 */
     0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
@@ -121,26 +93,26 @@ static const int sisPatALUConv[] =
 };
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
-static const unsigned char myrops[] = {
+static const int myrops[] = {
    	3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
-   };
+};
 #endif
 
 /* 300 series ----------------------------------------------------- */
 #ifdef CONFIG_FB_SIS_300
 static void
-SiS300Sync(void)
+SiS300Sync(struct sis_video_info *ivideo)
 {
 	SiS300Idle
 }
 
 static void
-SiS300SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
+SiS300SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int xdir, int ydir, 
+                                 int rop, int trans_color)
 {
-	SiS300SetupDSTColorDepth(ivideo.DstColor);
-	SiS300SetupSRCPitch(ivideo.video_linelength)
-	SiS300SetupDSTRect(ivideo.video_linelength, -1)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
+	SiS300SetupSRCPitch(ivideo->video_linelength)
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
 
 	if(trans_color != -1) {
 		SiS300SetupROP(0x0A)
@@ -158,29 +130,28 @@ SiS300SetupForScreenToScreenCopy(int xdi
 }
 
 static void
-SiS300SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
+SiS300SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, 
+				   int src_y, int dst_x, int dst_y, int width, int height)
 {
-	long srcbase, dstbase;
+	u32 srcbase = 0, dstbase = 0;
 
-	srcbase = dstbase = 0;
-	if (src_y >= 2048) {
-		srcbase = ivideo.video_linelength * src_y;
+	if(src_y >= 2048) {
+		srcbase = ivideo->video_linelength * src_y;
 		src_y = 0;
 	}
-	if (dst_y >= 2048) {
-		dstbase = ivideo.video_linelength * dst_y;
+	if(dst_y >= 2048) {
+		dstbase = ivideo->video_linelength * dst_y;
 		dst_y = 0;
 	}
 
 	SiS300SetupSRCBase(srcbase);
 	SiS300SetupDSTBase(dstbase);
 
-	if(!(ivideo.CommandReg & X_INC))  {
+	if(!(ivideo->CommandReg & X_INC))  {
 		src_x += width-1;
 		dst_x += width-1;
 	}
-	if(!(ivideo.CommandReg & Y_INC))  {
+	if(!(ivideo->CommandReg & Y_INC))  {
 		src_y += height-1;
 		dst_y += height-1;
 	}
@@ -191,23 +162,22 @@ SiS300SubsequentScreenToScreenCopy(int s
 }
 
 static void
-SiS300SetupForSolidFill(int color, int rop, unsigned int planemask)
+SiS300SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
 	SiS300SetupPATFG(color)
-	SiS300SetupDSTRect(ivideo.video_linelength, -1)
-	SiS300SetupDSTColorDepth(ivideo.DstColor);
+	SiS300SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS300SetupDSTColorDepth(ivideo->DstColor);
 	SiS300SetupROP(sisPatALUConv[rop])
 	SiS300SetupCMDFlag(PATFG)
 }
 
 static void
-SiS300SubsequentSolidFillRect(int x, int y, int w, int h)
+SiS300SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
 {
-	long dstbase;
+	u32 dstbase = 0;
 
-	dstbase = 0;
 	if(y >= 2048) {
-		dstbase = ivideo.video_linelength * y;
+		dstbase = ivideo->video_linelength * y;
 		y = 0;
 	}
 	SiS300SetupDSTBase(dstbase)
@@ -222,19 +192,18 @@ SiS300SubsequentSolidFillRect(int x, int
 
 #ifdef CONFIG_FB_SIS_315
 static void
-SiS310Sync(void)
+SiS310Sync(struct sis_video_info *ivideo)
 {
 	SiS310Idle
 }
 
 static void
-SiS310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
+SiS310SetupForScreenToScreenCopy(struct sis_video_info *ivideo, int rop, int trans_color)
 {
-	SiS310SetupDSTColorDepth(ivideo.DstColor);
-	SiS310SetupSRCPitch(ivideo.video_linelength)
-	SiS310SetupDSTRect(ivideo.video_linelength, -1)
-	if (trans_color != -1) {
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
+	SiS310SetupSRCPitch(ivideo->video_linelength)
+	SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+	if(trans_color != -1) {
 		SiS310SetupROP(0x0A)
 		SiS310SetupSRCTrans(trans_color)
 		SiS310SetupCMDFlag(TRANSPARENT_BITBLT)
@@ -243,20 +212,17 @@ SiS310SetupForScreenToScreenCopy(int xdi
 		/* Set command - not needed, both 0 */
 		/* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */
 	}
-	SiS310SetupCMDFlag(ivideo.SiS310_AccelDepth)
+	SiS310SetupCMDFlag(ivideo->SiS310_AccelDepth)
 	/* The 315 series is smart enough to know the direction */
 }
 
 static void
-SiS310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
+SiS310SubsequentScreenToScreenCopy(struct sis_video_info *ivideo, int src_x, int src_y,
+			 int dst_x, int dst_y, int width, int height)
 {
-	long srcbase, dstbase;
-	int mymin, mymax;
-
-	srcbase = dstbase = 0;
-	mymin = min(src_y, dst_y);
-	mymax = max(src_y, dst_y);
+	u32 srcbase = 0, dstbase = 0;
+	int mymin = min(src_y, dst_y);
+	int mymax = max(src_y, dst_y);
 	
 	/* Although the chip knows the direction to use
 	 * if the source and destination areas overlap, 
@@ -270,18 +236,18 @@ SiS310SubsequentScreenToScreenCopy(int s
 	 */
 	if((mymax - mymin) < height) { 
 	   if((src_y >= 2048) || (dst_y >= 2048)) {	      
-	      srcbase = ivideo.video_linelength * mymin;
-	      dstbase = ivideo.video_linelength * mymin;
+	      srcbase = ivideo->video_linelength * mymin;
+	      dstbase = ivideo->video_linelength * mymin;
 	      src_y -= mymin;
 	      dst_y -= mymin;
 	   }
 	} else {
 	   if(src_y >= 2048) {
-	      srcbase = ivideo.video_linelength * src_y;
+	      srcbase = ivideo->video_linelength * src_y;
 	      src_y = 0;
 	   }
 	   if(dst_y >= 2048) {
-	      dstbase = ivideo.video_linelength * dst_y;
+	      dstbase = ivideo->video_linelength * dst_y;
 	      dst_y = 0;
 	   }
 	}
@@ -295,23 +261,22 @@ SiS310SubsequentScreenToScreenCopy(int s
 }
 
 static void
-SiS310SetupForSolidFill(int color, int rop, unsigned int planemask)
+SiS310SetupForSolidFill(struct sis_video_info *ivideo, u32 color, int rop)
 {
 	SiS310SetupPATFG(color)
-	SiS310SetupDSTRect(ivideo.video_linelength, -1)
-	SiS310SetupDSTColorDepth(ivideo.DstColor);
+	SiS310SetupDSTRect(ivideo->video_linelength, 0xffff)
+	SiS310SetupDSTColorDepth(ivideo->DstColor);
 	SiS310SetupROP(sisPatALUConv[rop])
-	SiS310SetupCMDFlag(PATFG | ivideo.SiS310_AccelDepth)
+	SiS310SetupCMDFlag(PATFG | ivideo->SiS310_AccelDepth)
 }
 
 static void
-SiS310SubsequentSolidFillRect(int x, int y, int w, int h)
+SiS310SubsequentSolidFillRect(struct sis_video_info *ivideo, int x, int y, int w, int h)
 {
-	long dstbase;
+	u32 dstbase = 0;
 
-	dstbase = 0;
 	if(y >= 2048) {
-		dstbase = ivideo.video_linelength * y;
+		dstbase = ivideo->video_linelength * y;
 		y = 0;
 	}
 	SiS310SetupDSTBase(dstbase)
@@ -326,23 +291,23 @@ SiS310SubsequentSolidFillRect(int x, int
 
 /* The exported routines */
 
-int sisfb_initaccel(void)
+int sisfb_initaccel(struct sis_video_info *ivideo)
 {
 #ifdef SISFB_USE_SPINLOCKS
-    spin_lock_init(&ivideo.lockaccel);
+    spin_lock_init(&ivideo->lockaccel);
 #endif
     return(0);
 }
 
-void sisfb_syncaccel(void)
+void sisfb_syncaccel(struct sis_video_info *ivideo)
 {
-    if(ivideo.sisvga_engine == SIS_300_VGA) {
+    if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-    	SiS300Sync();
+    	SiS300Sync(ivideo);
 #endif
     } else {
 #ifdef CONFIG_FB_SIS_315
-    	SiS310Sync();
+    	SiS310Sync(ivideo);
 #endif
     }
 }
@@ -351,18 +316,19 @@ void sisfb_syncaccel(void)
 
 int fbcon_sis_sync(struct fb_info *info)
 {
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
    CRITFLAGS
 
-   if(!ivideo.accel)
+   if(!ivideo->accel)
    	return 0;
    
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
    CRITEND
@@ -371,42 +337,53 @@ int fbcon_sis_sync(struct fb_info *info)
 
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
-   int col=0;
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+   u32 col = 0; 
+   u32 vxres = info->var.xres_virtual;
+   u32 vyres = info->var.yres_virtual;
+   int width, height;
    CRITFLAGS
+   
+   if(info->state != FBINFO_STATE_RUNNING) {
+	return;
+   }
 
-   TWDEBUG("Inside sis_fillrect");
-   if(!rect->width || !rect->height)
-   	return;
-
-   if(!ivideo.accel) {
+   if(!ivideo->accel) {
 	cfb_fillrect(info, rect);
 	return;
    }
    
+   if(!rect->width || !rect->height || rect->dx >= vxres || rect->dy >= vyres) {
+	return;
+   }
+	
+   /* Clipping */
+   width = ((rect->dx + rect->width) > vxres) ? (vxres - rect->dx) : rect->width;
+   height = ((rect->dy + rect->height) > vyres) ? (vyres - rect->dy) : rect->height;
+   
    switch(info->var.bits_per_pixel) {
 	case 8:  col = rect->color;
 		 break;
-	case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
-		 break;
+	case 16: 
 	case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
 		 break;
    }
 
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
       CRITBEGIN
-      SiS300SetupForSolidFill(col, myrops[rect->rop], 0);
-      SiS300SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+      SiS300SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+      SiS300SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
       CRITEND
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
       CRITBEGIN
-      SiS310SetupForSolidFill(col, myrops[rect->rop], 0);
-      SiS310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
+      SiS310SetupForSolidFill(ivideo, col, myrops[rect->rop]);
+      SiS310SubsequentSolidFillRect(ivideo, rect->dx, rect->dy, width, height);
       CRITEND
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
 
@@ -414,38 +391,58 @@ void fbcon_sis_fillrect(struct fb_info *
 
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area)
 {
-   int xdir, ydir;
+   struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+   u32 vxres = info->var.xres_virtual;
+   u32 vyres = info->var.yres_virtual;
+   int width = area->width;
+   int height = area->height;
    CRITFLAGS
+   
+   if(info->state != FBINFO_STATE_RUNNING) {
+	return;
+   }
 
-   TWDEBUG("Inside sis_copyarea");
-   if(!ivideo.accel) {
+   if(!ivideo->accel) {
    	cfb_copyarea(info, area);
 	return;
    }
-
-   if(!area->width || !area->height)
+   
+   if(!width || !height ||
+      area->sx >= vxres || area->sy >= vyres ||
+      area->dx >= vxres || area->dy >= vyres) {
    	return;
+   }
+   
+   /* Clipping */
+   if((area->sx + width) > vxres) width = vxres - area->sx;
+   if((area->dx + width) > vxres) width = vxres - area->dx;
+   if((area->sy + height) > vyres) height = vyres - area->sy;
+   if((area->dy + height) > vyres) height = vyres - area->dy;
 
-   if(area->sx < area->dx) xdir = 0;
-   else                    xdir = 1;
-   if(area->sy < area->dy) ydir = 0;
-   else                    ydir = 1;
-
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
+      int xdir, ydir;
+      
+      if(area->sx < area->dx) xdir = 0;
+      else                    xdir = 1;
+      if(area->sy < area->dy) ydir = 0;
+      else                    ydir = 1;
+      
       CRITBEGIN
-      SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      SiS300SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+      SiS300SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, 
+      					 width, height);
       CRITEND
-      SiS300Sync();
+      SiS300Sync(ivideo);
 #endif
    } else {
 #ifdef CONFIG_FB_SIS_315
       CRITBEGIN
-      SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      SiS310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
+      SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+      SiS310SubsequentScreenToScreenCopy(ivideo, area->sx, area->sy, area->dx, area->dy, 
+      					 width, height);
       CRITEND
-      SiS310Sync();
+      SiS310Sync(ivideo);
 #endif
    }
 }
@@ -457,11 +454,12 @@ void fbcon_sis_copyarea(struct fb_info *
 void fbcon_sis_bmove(struct display *p, int srcy, int srcx,
 			    int dsty, int dstx, int height, int width)
 {
-        int xdir, ydir;
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
+        
 	CRITFLAGS
 
-	if(!ivideo.accel) {
-	    switch(ivideo.video_bpp) {
+	if(!ivideo->accel) {
+	    switch(ivideo->video_bpp) {
 	    case 8:
 #ifdef FBCON_HAS_CFB8
 	       fbcon_cfb8_bmove(p, srcy, srcx, dsty, dstx, height, width);
@@ -488,26 +486,28 @@ void fbcon_sis_bmove(struct display *p, 
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(srcx < dstx) xdir = 0;
-	else            xdir = 1;
-	if(srcy < dsty) ydir = 0;
-	else            ydir = 1;
-
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
+	   int xdir, ydir;
+	   
+	   if(srcx < dstx) xdir = 0;
+	   else            xdir = 1;
+	   if(srcy < dsty) ydir = 0;
+	   else            ydir = 1;
+	   
 	   CRITBEGIN
-	   SiS300SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-	   SiS300SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+	   SiS300SetupForScreenToScreenCopy(ivideo, xdir, ydir, 3, -1);
+	   SiS300SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-	   SiS310SubsequentScreenToScreenCopy(srcx, srcy, dstx, dsty, width, height);
+	   SiS310SetupForScreenToScreenCopy(ivideo, 3, -1);
+	   SiS310SubsequentScreenToScreenCopy(ivideo, srcx, srcy, dstx, dsty, width, height);
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
@@ -515,28 +515,29 @@ void fbcon_sis_bmove(struct display *p, 
 static void fbcon_sis_clear(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width, int color)
 {
+        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	CRITFLAGS
-
+	
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 	width *= fontwidth(p);
 	height *= fontheight(p);
 
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(color, 3, 0);
-	   SiS300SubsequentSolidFillRect(srcx, srcy, width, height);
+	   SiS300SetupForSolidFill(ivideo, color, 3);
+	   SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(color, 3, 0);
-	   SiS310SubsequentSolidFillRect(srcx, srcy, width, height);
+	   SiS310SetupForSolidFill(ivideo, color, 3);
+	   SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, width, height);
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
@@ -544,9 +545,10 @@ static void fbcon_sis_clear(struct vc_da
 void fbcon_sis_clear8(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
 
-	if(!ivideo.accel) {
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB8
 	    fbcon_cfb8_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -560,8 +562,10 @@ void fbcon_sis_clear8(struct vc_data *co
 void fbcon_sis_clear16(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+        struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
-	if(!ivideo.accel) {
+	
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB16
 	    fbcon_cfb16_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -575,9 +579,10 @@ void fbcon_sis_clear16(struct vc_data *c
 void fbcon_sis_clear32(struct vc_data *conp, struct display *p,
 			int srcy, int srcx, int height, int width)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	u32 bgx;
 
-	if(!ivideo.accel) {
+	if(!ivideo->accel) {
 #ifdef FBCON_HAS_CFB32
 	    fbcon_cfb32_clear(conp, p, srcy, srcx, height, width);
 #endif
@@ -590,10 +595,11 @@ void fbcon_sis_clear32(struct vc_data *c
 
 void fbcon_sis_revc(struct display *p, int srcx, int srcy)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)p->fb_info->par;
 	CRITFLAGS
 
-	if(!ivideo.accel) {
-	    switch(ivideo.video_bpp) {
+	if(!ivideo->accel) {
+	    switch(ivideo->video_bpp) {
 	    case 16:
 #ifdef FBCON_HAS_CFB16
 	       fbcon_cfb16_revc(p, srcx, srcy);
@@ -611,59 +617,59 @@ void fbcon_sis_revc(struct display *p, i
 	srcx *= fontwidth(p);
 	srcy *= fontheight(p);
 
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
 	   CRITBEGIN
-	   SiS300SetupForSolidFill(0, 0x0a, 0);
-	   SiS300SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+	   SiS300SetupForSolidFill(ivideo, 0, 0x0a);
+	   SiS300SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
 	   CRITEND
-	   SiS300Sync();
+	   SiS300Sync(ivideo);
 #endif
 	} else {
 #ifdef CONFIG_FB_SIS_315
 	   CRITBEGIN
-	   SiS310SetupForSolidFill(0, 0x0a, 0);
-	   SiS310SubsequentSolidFillRect(srcx, srcy, fontwidth(p), fontheight(p));
+	   SiS310SetupForSolidFill(ivideo, 0, 0x0a);
+	   SiS310SubsequentSolidFillRect(ivideo, srcx, srcy, fontwidth(p), fontheight(p));
 	   CRITEND
-	   SiS310Sync();
+	   SiS310Sync(ivideo);
 #endif
 	}
 }
 
 #ifdef FBCON_HAS_CFB8
 struct display_switch fbcon_sis8 = {
-	.setup			= fbcon_cfb8_setup,
-	.bmove			= fbcon_sis_bmove,
-	.clear			= fbcon_sis_clear8,
-	.putc			= fbcon_cfb8_putc,
-	.putcs			= fbcon_cfb8_putcs,
-	.revc			= fbcon_cfb8_revc,
-	.clear_margins		= fbcon_cfb8_clear_margins,
-	.fontwidthmask		= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+	.setup		= fbcon_cfb8_setup,
+	.bmove		= fbcon_sis_bmove,
+	.clear		= fbcon_sis_clear8,
+	.putc		= fbcon_cfb8_putc,
+	.putcs		= fbcon_cfb8_putcs,
+	.revc		= fbcon_cfb8_revc,
+	.clear_margins	= fbcon_cfb8_clear_margins,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB16
 struct display_switch fbcon_sis16 = {
-	.setup			= fbcon_cfb16_setup,
-	.bmove			= fbcon_sis_bmove,
-	.clear			= fbcon_sis_clear16,
-	.putc			= fbcon_cfb16_putc,
-	.putcs			= fbcon_cfb16_putcs,
-	.revc			= fbcon_sis_revc,
-	.clear_margins		= fbcon_cfb16_clear_margins,
-	.fontwidthmask		= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+	.setup		= fbcon_cfb16_setup,
+	.bmove		= fbcon_sis_bmove,
+	.clear		= fbcon_sis_clear16,
+	.putc		= fbcon_cfb16_putc,
+	.putcs		= fbcon_cfb16_putcs,
+	.revc		= fbcon_sis_revc,
+	.clear_margins	= fbcon_cfb16_clear_margins,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB32
 struct display_switch fbcon_sis32 = {
-	.setup			= fbcon_cfb32_setup,
-	.bmove			= fbcon_sis_bmove,
-	.clear			= fbcon_sis_clear32,
-	.putc			= fbcon_cfb32_putc,
-	.putcs			= fbcon_cfb32_putcs,
-	.revc			= fbcon_sis_revc,
-	.clear_margins		= fbcon_cfb32_clear_margins,
-	.fontwidthmask		= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+	.setup		= fbcon_cfb32_setup,
+	.bmove		= fbcon_sis_bmove,
+	.clear		= fbcon_sis_clear32,
+	.putc		= fbcon_cfb32_putc,
+	.putcs		= fbcon_cfb32_putcs,
+	.revc		= fbcon_sis_revc,
+	.clear_margins	= fbcon_cfb32_clear_margins,
+	.fontwidthmask	= FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/sis_accel.h linux-2.4.27-rc4/drivers/video/sis/sis_accel.h
--- linux-2.4.26/drivers/video/sis/sis_accel.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/sis_accel.h	2004-07-30 16:24:35.000000000 +0000
@@ -36,8 +36,8 @@
 
 #ifdef SISFB_USE_SPINLOCKS
 #include <linux/spinlock.h>
-#define CRITBEGIN  spin_lock_irqsave(&ivideo.lockaccel), critflags);
-#define CRITEND	   spin_unlock_irqrestore(&ivideo.lockaccel), critflags);
+#define CRITBEGIN  spin_lock_irqsave(&ivideo->lockaccel, critflags);
+#define CRITEND	   spin_unlock_irqrestore(&ivideo->lockaccel, critflags);
 #define CRITFLAGS  unsigned long critflags;
 #else
 #define CRITBEGIN
@@ -65,7 +65,6 @@
 #define A3D_FUNCTION		0x00000008  /* 3D command ? */
 #define	CLEAR_Z_BUFFER		0x00000009  /* ? */
 #define GRADIENT_FILL		0x0000000A  /* Gradient fill */
-#define STRETCH_BITBLT		0x0000000B  /* Stretched Blit */
 
 /* source select */
 #define SRCVIDEO                0x00000000  /* source is video RAM */
@@ -98,11 +97,6 @@
 #define DSTAGP                  0x02000000
 #define DSTVIDEO                0x02000000
 
-/* Line */
-#define LINE_STYLE              0x00800000
-#define NO_RESET_COUNTER        0x00400000
-#define NO_LAST_PIXEL           0x00200000
-
 /* Subfunctions for Color/Enhanced Color Expansion (315 only) */
 #define COLOR_TO_MONO		0x00100000
 #define AA_TEXT			0x00200000
@@ -134,221 +128,142 @@
 
 #define PATTERN_REG		0x8300  /* 384 bytes pattern buffer */
 
-/* Line registers */
-#define LINE_X0			SRC_Y
-#define LINE_X1			DST_Y
-#define LINE_Y0			SRC_X
-#define LINE_Y1			DST_X
-#define LINE_COUNT		RECT_WIDTH
-#define LINE_STYLE_PERIOD	RECT_HEIGHT
-#define LINE_STYLE_0		MONO_MASK
-#define LINE_STYLE_1		0x8230
-#define LINE_XN			PATTERN_REG
-#define LINE_YN			PATTERN_REG+2
-
 /* Transparent bitblit registers */
 #define TRANS_DST_KEY_HIGH	PAT_FGCOLOR
 #define TRANS_DST_KEY_LOW	PAT_BGCOLOR
 #define TRANS_SRC_KEY_HIGH	SRC_FGCOLOR
 #define TRANS_SRC_KEY_LOW	SRC_BGCOLOR
 
-/* Queue */
-#define Q_BASE_ADDR		0x85C0  /* Base address of software queue (?) */
-#define Q_WRITE_PTR		0x85C4  /* Current write pointer (?) */
-#define Q_READ_PTR		0x85C8  /* Current read pointer (?) */
-#define Q_STATUS		0x85CC  /* queue status */
-
-#define MMIO_IN8(base, offset)  readb((base+offset))
-#define MMIO_IN16(base, offset) readw((base+offset))
-#define MMIO_IN32(base, offset) readl((base+offset))
-
-#define MMIO_OUT8(base, offset, val)  writeb((val), (base+offset))
-#define MMIO_OUT16(base, offset, val) writew((val), (base+offset))
-#define MMIO_OUT32(base, offset, val) writel((val), (base+offset))
-
-#if 0
-#define MMIO_IN8(base, offset) \
-	*(volatile u8 *)(((u8*)(base)) + (offset))
-#define MMIO_IN16(base, offset) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_IN32(base, offset) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_OUT8(base, offset, val) \
-	*(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT16(base, offset, val) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT32(base, offset, val) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
-#endif
+/* Store queue length in par */
+#define CmdQueLen ivideo->cmdqueuelength
 
 /* ------------- SiS 300 series -------------- */
 
-/* Macros to do useful things with the SIS BitBLT engine */
-
-/* BR(16) (0x8420):
+/* BR(16) (0x8240):
 
    bit 31 2D engine: 1 is idle,
    bit 30 3D engine: 1 is idle,
    bit 29 Command queue: 1 is empty
-
    bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
-
    bits 15:0:  Current command queue length
 
 */
 
-/* TW: BR(16)+2 = 0x8242 */
-
-int     CmdQueLen;
-
 #define SiS300Idle \
   { \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  CmdQueLen=MMIO_IN16(ivideo.mmio_vbase, 0x8240); \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	while((MMIO_IN16(ivideo->mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
+  	CmdQueLen = MMIO_IN16(ivideo->mmio_vbase, 0x8240); \
   }
-/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
+/* (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
 
 #define SiS300SetupSRCBase(base) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(0), base);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(0), base);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCPitch(pitch) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(1), pitch);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1), pitch);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCXY(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(2), (x)<<16 | (y) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(2), (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTBase(base) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(4), base);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(4), base);\
+	CmdQueLen--;
 
 #define SiS300SetupDSTXY(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(3), (x)<<16 | (y) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(3), (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTRect(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(5), (y)<<16 | (x) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(5), (y)<<16 | (x) );\
+	CmdQueLen--;
 
 #define SiS300SetupDSTColorDepth(bpp) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(1)+2, bpp);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, BR(1)+2, bpp);\
+	CmdQueLen--;
 
 #define SiS300SetupRect(w,h) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(6), (h)<<16 | (w) );\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(6), (h)<<16 | (w) );\
+	CmdQueLen--;
 
 #define SiS300SetupPATFG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(7), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(7), color);\
+	CmdQueLen--;
 
 #define SiS300SetupPATBG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(8), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(8), color);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCFG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(9), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(9), color);\
+	CmdQueLen--;
 
 #define SiS300SetupSRCBG(color) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(10), color);\
-                CmdQueLen --;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(10), color);\
+	CmdQueLen--;
 
 /* 0x8224 src colorkey high */
 /* 0x8228 src colorkey low */
 /* 0x821c dest colorkey high */
 /* 0x8220 dest colorkey low */
 #define SiS300SetupSRCTrans(color) \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, 0x8224, color);\
-		MMIO_OUT32(ivideo.mmio_vbase, 0x8228, color);\
-		CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8224, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8228, color);\
+	CmdQueLen -= 2;
 
 #define SiS300SetupDSTTrans(color) \
-		if (CmdQueLen <= 1)  SiS300Idle;\
-		MMIO_OUT32(ivideo.mmio_vbase, 0x821C, color); \
-		MMIO_OUT32(ivideo.mmio_vbase, 0x8220, color); \
-                CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, 0x821C, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, 0x8220, color); \
+	CmdQueLen -= 2;
 
 #define SiS300SetupMONOPAT(p0,p1) \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(11), p0);\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(12), p1);\
-                CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(11), p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(12), p1);\
+	CmdQueLen -= 2;
 
 #define SiS300SetupClipLT(left,top) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
-                CmdQueLen--;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
 
 #define SiS300SetupClipRB(right,bottom) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
-                CmdQueLen--;
+	if(CmdQueLen <= 0) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
 
 /* General */
 #define SiS300SetupROP(rop) \
-                ivideo.CommandReg = (rop) << 8;
+	ivideo->CommandReg = (rop) << 8;
 
 #define SiS300SetupCMDFlag(flags) \
-                ivideo.CommandReg |= (flags);
+	ivideo->CommandReg |= (flags);
 
 #define SiS300DoCMD \
-                if (CmdQueLen <= 1)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(15), ivideo.CommandReg); \
-                MMIO_OUT32(ivideo.mmio_vbase, BR(16), 0);\
-                CmdQueLen -= 2;
-
-/* Line */
-#define SiS300SetupX0Y0(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(2), (y)<<16 | (x) );\
-                CmdQueLen--;
-
-#define SiS300SetupX1Y1(x,y) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(3), (y)<<16 | (x) );\
-                CmdQueLen--;
-
-#define SiS300SetupLineCount(c) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(6), c);\
-                CmdQueLen--;
-
-#define SiS300SetupStylePeriod(p) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT16(ivideo.mmio_vbase, BR(6)+2, p);\
-                CmdQueLen--;
-
-#define SiS300SetupStyleLow(ls) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(11), ls);\
-                CmdQueLen--;
-
-#define SiS300SetupStyleHigh(ls) \
-                if (CmdQueLen <= 0)  SiS300Idle;\
-                MMIO_OUT32(ivideo.mmio_vbase, BR(12), ls);\
-                CmdQueLen--;
-
-
+	if(CmdQueLen <= 1) SiS300Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, BR(15), ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, BR(16), 0);\
+	CmdQueLen -= 2;
 
-/* -------------- SiS 315 series --------------- */
+/* -------------- SiS 315/330 series --------------- */
 
 /* Q_STATUS:
    bit 31 = 1: All engines idle and all queues empty
@@ -362,179 +277,131 @@ int     CmdQueLen;
    bits 23:16: 2D counter 3
    bits 15:8:  2D counter 2
    bits 7:0:   2D counter 1
-
-   Where is the command queue length (current amount of commands the queue
-   can accept) on the 315 series?
 */
 
-/* TW: FIXME: CmdQueLen is... where....? */
-/* We assume a length of 4 bytes per command; since 512K of
- * of RAM are allocated, the number of commands is easily
- * calculated (assuming that there is no 3D support yet)
- * We calculate it very cautiously (128K only) and let the
- * rest to the (never?)-to-come (?) 3D engine. (The 3D engine
- * can use a similar technique, using the remaining 384K,
- * hence a queue overflow is avoided)
- * UPDATE: This technique causes a terrible system latency
- * on integrated chipsets. Disable the queue handling for
- * now.
- */
 #define SiS310Idle \
   { \
-  while( (MMIO_IN16(ivideo.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  while( (MMIO_IN16(ivideo.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  CmdQueLen = 0; \
-  /*CmdQueLen = ((128 * 1024) / 4) - 64; */ \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	while( (MMIO_IN16(ivideo->mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
+  	CmdQueLen = 0; \
   }
 
 #define SiS310SetupSRCBase(base) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_ADDR, base);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_ADDR, base);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCPitch(pitch) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, SRC_PITCH, pitch);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, SRC_PITCH, pitch);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCXY(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTBase(base) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_ADDR, base);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_ADDR, base);\
+	CmdQueLen--;
 
 #define SiS310SetupDSTXY(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_Y, (x)<<16 | (y) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_Y, (x)<<16 | (y) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTRect(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
+	CmdQueLen--;
 
 #define SiS310SetupDSTColorDepth(bpp) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, AGP_BASE, bpp);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT16(ivideo->mmio_vbase, AGP_BASE, bpp);\
+	CmdQueLen--;
 
 #define SiS310SetupRect(w,h) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
+	CmdQueLen--;
 
 #define SiS310SetupPATFG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, PAT_FGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_FGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupPATBG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, PAT_BGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, PAT_BGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCFG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_FGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_FGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCBG(color) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, SRC_BGCOLOR, color);\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, SRC_BGCOLOR, color);\
+	CmdQueLen--;
 
 #define SiS310SetupSRCTrans(color) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_SRC_KEY_LOW, color);\
+	CmdQueLen -= 2;
 
 #define SiS310SetupDSTTrans(color) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
-      MMIO_OUT32(ivideo.mmio_vbase, TRANS_DST_KEY_LOW, color); \
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_HIGH, color); \
+	MMIO_OUT32(ivideo->mmio_vbase, TRANS_DST_KEY_LOW, color); \
+	CmdQueLen -= 2;
 
 #define SiS310SetupMONOPAT(p0,p1) \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, MONO_MASK, p0);\
-      MMIO_OUT32(ivideo.mmio_vbase, MONO_MASK+4, p1);\
-      CmdQueLen -= 2;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK, p0);\
+	MMIO_OUT32(ivideo->mmio_vbase, MONO_MASK+4, p1);\
+	CmdQueLen -= 2;
 
 #define SiS310SetupClipLT(left,top) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
+	CmdQueLen--;
 
 #define SiS310SetupClipRB(right,bottom) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
-      CmdQueLen--;
+	if(CmdQueLen <= 0) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
+	CmdQueLen--;
 
 #define SiS310SetupROP(rop) \
-      ivideo.CommandReg = (rop) << 8;
+	ivideo->CommandReg = (rop) << 8;
 
 #define SiS310SetupCMDFlag(flags) \
-      ivideo.CommandReg |= (flags);
+	ivideo->CommandReg |= (flags);
 
 #define SiS310DoCMD \
-      if (CmdQueLen <= 1)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, COMMAND_READY, ivideo.CommandReg); \
-      MMIO_OUT32(ivideo.mmio_vbase, FIRE_TRIGGER, 0); \
-      CmdQueLen -= 2;
-
-#define SiS310SetupX0Y0(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
-      CmdQueLen--;
-
-#define SiS310SetupX1Y1(x,y) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
-      CmdQueLen--;
-
-#define SiS310SetupLineCount(c) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, LINE_COUNT, c);\
-      CmdQueLen--;
-
-#define SiS310SetupStylePeriod(p) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT16(ivideo.mmio_vbase, LINE_STYLE_PERIOD, p);\
-      CmdQueLen--;
-
-#define SiS310SetupStyleLow(ls) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_STYLE_0, ls);\
-      CmdQueLen--;
-
-#define SiS310SetupStyleHigh(ls) \
-      if (CmdQueLen <= 0)  SiS310Idle;\
-      MMIO_OUT32(ivideo.mmio_vbase, LINE_STYLE_1, ls);\
-      CmdQueLen--;
-
-int  sisfb_initaccel(void);
-void sisfb_syncaccel(void);
-
-extern struct video_info ivideo;
+	if(CmdQueLen <= 1) SiS310Idle;\
+	MMIO_OUT32(ivideo->mmio_vbase, COMMAND_READY, ivideo->CommandReg); \
+	MMIO_OUT32(ivideo->mmio_vbase, FIRE_TRIGGER, 0); \
+	CmdQueLen -= 2;
+
+      
+int  sisfb_initaccel(struct sis_video_info *ivideo);
+void sisfb_syncaccel(struct sis_video_info *ivideo);
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)
 void fbcon_sis_bmove(struct display *p, int srcy, int srcx, int dsty,
-                     int dstx, int height, int width);
+			int dstx, int height, int width);
 void fbcon_sis_revc(struct display *p, int srcy, int srcx);
 void fbcon_sis_clear8(struct vc_data *conp, struct display *p, int srcy,
-                      int srcx, int height, int width);
+			int srcx, int height, int width);
 void fbcon_sis_clear16(struct vc_data *conp, struct display *p, int srcy,
-                       int srcx, int height, int width);
+			int srcx, int height, int width);
 void fbcon_sis_clear32(struct vc_data *conp, struct display *p, int srcy,
-                       int srcx, int height, int width);
+			int srcx, int height, int width);
 #endif
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
-extern int sisfb_accel;
 void fbcon_sis_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
 void fbcon_sis_copyarea(struct fb_info *info, const struct fb_copyarea *area);
 #endif
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/sis_main.c linux-2.4.27-rc4/drivers/video/sis/sis_main.c
--- linux-2.4.26/drivers/video/sis/sis_main.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/sis_main.c	2004-07-30 16:29:47.000000000 +0000
@@ -1,6 +1,7 @@
 /*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/M741/330/760
- * frame buffer driver for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/305/540/630(S)/730(S)
+ * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * frame buffer driver for Linux kernels >= 2.4.14 and >=2.6.3
  *
  * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
  *
@@ -20,8 +21,8 @@
  *
  * Author:   	Thomas Winischhofer <thomas@winischhofer.net>
  *
- * Author of code base:
- *		SiS (www.sis.com.tw)
+ * Author of (practically wiped) code base:
+ *		SiS (www.sis.com)
  *	 	Copyright (C) 1999 Silicon Integrated Systems, Inc.
  *
  * See http://www.winischhofer.net/ for more information and updates
@@ -34,7 +35,11 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+#include <linux/moduleparam.h>
+#endif
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -51,22 +56,8 @@
 #include <linux/vt_kern.h>
 #include <linux/capability.h>
 #include <linux/fs.h>
-#include <linux/agp_backend.h>
 #include <linux/types.h>
 #include <asm/uaccess.h>
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#include <linux/spinlock.h>
-#endif
-
-#include "osdef.h"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-#include <video/sisfb.h>
-#else
-#include <linux/sisfb.h>
-#endif
-
 #include <asm/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
@@ -80,32 +71,16 @@
 #include <video/fbcon-cfb32.h>
 #endif
 
-#include "vgatypes.h"
-#include "sis_main.h"
 #include "sis.h"
+#include "sis_main.h"
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3)
 #error "This version of sisfb requires at least 2.6.3"
-#else
-#if 0
-#define NEWFBDEV		/* Define this as soon as sysfs support has returned */
-#endif
-#endif
 #endif
-
-/* -------------------- Macro definitions ---------------------------- */
-
-#undef SISFBDEBUG 	/* no debugging */
-
-#ifdef SISFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#ifdef SISFBACCEL
 #ifdef FBCON_HAS_CFB8
 extern struct display_switch fbcon_sis8;
 #endif
@@ -116,24 +91,286 @@ extern struct display_switch fbcon_sis16
 extern struct display_switch fbcon_sis32;
 #endif
 #endif
+
+/* ------------------ Internal helper routines ----------------- */
+
+static void __init
+sisfb_setdefaultparms(void)
+{
+	sisfb_off 		= 0;
+	sisfb_parm_mem 		= 0;
+	sisfb_accel 		= -1;
+	sisfb_ypan      	= -1;
+	sisfb_max 		= -1;
+	sisfb_userom    	= -1;
+        sisfb_useoem    	= -1;
+#ifdef MODULE
+	/* Module: "None" for 2.4, default mode for 2.5+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	sisfb_mode_idx 		= -1;
+#else	
+	sisfb_mode_idx  	= MODE_INDEX_NONE;
+#endif	
+#else	
+	/* Static: Default mode */
+	sisfb_mode_idx  	= -1;
+#endif	
+	sisfb_parm_rate 	= -1;
+	sisfb_crt1off 		= 0;
+	sisfb_forcecrt1 	= -1;
+	sisfb_crt2type  	= -1;
+	sisfb_crt2flags 	= 0;
+	sisfb_pdc 		= 0xff;
+	sisfb_pdca 		= 0xff;
+	sisfb_scalelcd  	= -1;
+	sisfb_specialtiming 	= CUT_NONE;
+	sisfb_lvdshl 		= -1;
+	sisfb_dstn     		= 0;
+	sisfb_fstn 		= 0;
+	sisfb_tvplug    	= -1;
+	sisfb_tvstd     	= -1;
+	sisfb_tvxposoffset 	= 0;
+	sisfb_tvyposoffset 	= 0;
+	sisfb_filter 		= -1;
+	sisfb_nocrt2rate 	= 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
+	sisfb_inverse   	= 0;
+	sisfb_fontname[0] 	= 0;
+#endif	
+#if !defined(__i386__) && !defined(__x86_64__)
+	sisfb_resetcard 	= 0;
+	sisfb_videoram  	= 0;
+#endif	
+}
+
+static void __init
+sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
+{
+	int i = 0, j = 0;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(vesamode == 0) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+		sisfb_mode_idx = MODE_INDEX_NONE;
+#else
+		if(!quiet) {
+		   printk(KERN_ERR "sisfb: Invalid mode. Using default.\n");
+		}
+		sisfb_mode_idx = DEFAULT_MODE;
+#endif
+		return;
+	}
+
+	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
+
+	while(sisbios_mode[i++].mode_no[0] != 0) {
+		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
+		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
+		    if(sisfb_fstn) {
+		       if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+		          sisbios_mode[i-1].mode_no[1] == 0x56 ||
+		          sisbios_mode[i-1].mode_no[1] == 0x53) continue;
+	            } else {
+		       if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+		          sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
+		    }
+		    sisfb_mode_idx = i - 1;
+		    j = 1;
+		    break;
+		}
+	}
+	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
+}
+
+static void 
+sisfb_search_mode(char *name, BOOLEAN quiet)
+{
+	int i = 0;
+	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
+	char strbuf[16], strbuf1[20];
+	char *nameptr = name;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) {
+	   if(!quiet) {
+	      printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
+	   }
+	   sisfb_mode_idx = DEFAULT_MODE;
+	   return;
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+        if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
+	   if(!quiet) {
+	      printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
+	   }
+	   sisfb_mode_idx = DEFAULT_MODE;
+	   return;
+	}
 #endif
+	if(strlen(name) <= 19) {
+	   strcpy(strbuf1, name);
+	   for(i=0; i<strlen(strbuf1); i++) {
+	      if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
+	   }
+
+	   /* This does some fuzzy mode naming detection */
+	   if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
+	      if((rate <= 32) || (depth > 32)) {
+	         j = rate; rate = depth; depth = j;
+	      }
+	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+	      nameptr = strbuf;
+	      sisfb_parm_rate = rate;
+	   } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
+	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
+	      nameptr = strbuf;
+	   } else {
+	      xres = 0;
+	      if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
+	         sprintf(strbuf, "%ux%ux8", xres, yres);
+	         nameptr = strbuf;
+	      } else {
+	         sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
+	         return;
+	      }
+	   }
+	}
 
-/* --------------- Hardware Access Routines -------------------------- */
+	i = 0; j = 0;
+	while(sisbios_mode[i].mode_no[0] != 0) {
+		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
+		   	if(sisfb_fstn) {
+		      		if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x56 ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x53) continue;
+	           	} else {
+		      		if(sisbios_mode[i-1].mode_no[1] == 0x5a ||
+		         	   sisbios_mode[i-1].mode_no[1] == 0x5b) continue;
+		   	}
+		   	sisfb_mode_idx = i - 1;
+		   	j = 1;
+		   	break;
+		}
+	}
+	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
+}
 
-/* These are used on x86 hardware during probe only */
+#ifndef MODULE
 static void __devinit
-sisfb_set_reg4(u16 port, u32 data)
+sisfb_get_vga_mode_from_kernel(void)
 {
-	outl((u32)(data & 0xffffffff), port);
+#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
+   	char mymode[32];
+	int  mydepth = screen_info.lfb_depth;
+	
+	if(screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return;
+
+	if( (screen_info.lfb_width >= 320) && (screen_info.lfb_width <= 2048) &&	
+	    (screen_info.lfb_height >= 200) && (screen_info.lfb_height <= 1536) &&
+	    (mydepth >= 8) && (mydepth <= 32) ) {
+	    
+	    if(mydepth == 24) mydepth = 32;
+	    
+	    sprintf(mymode, "%ux%ux%u", screen_info.lfb_width, 
+	    				screen_info.lfb_height,
+					mydepth);
+					
+	    printk(KERN_DEBUG "sisfb: Using vga mode %s pre-set by kernel as default\n", mymode);
+	    					
+	    sisfb_search_mode(mymode, TRUE);
+	}
+#endif
+	return;		    
 }
+#endif
 
-static u32 __devinit
-sisfb_get_reg3(u16 port)
+static void __init
+sisfb_search_crt2type(const char *name)
 {
-	return((u32)inl(port));
+	int i = 0;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	while(sis_crt2type[i].type_no != -1) {
+	   	if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
+	      		sisfb_crt2type = sis_crt2type[i].type_no;
+	      		sisfb_tvplug = sis_crt2type[i].tvplug_no;
+	      		sisfb_crt2flags = sis_crt2type[i].flags;
+	      		break;
+	   	}
+	   	i++;
+	}
+	
+	sisfb_dstn = (sisfb_crt2flags & FL_550_DSTN) ? 1 : 0;
+	sisfb_fstn = (sisfb_crt2flags & FL_550_FSTN) ? 1 : 0;
+	
+	if(sisfb_crt2type < 0) {
+		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
+	}
 }
 
-/* ------------------ Internal helper routines ----------------- */
+static void __init
+sisfb_search_tvstd(const char *name)
+{
+	int i = 0;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	while(sis_tvtype[i].type_no != -1) {
+	   	if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
+	      		sisfb_tvstd = sis_tvtype[i].type_no;
+	      		break;
+	   	}
+	   	i++;
+	}
+}
+
+static void __init
+sisfb_search_specialtiming(const char *name)
+{
+	int i = 0;
+	BOOLEAN found = FALSE;
+	
+	/* BEWARE: We don't know the hardware specs yet and there is no ivideo */
+
+	if(name == NULL) return;
+
+	if(!strnicmp(name, "none", 4)) {
+	        sisfb_specialtiming = CUT_FORCENONE;
+		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
+	} else {
+	   while(mycustomttable[i].chipID != 0) {
+	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
+		 sisfb_specialtiming = mycustomttable[i].SpecialID;
+		 found = TRUE;
+		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
+		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
+		 	mycustomttable[i].optionName);
+		 break;
+	      }
+	      i++;
+	   }
+	   if(!found) {
+	      printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
+	      printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
+	      i = 0;
+	      while(mycustomttable[i].chipID != 0) {
+		 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
+		     mycustomttable[i].optionName,
+		     mycustomttable[i].vendorName,
+		     mycustomttable[i].cardName);
+		 i++;
+	      }
+           }
+ 	}
+}
 
 static BOOLEAN __devinit
 sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer)
@@ -237,7 +474,7 @@ sisfb_interpret_edid(struct sisfb_monito
 }
 
 static void __devinit
-sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno)
+sisfb_handle_ddc(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, int crtno)
 {
 	USHORT  temp, i, realcrtno = crtno;
    	u8      buffer[256];
@@ -245,14 +482,15 @@ sisfb_handle_ddc(struct sisfb_monitor *m
 	monitor->datavalid = FALSE;
 
 	if(crtno) {
-       	   if(ivideo.vbflags & CRT2_LCD)      realcrtno = 1;
-      	   else if(ivideo.vbflags & CRT2_VGA) realcrtno = 2;
+       	   if(ivideo->vbflags & CRT2_LCD)      realcrtno = 1;
+      	   else if(ivideo->vbflags & CRT2_VGA) realcrtno = 2;
       	   else return;
    	}
 
-	if((sisfb_crt1off) && (!crtno)) return;
+	if((ivideo->sisfb_crt1off) && (!crtno)) return;
 
-    	temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, realcrtno, 0, &buffer[0]);
+    	temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 
+				realcrtno, 0, &buffer[0]);
    	if((!temp) || (temp == 0xffff)) {
       	   printk(KERN_INFO "sisfb: CRT%d DDC probing failed\n", crtno + 1);
 	   return;
@@ -267,7 +505,7 @@ sisfb_handle_ddc(struct sisfb_monitor *m
       	   if(temp & 0x02) {
 	      i = 3;  /* Number of retrys */
 	      do {
-	    	 temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine,
+	    	 temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
 				     realcrtno, 1, &buffer[0]);
 	      } while((temp) && i--);
               if(!temp) {
@@ -287,218 +525,9 @@ sisfb_handle_ddc(struct sisfb_monitor *m
 	}
 }
 
-static void __init
-sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
-{
-	int i = 0, j = 0;
-
-	if(vesamode == 0) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		sisfb_mode_idx = MODE_INDEX_NONE;
-#else
-		if(!quiet)
-		   printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-		sisfb_mode_idx = DEFAULT_MODE;
-#endif
-		return;
-	}
-
-	vesamode &= 0x1dff;  /* Clean VESA mode number from other flags */
-
-	while(sisbios_mode[i++].mode_no != 0) {
-		if( (sisbios_mode[i-1].vesa_mode_no_1 == vesamode) ||
-		    (sisbios_mode[i-1].vesa_mode_no_2 == vesamode) ) {
-		    if(sisfb_fstn) {
-		       if(sisbios_mode[i-1].mode_no == 0x50 ||
-		          sisbios_mode[i-1].mode_no == 0x56 ||
-		          sisbios_mode[i-1].mode_no == 0x53) continue;
-	            } else {
-		       if(sisbios_mode[i-1].mode_no == 0x5a ||
-		          sisbios_mode[i-1].mode_no == 0x5b) continue;
-		    }
-		    sisfb_mode_idx = i - 1;
-		    j = 1;
-		    break;
-		}
-	}
-	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid VESA mode 0x%x'\n", vesamode);
-}
-
-static void __init
-sisfb_search_mode(char *name, BOOLEAN quiet)
-{
-	int i = 0;
-	unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0;
-	char strbuf[16], strbuf1[20];
-	char *nameptr = name;
-
-	if(name == NULL) {
-	   if(!quiet)
-	      printk(KERN_ERR "sisfb: Internal error, using default mode.\n");
-	   sisfb_mode_idx = DEFAULT_MODE;
-	   return;
-	}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-        if (!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
-	   if(!quiet)
-	      printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
-	   sisfb_mode_idx = DEFAULT_MODE;
-	   return;
-	}
-#endif
-	if(strlen(name) <= 19) {
-	   strcpy(strbuf1, name);
-	   for(i=0; i<strlen(strbuf1); i++) {
-	      if(strbuf1[i] < '0' || strbuf1[i] > '9') strbuf1[i] = ' ';
-	   }
-
-	   /* This does some fuzzy mode naming detection */
-	   if(sscanf(strbuf1, "%u %u %u %u", &xres, &yres, &depth, &rate) == 4) {
-	      if((rate <= 32) || (depth > 32)) {
-	         j = rate; rate = depth; depth = j;
-	      }
-	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-	      nameptr = strbuf;
-	      ivideo.refresh_rate = sisfb_parm_rate = rate;
-	   } else if(sscanf(strbuf1, "%u %u %u", &xres, &yres, &depth) == 3) {
-	      sprintf(strbuf, "%ux%ux%u", xres, yres, depth);
-	      nameptr = strbuf;
-	   } else {
-	      xres = 0;
-	      if((sscanf(strbuf1, "%u %u", &xres, &yres) == 2) && (xres != 0)) {
-	         sprintf(strbuf, "%ux%ux8", xres, yres);
-	         nameptr = strbuf;
-	      } else {
-	         sisfb_search_vesamode(simple_strtoul(name, NULL, 0), quiet);
-	         return;
-	      }
-	   }
-	}
-
-	i = 0; j = 0;
-	while(sisbios_mode[i].mode_no != 0) {
-		if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
-		   if(sisfb_fstn) {
-		      if(sisbios_mode[i-1].mode_no == 0x50 ||
-		         sisbios_mode[i-1].mode_no == 0x56 ||
-		         sisbios_mode[i-1].mode_no == 0x53) continue;
-	           } else {
-		      if(sisbios_mode[i-1].mode_no == 0x5a ||
-		         sisbios_mode[i-1].mode_no == 0x5b) continue;
-		   }
-		   sisfb_mode_idx = i - 1;
-		   j = 1;
-		   break;
-		}
-	}
-	if((!j) && !quiet) printk(KERN_ERR "sisfb: Invalid mode '%s'\n", nameptr);
-
-}
-
-static void __init
-sisfb_search_crt2type(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while(sis_crt2type[i].type_no != -1) {
-		if (!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
-			sisfb_crt2type = sis_crt2type[i].type_no;
-			sisfb_tvplug = sis_crt2type[i].tvplug_no;
-			sisfb_dstn = (sis_crt2type[i].flags & FL_550_DSTN) ? 1 : 0;
-			sisfb_fstn = (sis_crt2type[i].flags & FL_550_FSTN) ? 1 : 0;
-			break;
-		}
-		i++;
-	}
-	if(sisfb_crt2type < 0)
-		printk(KERN_ERR "sisfb: Invalid CRT2 type: %s\n", name);
-        if(ivideo.chip != SIS_550) {
-	   sisfb_dstn = sisfb_fstn = 0;
-	}
-}
-
-static void __init
-sisfb_search_queuemode(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_queuemode[i].type_no != -1) {
-		if (!strnicmp(name, sis_queuemode[i].name, strlen(sis_queuemode[i].name))) {
-			sisfb_queuemode = sis_queuemode[i].type_no;
-			break;
-		}
-		i++;
-	}
-	if (sisfb_queuemode < 0)
-		printk(KERN_ERR "sisfb: Invalid queuemode type: %s\n", name);
-}
-
-static void __init
-sisfb_search_tvstd(const char *name)
-{
-	int i = 0;
-
-	if(name == NULL)
-		return;
-
-	while (sis_tvtype[i].type_no != -1) {
-		if (!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
-		        ivideo.vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN);
-			ivideo.vbflags |= sis_tvtype[i].type_no;
-			break;
-		}
-		i++;
-	}
-}
-
-static void __init
-sisfb_search_specialtiming(const char *name)
-{
-	int i = 0;
-	BOOLEAN found = FALSE;
-
-	if(name == NULL)
-		return;
-
-	if(!strnicmp(name, "none", 4)) {
-	        SiS_Pr.SiS_CustomT = CUT_FORCENONE;
-		printk(KERN_DEBUG "sisfb: Special timing disabled\n");
-	} else {
-	   while(mycustomttable[i].chipID != 0) {
-	      if(!strnicmp(name,mycustomttable[i].optionName, strlen(mycustomttable[i].optionName))) {
-		 SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
-		 found = TRUE;
-		 printk(KERN_INFO "sisfb: Special timing for %s %s forced (\"%s\")\n",
-		 	mycustomttable[i].vendorName, mycustomttable[i].cardName,
-		 	mycustomttable[i].optionName);
-		 break;
-	      }
-	      i++;
-	   }
-	   if(!found) {
-	      printk(KERN_WARNING "sisfb: Invalid SpecialTiming parameter, valid are:");
-	      printk(KERN_WARNING "\t\"none\" (to disable special timings)\n");
-	      i = 0;
-	      while(mycustomttable[i].chipID != 0) {
-		 printk(KERN_WARNING "\t\"%s\" (for %s %s)\n",
-		     mycustomttable[i].optionName,
-		     mycustomttable[i].vendorName,
-		     mycustomttable[i].cardName);
-		 i++;
-	      }
-           }
- 	}
-}
-
 static BOOLEAN
-sisfb_verify_rate(struct sisfb_monitor *monitor, int mode_idx, int rate_idx, int rate)
+sisfb_verify_rate(struct sis_video_info *ivideo, struct sisfb_monitor *monitor, 
+		int mode_idx, int rate_idx, int rate)
 {
 	int htotal, vtotal;
 	unsigned int dclock, hsync;
@@ -510,7 +539,8 @@ sisfb_verify_rate(struct sisfb_monitor *
 	if(rate < (monitor->vmin - 1)) return FALSE;
 	if(rate > (monitor->vmax + 1)) return FALSE;
 
-	if(sisfb_gettotalfrommode(&SiS_Pr, &sishw_ext, sisbios_mode[mode_idx].mode_no,
+	if(sisfb_gettotalfrommode(&ivideo->SiS_Pr, &ivideo->sishw_ext, 
+				  sisbios_mode[mode_idx].mode_no[ivideo->mni],
 	                          &htotal, &vtotal, rate_idx)) {
 		dclock = (htotal * vtotal * rate) / 1000;
 		if(dclock > (monitor->dclockmax + 1000)) return FALSE;
@@ -524,90 +554,69 @@ sisfb_verify_rate(struct sisfb_monitor *
 }
 
 static int
-sisfb_validate_mode(int myindex, unsigned long vbflags)
+sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
 {
    u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-   if(ivideo.sisvga_engine == SIS_300_VGA) {
+   if(ivideo->sisvga_engine == SIS_300_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS300)) return(-1);
    }
 #endif
 #ifdef CONFIG_FB_SIS_315
-   if(ivideo.sisvga_engine == SIS_315_VGA) {
+   if(ivideo->sisvga_engine == SIS_315_VGA) {
       if(!(sisbios_mode[myindex].chipset & MD_SIS315)) return(-1);
    }
 #endif
 
    myres = sisbios_mode[myindex].yres;
 
-   switch (vbflags & VB_DISPTYPE_DISP2) {
+   switch(vbflags & VB_DISPTYPE_DISP2) {
+   
      case CRT2_LCD:
-	switch(sishw_ext.ulCRT2LCDType) {
-	case LCD_640x480:  xres =  640; yres =  480;  break;
-	case LCD_800x600:  xres =  800; yres =  600;  break;
-        case LCD_1024x600: xres = 1024; yres =  600;  break;
-	case LCD_1024x768: xres = 1024; yres =  768;  break;
-	case LCD_1152x768: xres = 1152; yres =  768;  break;
-	case LCD_1280x960: xres = 1280; yres =  960;  break;
-	case LCD_1280x768: xres = 1280; yres =  768;  break;
-	case LCD_1280x1024:xres = 1280; yres = 1024;  break;
-	case LCD_1400x1050:xres = 1400; yres = 1050;  break;
-	case LCD_1600x1200:xres = 1600; yres = 1200;  break;
-	case LCD_320x480:  xres =  320; yres =  480;  break; /* FSTN (old) */
-	case LCD_640x480_2:
-	case LCD_640x480_3:xres =  640; yres =  480;  break; /* FSTN (new) */
-	case LCD_1680x1050:xres = 1680; yres = 1050;  break;
-	case LCD_1280x800: xres = 1280; yres =  800;  break;
-	case LCD_1280x720: yres = 1280; yres =  720;  break;
-	default:           xres =    0; yres =    0;  break;
-	}
 
-	if(SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
-	   xres = 1360; yres = 1024;
-	}
+        xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 
-	if(SiS_Pr.SiS_CustomT == CUT_PANEL848) {
-	   xres = 848;  yres =  480;
-	} else {
-	   if(sisbios_mode[myindex].xres > xres) return(-1);
-           if(myres > yres) return(-1);
+	if(ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) {
+	   	if(sisbios_mode[myindex].xres > xres) return(-1);
+           	if(myres > yres) return(-1);
 	}
 
 	if(vbflags & (VB_LVDS | VB_30xBDH)) {
 	   if(sisbios_mode[myindex].xres == 320) {
 	      if((myres == 240) || (myres == 480)) {
-		 if(!sisfb_fstn) {
-		    if(sisbios_mode[myindex].mode_no == 0x5a ||
-		       sisbios_mode[myindex].mode_no == 0x5b)
+		 if(!ivideo->sisfb_fstn) {
+		    if(sisbios_mode[myindex].mode_no[1] == 0x5a ||
+		       sisbios_mode[myindex].mode_no[1] == 0x5b)
 		       return(-1);
 		 } else {
-		    if(sisbios_mode[myindex].mode_no == 0x50 ||
-		       sisbios_mode[myindex].mode_no == 0x56 ||
-		       sisbios_mode[myindex].mode_no == 0x53)
+		    if(sisbios_mode[myindex].mode_no[1] == 0x50 ||
+		       sisbios_mode[myindex].mode_no[1] == 0x56 ||
+		       sisbios_mode[myindex].mode_no[1] == 0x53)
 		       return(-1);
 		 }
 	      }
 	   }
 	}
 
-	if(SiS_GetModeID_LCD(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres, sisbios_mode[myindex].yres,
-	                     0, sisfb_fstn, SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
-	   return(-1);
+	if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres, 
+			     sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn, 
+			     ivideo->SiS_Pr.SiS_CustomT, xres, yres) < 0x14) {
+	   	return(-1);
 	}
 	break;
 
      case CRT2_TV:
-	if(SiS_GetModeID_TV(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+	if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
 	                    sisbios_mode[myindex].yres, 0) < 0x14) {
-	   return(-1);
+	   	return(-1);
 	}
 	break;
 
      case CRT2_VGA:
-        if(SiS_GetModeID_VGA2(ivideo.sisvga_engine, vbflags, sisbios_mode[myindex].xres,
-	                    sisbios_mode[myindex].yres, 0) < 0x14) {
-	   return(-1);
+        if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+	                      sisbios_mode[myindex].yres, 0) < 0x14) {
+	   	return(-1);
 	}
 	break;
      }
@@ -615,9 +624,8 @@ sisfb_validate_mode(int myindex, unsigne
      return(myindex);
 }
 
-
 static u8
-sisfb_search_refresh_rate(unsigned int rate, int mode_idx)
+sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, int mode_idx)
 {
 	u16 xres, yres;
 	int i = 0;
@@ -625,55 +633,54 @@ sisfb_search_refresh_rate(unsigned int r
 	xres = sisbios_mode[mode_idx].xres;
 	yres = sisbios_mode[mode_idx].yres;
 
-	ivideo.rate_idx = 0;
-	while ((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
-		if ((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
-			if (sisfb_vrate[i].refresh == rate) {
-				ivideo.rate_idx = sisfb_vrate[i].idx;
+	ivideo->rate_idx = 0;
+	while((sisfb_vrate[i].idx != 0) && (sisfb_vrate[i].xres <= xres)) {
+		if((sisfb_vrate[i].xres == xres) && (sisfb_vrate[i].yres == yres)) {
+			if(sisfb_vrate[i].refresh == rate) {
+				ivideo->rate_idx = sisfb_vrate[i].idx;
 				break;
-			} else if (sisfb_vrate[i].refresh > rate) {
-				if ((sisfb_vrate[i].refresh - rate) <= 3) {
+			} else if(sisfb_vrate[i].refresh > rate) {
+				if((sisfb_vrate[i].refresh - rate) <= 3) {
 					DPRINTK("sisfb: Adjusting rate from %d up to %d\n",
 						rate, sisfb_vrate[i].refresh);
-					ivideo.rate_idx = sisfb_vrate[i].idx;
-					ivideo.refresh_rate = sisfb_vrate[i].refresh;
-				} else if (((rate - sisfb_vrate[i-1].refresh) <= 2)
+					ivideo->rate_idx = sisfb_vrate[i].idx;
+					ivideo->refresh_rate = sisfb_vrate[i].refresh;
+				} else if(((rate - sisfb_vrate[i-1].refresh) <= 2)
 						&& (sisfb_vrate[i].idx != 1)) {
 					DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i-1].refresh);
-					ivideo.rate_idx = sisfb_vrate[i-1].idx;
-					ivideo.refresh_rate = sisfb_vrate[i-1].refresh;
+					ivideo->rate_idx = sisfb_vrate[i-1].idx;
+					ivideo->refresh_rate = sisfb_vrate[i-1].refresh;
 				} 
 				break;
 			} else if((rate - sisfb_vrate[i].refresh) <= 2) {
 				DPRINTK("sisfb: Adjusting rate from %d down to %d\n",
 						rate, sisfb_vrate[i].refresh);
-	           		ivideo.rate_idx = sisfb_vrate[i].idx;
+	           		ivideo->rate_idx = sisfb_vrate[i].idx;
 		   		break;
 	       		}
 		}
 		i++;
 	}
-	if(ivideo.rate_idx > 0) {
-		return ivideo.rate_idx;
+	if(ivideo->rate_idx > 0) {
+		return ivideo->rate_idx;
 	} else {
-		printk(KERN_INFO
-			"sisfb: Unsupported rate %d for %dx%d\n", rate, xres, yres);
+		printk(KERN_INFO "sisfb: Unsupported rate %d for %dx%d\n", 
+				rate, xres, yres);
 		return 0;
 	}
 }
 
-
 static BOOLEAN
-sisfb_bridgeisslave(void)
+sisfb_bridgeisslave(struct sis_video_info *ivideo)
 {
    unsigned char P1_00;
 
-   if(!(ivideo.vbflags & VB_VIDEOBRIDGE)) return FALSE;
+   if(!(ivideo->vbflags & VB_VIDEOBRIDGE)) return FALSE;
 
    inSISIDXREG(SISPART1,0x00,P1_00);
-   if( ((ivideo.sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
-       ((ivideo.sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
+   if( ((ivideo->sisvga_engine == SIS_300_VGA) && (P1_00 & 0xa0) == 0x20) ||
+       ((ivideo->sisvga_engine == SIS_315_VGA) && (P1_00 & 0x50) == 0x10) ) {
 	   return TRUE;
    } else {
            return FALSE;
@@ -681,7 +688,7 @@ sisfb_bridgeisslave(void)
 }
 
 static BOOLEAN
-sisfballowretracecrt1(void)
+sisfballowretracecrt1(struct sis_video_info *ivideo)
 {
    u8 temp;
 
@@ -695,20 +702,20 @@ sisfballowretracecrt1(void)
 }
 
 static BOOLEAN
-sisfbcheckvretracecrt1(void)
+sisfbcheckvretracecrt1(struct sis_video_info *ivideo)
 {
-   if(!sisfballowretracecrt1()) return FALSE;
+   if(!sisfballowretracecrt1(ivideo)) return FALSE;
 
    if(inSISREG(SISINPSTAT) & 0x08) return TRUE;
    else 			   return FALSE;
 }
 
 static void
-sisfbwaitretracecrt1(void)
+sisfbwaitretracecrt1(struct sis_video_info *ivideo)
 {
    int watchdog;
 
-   if(!sisfballowretracecrt1()) return;
+   if(!sisfballowretracecrt1(ivideo)) return;
 
    watchdog = 65536;
    while((!(inSISREG(SISINPSTAT) & 0x08)) && --watchdog);
@@ -717,19 +724,14 @@ sisfbwaitretracecrt1(void)
 }
 
 static BOOLEAN
-sisfbcheckvretracecrt2(void)
+sisfbcheckvretracecrt2(struct sis_video_info *ivideo)
 {
    unsigned char temp, reg;
 
-   switch(ivideo.sisvga_engine) {
-   case SIS_300_VGA:
-   	reg = 0x25;
-	break;
-   case SIS_315_VGA:
-   	reg = 0x30;
-	break;
-   default:
-        return FALSE;
+   switch(ivideo->sisvga_engine) {
+   case SIS_300_VGA: reg = 0x25; break;
+   case SIS_315_VGA: reg = 0x30; break;
+   default:          return FALSE;
    }
 
    inSISIDXREG(SISPART1, reg, temp);
@@ -738,24 +740,70 @@ sisfbcheckvretracecrt2(void)
 }
 
 static BOOLEAN
-sisfb_CheckVBRetrace(void)
+sisfb_CheckVBRetrace(struct sis_video_info *ivideo)
 {
-   if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-      if(sisfb_bridgeisslave()) {
-         return(sisfbcheckvretracecrt1());
+   if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+      if(sisfb_bridgeisslave(ivideo)) {
+         return(sisfbcheckvretracecrt1(ivideo));
       } else {
-         return(sisfbcheckvretracecrt2());
+         return(sisfbcheckvretracecrt2(ivideo));
       }
    } 
-   return(sisfbcheckvretracecrt1());
+   return(sisfbcheckvretracecrt1(ivideo));
+}
+
+static u32
+sisfb_setupvbblankflags(struct sis_video_info *ivideo, u32 *vcount, u32 *hcount)
+{
+   u8 idx, reg1, reg2, reg3, reg4;
+   u32 ret = 0;
+   
+   (*vcount) = (*hcount) = 0;
+   
+   if((ivideo->currentvbflags & VB_DISPTYPE_DISP2) && (!(sisfb_bridgeisslave(ivideo)))) {
+      ret |= (FB_VBLANK_HAVE_VSYNC  |
+      	      FB_VBLANK_HAVE_HBLANK | 
+              FB_VBLANK_HAVE_VBLANK | 
+	      FB_VBLANK_HAVE_VCOUNT | 
+	      FB_VBLANK_HAVE_HCOUNT);
+      switch(ivideo->sisvga_engine) {
+         case SIS_300_VGA: idx = 0x25; break;
+	 default:
+         case SIS_315_VGA: idx = 0x30; break;
+      }
+      inSISIDXREG(SISPART1,(idx+0),reg1); /* 30 */
+      inSISIDXREG(SISPART1,(idx+1),reg2); /* 31 */
+      inSISIDXREG(SISPART1,(idx+2),reg3); /* 32 */
+      inSISIDXREG(SISPART1,(idx+3),reg4); /* 33 */
+      if(!(reg1 & 0x01)) ret |= FB_VBLANK_VBLANKING;
+      if(!(reg1 & 0x02)) ret |= FB_VBLANK_VSYNCING;
+      if(!(reg4 & 0x80)) ret |= FB_VBLANK_HBLANKING;
+      (*vcount) = reg3 | ((reg4 & 0x70) << 4);
+      (*hcount) = reg2 | ((reg4 & 0x0f) << 8);
+   } else if(sisfballowretracecrt1(ivideo)) {
+      ret |= (FB_VBLANK_HAVE_VSYNC  |
+              FB_VBLANK_HAVE_VBLANK | 
+	      FB_VBLANK_HAVE_VCOUNT | 
+	      FB_VBLANK_HAVE_HCOUNT);
+      reg1 = inSISREG(SISINPSTAT);
+      if(reg1 & 0x08) ret |= FB_VBLANK_VSYNCING;
+      if(reg1 & 0x01) ret |= FB_VBLANK_VBLANKING;
+      inSISIDXREG(SISCR,0x20,reg1);
+      inSISIDXREG(SISCR,0x1b,reg1);
+      inSISIDXREG(SISCR,0x1c,reg2);
+      inSISIDXREG(SISCR,0x1d,reg3);
+      (*vcount) = reg2 | ((reg3 & 0x07) << 8);
+      (*hcount) = (reg1 | ((reg3 & 0x10) << 4)) << 3;
+   }
+   return ret;
 }
 
 static int
-sisfb_myblank(int blank)
+sisfb_myblank(struct sis_video_info *ivideo, int blank)
 {
    u8 sr01, sr11, sr1f, cr63=0, p2_0, p1_13;
    BOOLEAN backlight = TRUE;
-
+   
    switch(blank) {
    case 0:	/* on */
       sr01  = 0x00;
@@ -806,63 +854,64 @@ sisfb_myblank(int blank)
       return 1;
    }
 
-   if(ivideo.currentvbflags & VB_DISPTYPE_CRT1) {
-
-      setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+   if(ivideo->currentvbflags & VB_DISPTYPE_CRT1) {
 
-      if( (!sisfb_thismonitor.datavalid) ||
-          ((sisfb_thismonitor.datavalid) &&
-           (sisfb_thismonitor.feature & 0xe0))) {
+      if( (!ivideo->sisfb_thismonitor.datavalid) ||
+          ((ivideo->sisfb_thismonitor.datavalid) &&
+           (ivideo->sisfb_thismonitor.feature & 0xe0))) {
 
-	 if(ivideo.sisvga_engine == SIS_315_VGA) {
-	    setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, 0xbf, cr63);
+	 if(ivideo->sisvga_engine == SIS_315_VGA) {
+	    setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xbf, cr63);
 	 }
 
-	 setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+	 if(!(sisfb_bridgeisslave(ivideo))) {
+	    setSISIDXREG(SISSR, 0x01, ~0x20, sr01);
+	    setSISIDXREG(SISSR, 0x1f, 0x3f, sr1f);
+	 }
       }
 
    }
 
-   if(ivideo.currentvbflags & CRT2_LCD) {
+   if(ivideo->currentvbflags & CRT2_LCD) {
 
-      if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+      if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
 	 if(backlight) {
-	    SiS_SiS30xBLOn(&SiS_Pr, &sishw_ext);
+	    SiS_SiS30xBLOn(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 	 } else {
-	    SiS_SiS30xBLOff(&SiS_Pr, &sishw_ext);
+	    SiS_SiS30xBLOff(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 	 }
-      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
-	 if(ivideo.vbflags & VB_CHRONTEL) {
+      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+	 if(ivideo->vbflags & VB_CHRONTEL) {
 	    if(backlight) {
-	       SiS_Chrontel701xBLOn(&SiS_Pr,&sishw_ext);
+	       SiS_Chrontel701xBLOn(&ivideo->SiS_Pr,&ivideo->sishw_ext);
 	    } else {
-	       SiS_Chrontel701xBLOff(&SiS_Pr);
+	       SiS_Chrontel701xBLOff(&ivideo->SiS_Pr);
 	    }
 	 }
       }
 
-      if(((ivideo.sisvga_engine == SIS_300_VGA) &&
-          (ivideo.vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
-         ((ivideo.sisvga_engine == SIS_315_VGA) &&
-          ((ivideo.vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
+      if(((ivideo->sisvga_engine == SIS_300_VGA) &&
+          (ivideo->vbflags & (VB_301|VB_30xBDH|VB_LVDS))) ||
+         ((ivideo->sisvga_engine == SIS_315_VGA) &&
+          ((ivideo->vbflags & (VB_LVDS | VB_CHRONTEL)) == VB_LVDS))) {
           setSISIDXREG(SISSR, 0x11, ~0x0c, sr11);
       }
 
-      if(ivideo.sisvga_engine == SIS_300_VGA) {
-         if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo.vbflags & VB_30xBDH))) {
+      if(ivideo->sisvga_engine == SIS_300_VGA) {
+         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
+            (!(ivideo->vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART1, 0x13, 0x3f, p1_13);
 	 }
-      } else if(ivideo.sisvga_engine == SIS_315_VGA) {
-         if((ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) &&
-            (!(ivideo.vbflags & VB_30xBDH))) {
+      } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+         if((ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) &&
+            (!(ivideo->vbflags & VB_30xBDH))) {
 	    setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
 	 }
       }
 
-   } else if(ivideo.currentvbflags & CRT2_VGA) {
+   } else if(ivideo->currentvbflags & CRT2_VGA) {
 
-      if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B)) {
+      if(ivideo->vbflags & (VB_301B|VB_301C|VB_302B)) {
          setSISIDXREG(SISPART2, 0x00, 0x1f, p2_0);
       }
 
@@ -873,37 +922,77 @@ sisfb_myblank(int blank)
 
 /* ----------- FBDev related routines for all series ----------- */
 
+static int
+sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
+{
+	return (var->bits_per_pixel == 8) ? 256 : 16;
+}
+
 static void
-sisfb_set_vparms(void)
+sisfb_set_vparms(struct sis_video_info *ivideo)
 {
-   switch(ivideo.video_bpp) {
-   case 8:
-       	ivideo.DstColor = 0x0000;
-	ivideo.SiS310_AccelDepth = 0x00000000;
-	ivideo.video_cmap_len = 256;
-       	break;
-   case 16:
-       	ivideo.DstColor = 0x8000;
-       	ivideo.SiS310_AccelDepth = 0x00010000;
-	ivideo.video_cmap_len = 16;
-       	break;
-   case 32:
-       	ivideo.DstColor = 0xC000;
-	ivideo.SiS310_AccelDepth = 0x00020000;
-	ivideo.video_cmap_len = 16;
-       	break;
-   default:
- 	ivideo.video_cmap_len = 16;
-	printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo.video_bpp);
-	ivideo.accel = 0;
-	break;
-   }
+   	switch(ivideo->video_bpp) {
+	case 8:
+		ivideo->DstColor = 0x0000;
+		ivideo->SiS310_AccelDepth = 0x00000000;
+		ivideo->video_cmap_len = 256;
+		break;
+	case 16:
+		ivideo->DstColor = 0x8000;
+		ivideo->SiS310_AccelDepth = 0x00010000;
+		ivideo->video_cmap_len = 16;
+		break;
+	case 32:
+		ivideo->DstColor = 0xC000;
+		ivideo->SiS310_AccelDepth = 0x00020000;
+		ivideo->video_cmap_len = 16;
+		break;
+	default:
+		ivideo->video_cmap_len = 16;
+		printk(KERN_ERR "sisfb: Unsupported depth %d", ivideo->video_bpp);
+		ivideo->accel = 0;
+		break;
+   	}
+}
+
+static void
+sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
+{
+	ivideo->video_cmap_len = sisfb_get_cmap_len(var);
+	
+	switch(var->bits_per_pixel) {
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = 6;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
 }
 
 static int
 sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int htotal = 0, vtotal = 0; 
 	unsigned int drate = 0, hrate = 0;
 	int found_mode = 0;
@@ -933,47 +1022,51 @@ sisfb_do_set_var(struct fb_var_screeninf
 	}
 
 	if(pixclock && htotal && vtotal) {
-	   drate = 1000000000 / pixclock;
-	   hrate = (drate * 1000) / htotal;
-	   ivideo.refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else ivideo.refresh_rate = 60;
-
-	old_mode = sisfb_mode_idx;
-	sisfb_mode_idx = 0;
-
-	while( (sisbios_mode[sisfb_mode_idx].mode_no != 0) &&
-	       (sisbios_mode[sisfb_mode_idx].xres <= var->xres) ) {
-		if( (sisbios_mode[sisfb_mode_idx].xres == var->xres) &&
-		    (sisbios_mode[sisfb_mode_idx].yres == var->yres) &&
-		    (sisbios_mode[sisfb_mode_idx].bpp == var->bits_per_pixel)) {
-			ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+	   	drate = 1000000000 / pixclock;
+	   	hrate = (drate * 1000) / htotal;
+	   	ivideo->refresh_rate = (unsigned int) (hrate * 2 / vtotal);
+	} else {
+	   	ivideo->refresh_rate = 60;
+	}
+
+	old_mode = ivideo->sisfb_mode_idx;
+	ivideo->sisfb_mode_idx = 0;
+
+	while( (sisbios_mode[ivideo->sisfb_mode_idx].mode_no[0] != 0) &&
+	       (sisbios_mode[ivideo->sisfb_mode_idx].xres <= var->xres) ) {
+		if( (sisbios_mode[ivideo->sisfb_mode_idx].xres == var->xres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].yres == var->yres) &&
+		    (sisbios_mode[ivideo->sisfb_mode_idx].bpp == var->bits_per_pixel)) {
+			ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 			found_mode = 1;
 			break;
 		}
-		sisfb_mode_idx++;
+		ivideo->sisfb_mode_idx++;
 	}
 
-	if(found_mode)
-		sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
-	else
-		sisfb_mode_idx = -1;
+	if(found_mode) {
+		ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo, 
+				ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+	} else {
+		ivideo->sisfb_mode_idx = -1;
+	}
 
-       	if(sisfb_mode_idx < 0) {
+       	if(ivideo->sisfb_mode_idx < 0) {
 		printk(KERN_ERR "sisfb: Mode %dx%dx%d not supported\n", var->xres,
 		       var->yres, var->bits_per_pixel);
-		sisfb_mode_idx = old_mode;
+		ivideo->sisfb_mode_idx = old_mode;
 		return -EINVAL;
 	}
 
-	if(sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx) == 0) {
-		ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
-		ivideo.refresh_rate = 60;
+	if(sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx) == 0) {
+		ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+		ivideo->refresh_rate = 60;
 	}
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	if(sisfb_thismonitor.datavalid) {
-	   if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-	                         ivideo.rate_idx, ivideo.refresh_rate)) {
+	if(ivideo->sisfb_thismonitor.datavalid) {
+	   if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+	                         ivideo->rate_idx, ivideo->refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
@@ -983,51 +1076,52 @@ sisfb_do_set_var(struct fb_var_screeninf
 	if(((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) {
 #else
 	if(isactive) {
-#endif
-		sisfb_pre_setmode();
+#endif	
+		sisfb_pre_setmode(ivideo);
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
-			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo.mode_no);
+		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
+			printk(KERN_ERR "sisfb: Setting mode[0x%x] failed\n", ivideo->mode_no);
 			return -EINVAL;
 		}
-
+		
 		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 		
-		ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
-		ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
-		ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
-		ivideo.org_x = ivideo.org_y = 0;
-		ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
+		sisfb_post_setmode(ivideo);
+		
+		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_vwidth  = ivideo->video_width  = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_vheight = ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+		ivideo->video_linelength = ivideo->video_width * (ivideo->video_bpp >> 3);
+		ivideo->org_x = ivideo->org_y = 0;
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = (var->accel_flags & FB_ACCELF_TEXT) ? -1 : 0;
 		}
 
-		sisfb_set_vparms();
+		sisfb_set_vparms(ivideo);
 		
-		ivideo.current_width = ivideo.video_width;
-		ivideo.current_height = ivideo.video_height;
-		ivideo.current_bpp = ivideo.video_bpp;
-		ivideo.current_htotal = htotal;
-		ivideo.current_vtotal = vtotal;
-		ivideo.current_pixclock = var->pixclock;
-		ivideo.current_refresh_rate = ivideo.refresh_rate;
+		ivideo->current_width = ivideo->video_width;
+		ivideo->current_height = ivideo->video_height;
+		ivideo->current_bpp = ivideo->video_bpp;
+		ivideo->current_htotal = htotal;
+		ivideo->current_vtotal = vtotal;
+		ivideo->current_pixclock = var->pixclock;
+		ivideo->current_refresh_rate = ivideo->refresh_rate;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-                sisfb_lastrates[ivideo.mode_no] = ivideo.refresh_rate;
+                ivideo->sisfb_lastrates[ivideo->mode_no] = ivideo->refresh_rate;
 #endif
 		
-		sisfb_post_setmode();
-
 	}
+
 	return 0;
 }
 
 static int
-sisfb_pan_var(struct fb_var_screeninfo *var)
+sisfb_pan_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
 	unsigned int base;
 
-	if (var->xoffset > (var->xres_virtual - var->xres)) {
+	if(var->xoffset > (var->xres_virtual - var->xres)) {
 		return -EINVAL;
 	}
 	if(var->yoffset > (var->yres_virtual - var->yres)) {
@@ -1038,11 +1132,11 @@ sisfb_pan_var(struct fb_var_screeninfo *
 		
         /* calculate base bpp dep. */
         switch(var->bits_per_pixel) {
+	case 32:
+            	break;
         case 16:
         	base >>= 1;
         	break;
-	case 32:
-            	break;
 	case 8:
         default:
         	base >>= 2;
@@ -1054,84 +1148,27 @@ sisfb_pan_var(struct fb_var_screeninfo *
         outSISIDXREG(SISCR, 0x0D, base & 0xFF);
 	outSISIDXREG(SISCR, 0x0C, (base >> 8) & 0xFF);
 	outSISIDXREG(SISSR, 0x0D, (base >> 16) & 0xFF);
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		setSISIDXREG(SISSR, 0x37, 0xFE, (base >> 24) & 0x01);
 	}
-        if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
-		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
+        if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
         	outSISIDXREG(SISPART1, 0x06, (base & 0xFF));
         	outSISIDXREG(SISPART1, 0x05, ((base >> 8) & 0xFF));
         	outSISIDXREG(SISPART1, 0x04, ((base >> 16) & 0xFF));
-		if(ivideo.sisvga_engine == SIS_315_VGA) {
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
 			setSISIDXREG(SISPART1, 0x02, 0x7F, ((base >> 24) & 0x01) << 7);
 		}
         }
 	return 0;
 }
 
-static void
-sisfb_bpp_to_var(struct fb_var_screeninfo *var)
-{
-	switch(var->bits_per_pixel) {
-	   case 8:
-	   	var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->red.length = var->green.length = var->blue.length = 6;
-		ivideo.video_cmap_len = 256;
-		break;
-	   case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		ivideo.video_cmap_len = 16;
-		break;
-	   case 32:
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		ivideo.video_cmap_len = 16;
-		break;
-	}
-}
-
-void
-sis_dispinfo(struct ap_data *rec)
-{
-	rec->minfo.bpp      = ivideo.video_bpp;
-	rec->minfo.xres     = ivideo.video_width;
-	rec->minfo.yres     = ivideo.video_height;
-	rec->minfo.v_xres   = ivideo.video_vwidth;
-	rec->minfo.v_yres   = ivideo.video_vheight;
-	rec->minfo.org_x    = ivideo.org_x;
-	rec->minfo.org_y    = ivideo.org_y;
-	rec->minfo.vrate    = ivideo.refresh_rate;
-	rec->iobase         = ivideo.vga_base - 0x30;
-	rec->mem_size       = ivideo.video_size;
-	rec->disp_state     = ivideo.disp_state; 
-	rec->version        = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL; 
-	rec->hasVB          = ivideo.hasVB;
-	rec->TV_type        = ivideo.TV_type; 
-	rec->TV_plug        = ivideo.TV_plug; 
-	rec->chip           = ivideo.chip;
-	rec->vbflags	    = ivideo.vbflags;
-	rec->currentvbflags = ivideo.currentvbflags;
-}
-
 /* ------------ FBDev related routines for 2.4 series ----------- */
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 
 static void
-sisfb_crtc_to_var(struct fb_var_screeninfo *var)
+sisfb_crtc_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var)
 {
 	u16 VRE, VBE, VRS, VBS, VDE, VT;
 	u16 HRE, HBE, HRS, HBS, HDE, HT;
@@ -1146,50 +1183,55 @@ sisfb_crtc_to_var(struct fb_var_screenin
 	else
 	   var->vmode = FB_VMODE_NONINTERLACED;
 
-	switch ((sr_data & 0x1C) >> 2) {
-	   case SIS_8BPP_COLOR_MODE:
+	switch((sr_data & 0x1C) >> 2) {
+	case SIS_8BPP_COLOR_MODE:
 		var->bits_per_pixel = 8;
 		break;
-	   case SIS_16BPP_COLOR_MODE:
+	case SIS_16BPP_COLOR_MODE:
 		var->bits_per_pixel = 16;
 		break;
-	   case SIS_32BPP_COLOR_MODE:
+	case SIS_32BPP_COLOR_MODE:
 		var->bits_per_pixel = 32;
 		break;
 	}
 
-	sisfb_bpp_to_var(var);
+	sisfb_bpp_to_var(ivideo, var);
 	
 	inSISIDXREG(SISSR, 0x0A, sr_data);
-
         inSISIDXREG(SISCR, 0x06, cr_data);
-
         inSISIDXREG(SISCR, 0x07, cr_data2);
 
-	VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |
-	     ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) << 10);
+	VT = (cr_data & 0xFF) | 
+	     ((u16) (cr_data2 & 0x01) << 8) |
+	     ((u16) (cr_data2 & 0x20) << 4) | 
+	     ((u16) (sr_data  & 0x01) << 10);
 	A = VT + 2;
 
 	inSISIDXREG(SISCR, 0x12, cr_data);
 
-	VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |
-	      ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);
+	VDE = (cr_data & 0xff) | 
+	      ((u16) (cr_data2 & 0x02) << 7) |
+	      ((u16) (cr_data2 & 0x40) << 3) | 
+	      ((u16) (sr_data  & 0x02) << 9);
 	E = VDE + 1;
 
 	inSISIDXREG(SISCR, 0x10, cr_data);
 
-	VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |
-	      ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);
+	VRS = (cr_data & 0xff) | 
+	      ((u16) (cr_data2 & 0x04) << 6) |
+	      ((u16) (cr_data2 & 0x80) << 2) | 
+	      ((u16) (sr_data  & 0x08) << 7);
 	F = VRS + 1 - E;
 
 	inSISIDXREG(SISCR, 0x15, cr_data);
-
 	inSISIDXREG(SISCR, 0x09, cr_data3);
 
 	if(cr_data3 & 0x80) var->vmode = FB_VMODE_DOUBLE;
 
-	VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |
-	      ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);
+	VBS = (cr_data & 0xff) | 
+	      ((u16) (cr_data2 & 0x08) << 5) |
+	      ((u16) (cr_data3 & 0x20) << 4) | 
+	      ((u16) (sr_data & 0x04) << 8);
 
 	inSISIDXREG(SISCR, 0x16, cr_data);
 
@@ -1223,7 +1265,6 @@ sisfb_crtc_to_var(struct fb_var_screenin
 	}
 
 	inSISIDXREG(SISSR, 0x0b, sr_data);
-
 	inSISIDXREG(SISCR, 0x00, cr_data);
 
 	HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);
@@ -1244,13 +1285,12 @@ sisfb_crtc_to_var(struct fb_var_screenin
 	HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);
 
 	inSISIDXREG(SISSR, 0x0c, sr_data);
-
 	inSISIDXREG(SISCR, 0x03, cr_data);
-
 	inSISIDXREG(SISCR, 0x05, cr_data2);
 
-	HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |
-	      ((u16) (sr_data & 0x03) << 6);
+	HBE = (cr_data & 0x1f) | 
+	      ((u16) (cr_data2 & 0x80) >> 2) |
+	      ((u16) (sr_data  & 0x03) << 6);
 	HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);
 
 	temp = HBE - ((E - 1) & 255);
@@ -1298,14 +1338,14 @@ sisfb_crtc_to_var(struct fb_var_screenin
 	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
 	   VT <<= 1;
 	}
-	hrate = ivideo.refresh_rate * VT / 2;
+	hrate = ivideo->refresh_rate * VT / 2;
 	drate = (hrate * HT) / 1000;
 	var->pixclock = (u32) (1000000000 / drate);
 
-	if(sisfb_ypan) {
-	   maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+	if(ivideo->sisfb_ypan) {
+	   maxyres = ivideo->heapstart / (var->xres * (var->bits_per_pixel >> 3));
 	   if(maxyres > 32767) maxyres = 32767;
-	   if(sisfb_max) {
+	   if(ivideo->sisfb_max) {
 	      var->yres_virtual = maxyres;
 	   } else {
 	      if(var->yres_virtual > maxyres) {
@@ -1315,44 +1355,48 @@ sisfb_crtc_to_var(struct fb_var_screenin
 	   if(var->yres_virtual <= var->yres) {
 	      var->yres_virtual = var->yres;
 	   }
-	} else
+	} else {
 	   var->yres_virtual = var->yres;
+	}
 
 }
 
 static int
 sis_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue,
-			 unsigned *transp, struct fb_info *fb_info)
+			 unsigned *transp, struct fb_info *info)
 {
-	if(regno >= ivideo.video_cmap_len)
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(regno >= ivideo->video_cmap_len) return 1;
 
-	*red = sis_palette[regno].red;
-	*green = sis_palette[regno].green;
-	*blue = sis_palette[regno].blue;
+	*red   = ivideo->sis_palette[regno].red;
+	*green = ivideo->sis_palette[regno].green;
+	*blue  = ivideo->sis_palette[regno].blue;
 	*transp = 0;
+
 	return 0;
 }
 
 static int
 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
-                           unsigned transp, struct fb_info *fb_info)
+                           unsigned transp, struct fb_info *info)
 {
-	if(regno >= ivideo.video_cmap_len)
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(regno >= ivideo->video_cmap_len) return 1;
 
-	sis_palette[regno].red = red;
-	sis_palette[regno].green = green;
-	sis_palette[regno].blue = blue;
+	ivideo->sis_palette[regno].red   = red;
+	ivideo->sis_palette[regno].green = green;
+	ivideo->sis_palette[regno].blue  = blue;
 
-	switch(ivideo.video_bpp) {
+	switch(ivideo->video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
 	        outSISREG(SISDACA, regno);
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1362,328 +1406,266 @@ sisfb_setcolreg(unsigned regno, unsigned
 #endif
 #ifdef FBCON_HAS_CFB16
 	case 16:
-		sis_fbcon_cmap.cfb16[regno] =
+		ivideo->sis_fbcon_cmap.cfb16[regno] =
 		    ((red & 0xf800)) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
 	case 32:
-		red >>= 8;
+		red   >>= 8;
 		green >>= 8;
-		blue >>= 8;
-		sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
+		blue  >>= 8;
+		ivideo->sis_fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue);
 		break;
 #endif
 	}
+	
 	return 0;
 }
 
 static void
-sisfb_set_disp(int con, struct fb_var_screeninfo *var,
-                           struct fb_info *info)
+sisfb_set_disp(int con, struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct sis_video_info    *ivideo = (struct sis_video_info *)info->par;
+	struct display           *display;
+	struct display_switch    *sw;
 	struct fb_fix_screeninfo fix;
 	long   flags;
-	struct display *display;
-	struct display_switch *sw;
 
-	if(con >= 0)
-		display = &fb_display[con];
-	else
-		display = &sis_disp;
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
 
-	sisfb_get_fix(&fix, con, 0);
+	sisfb_get_fix(&fix, con, info);
 
-	display->screen_base = ivideo.video_vbase;
+	display->var = *var;
+	display->screen_base = (char *)ivideo->video_vbase;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
 	display->ypanstep = fix.ypanstep;
 	display->ywrapstep = fix.ywrapstep;
 	display->line_length = fix.line_length;
-	display->next_line = fix.line_length;
 	display->can_soft_blank = 1;
-	display->inverse = sisfb_inverse;
-	display->var = *var;
+	display->inverse = ivideo->sisfb_inverse;
+	display->next_line = fix.line_length;
 
 	save_flags(flags);
 
-	switch(ivideo.video_bpp) {
+	switch(ivideo->video_bpp) {
 #ifdef FBCON_HAS_CFB8
-	   case 8:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis8 : &fbcon_cfb8;
-#else
-		sw = &fbcon_cfb8;
-#endif
+	case 8:
+		sw = ivideo->accel ? &fbcon_sis8 : &fbcon_cfb8;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
-	   case 16:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis16 : &fbcon_cfb16;
-#else
-		sw = &fbcon_cfb16;
-#endif
-		display->dispsw_data = sis_fbcon_cmap.cfb16;
+	case 16:
+		sw = ivideo->accel ? &fbcon_sis16 : &fbcon_cfb16;
+		display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb16;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	   case 32:
-#ifdef SISFBACCEL
-		sw = ivideo.accel ? &fbcon_sis32 : &fbcon_cfb32;
-#else
-		sw = &fbcon_cfb32;
-#endif
-		display->dispsw_data = sis_fbcon_cmap.cfb32;
+	case 32:
+		sw = ivideo->accel ? &fbcon_sis32 : &fbcon_cfb32;
+		display->dispsw_data = &ivideo->sis_fbcon_cmap.cfb32;
 		break;
 #endif
-	   default:
+	default:
 		sw = &fbcon_dummy;
-		return;
+		break;
 	}
-	memcpy(&sisfb_sw, sw, sizeof(*sw));
-	display->dispsw = &sisfb_sw;
+	memcpy(&ivideo->sisfb_sw, sw, sizeof(*sw));
+	display->dispsw = &ivideo->sisfb_sw;
+	
 	restore_flags(flags);
 
-        if(sisfb_ypan) {
+        if(ivideo->sisfb_ypan) {
   	    /* display->scrollmode = 0;  */
 	} else {
 	    display->scrollmode = SCROLL_YREDRAW;
-	    sisfb_sw.bmove = fbcon_redraw_bmove;
+	    ivideo->sisfb_sw.bmove = fbcon_redraw_bmove;
 	}
 }
 
 static void
 sisfb_do_install_cmap(int con, struct fb_info *info)
 {
-        if(con != currcon)
-		return;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+        if(con != ivideo->currcon) return;
 
-        if(fb_display[con].cmap.len)
+        if(fb_display[con].cmap.len) {
 		fb_set_cmap(&fb_display[con].cmap, 1, sisfb_setcolreg, info);
-        else
-		fb_set_cmap(fb_default_cmap(ivideo.video_cmap_len), 1,
-			    sisfb_setcolreg, info);
+        } else {
+		int size = sisfb_get_cmap_len(&fb_display[con].var);
+		fb_set_cmap(fb_default_cmap(size), 1, sisfb_setcolreg, info);
+	}
 }
 
-
 static int
-sisfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-	if(con == -1)
-		memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
-	else
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(con == -1) {
+		memcpy(var, &ivideo->default_var, sizeof(struct fb_var_screeninfo));
+	} else {
 		*var = fb_display[con].var;
+	}
 
-	if(sisfb_fstn) {
-	   if (var->xres == 320 && var->yres == 480)
-		var->yres = 240;
+	if(ivideo->sisfb_fstn) {
+	   	if(var->xres == 320 && var->yres == 480) var->yres = 240;
         }
 
 	return 0;
 }
 
 static int
-sisfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
-	int err;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int cols, rows;
+	int err;
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
-        if(sisfb_do_set_var(var, con == currcon, info)) {
-		sisfb_crtc_to_var(var);
+	
+        if(sisfb_do_set_var(var, con == ivideo->currcon, info)) {
+		sisfb_crtc_to_var(ivideo, var);
 		return -EINVAL;
 	}
 
-	sisfb_crtc_to_var(var);
+	sisfb_crtc_to_var(ivideo, var);
 
 	sisfb_set_disp(con, var, info);
 
-	if(info->changevar)
-		(*info->changevar) (con);
+	if(info->changevar) {
+		(*info->changevar)(con);
+	}
 
-	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))
+	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) {
 		return err;
+	}
 
 	sisfb_do_install_cmap(con, info);
 
-	cols = sisbios_mode[sisfb_mode_idx].cols;
-	rows = sisbios_mode[sisfb_mode_idx].rows;
-#if 0
-	/* Why was this called here? */
+	cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
+	rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
+	
+#if 0	/* Why was this called here? */
  	vc_resize_con(rows, cols, fb_display[con].conp->vc_num); 
 #endif	
-
 	return 0;
 }
 
 static int
-sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-        if(con == currcon)
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	struct display *display;
+	
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
+	
+        if(con == ivideo->currcon) {
+	
 		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);
-
-	else if (fb_display[con].cmap.len)
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-	else
-		fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2);
+		
+	} else if(display->cmap.len) {
+	
+		fb_copy_cmap(&display->cmap, cmap, kspc ? 0 : 2);
+		
+	} else {
+	
+		int size = sisfb_get_cmap_len(&display->var);
+		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+		
+	}
 
 	return 0;
 }
 
 static int
-sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
-	int err;
-
-	if(!fb_display[con].cmap.len) {
-		err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);
-		if (err)
-			return err;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	struct display *display;
+	int err, size;
+	
+	display = (con >= 0) ? &fb_display[con] : &ivideo->sis_disp;
+	
+	size = sisfb_get_cmap_len(&display->var);
+	if(display->cmap.len != size) {
+		err = fb_alloc_cmap(&display->cmap, size, 0);
+		if(err)	return err;
 	}
         
-	if(con == currcon)
+	if(con == ivideo->currcon) {
 		return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);
-
-	else
-		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+	} else {
+		fb_copy_cmap(cmap, &display->cmap, kspc ? 0 : 1);
+	}
 
 	return 0;
 }
 
 static int
-sisfb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info* info)
+sisfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
 
 	if(var->vmode & FB_VMODE_YWRAP) {
-		if(var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
+		if((var->yoffset < 0) || 
+		   (var->yoffset >= fb_display[con].var.yres_virtual) || 
+		   (var->xoffset)) {
 			return -EINVAL;
+		}
 	} else {
-		if(var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
-		   var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+		if((var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual) ||
+		   (var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)) {
 			return -EINVAL;
+		}
 	}
 
-        if(con == currcon) {
-	   if((err = sisfb_pan_var(var)) < 0) return err;
+        if(con == ivideo->currcon) {
+	   	if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
 	}
 
 	fb_display[con].var.xoffset = var->xoffset;
 	fb_display[con].var.yoffset = var->yoffset;
-	if(var->vmode & FB_VMODE_YWRAP)
+	if(var->vmode & FB_VMODE_YWRAP) {
 		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
-	else
+	} else {
 		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+	}
 
 	return 0;
 }
 
 static int
-sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
-{
-	struct fb_var_screeninfo var;
-	unsigned long start;
-	unsigned long off;
-	unsigned long len, mmio_off;
-
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
-#if 0
-	if (off >= len) {
-		off -= len;
-#endif
-	/* By Jake Page: Treat mmap request with offset beyond heapstart
-	 *               as request for mapping the mmio area 
-	 */
-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart);
-	if(off >= mmio_off) {
-		off -= mmio_off;		
-		sisfb_get_var(&var, currcon, info);
-		if(var.accel_flags) return -EINVAL;
-
-		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
-	}
-
-	start &= PAGE_MASK;
-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
-
-#if defined(__i386__) || defined(__x86_64__)
-	if(boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-        /* RedHat requires vma as the first paramater to the following call */
-	if(io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,
-			       vma->vm_page_prot))
-		return -EAGAIN;
-
-	return 0;
-}
-
-static void
-sis_get_glyph(struct fb_info *info, SIS_GLYINFO *gly)
-{
-	struct display *p = &fb_display[currcon];
-	u16 c;
-	u8 *cdat;
-	int widthb;
-	u8 *gbuf = gly->gmask;
-	int size;
-
-	gly->fontheight = fontheight(p);
-	gly->fontwidth = fontwidth(p);
-	widthb = (fontwidth(p) + 7) / 8;
-
-	c = gly->ch & p->charmask;
-	if(fontwidth(p) <= 8)
-		cdat = p->fontdata + c * fontheight(p);
-	else
-		cdat = p->fontdata + (c * fontheight(p) << 1);
-
-	size = fontheight(p) * widthb;
-	memcpy(gbuf, cdat, size);
-	gly->ngmask = size;
-}
-
-static int
 sisfb_update_var(int con, struct fb_info *info)
 {
-        return(sisfb_pan_var(&fb_display[con].var));
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+        return(sisfb_pan_var(ivideo, &fb_display[con].var));
 }
 
 static int
 sisfb_switch(int con, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int cols, rows;
 
-        if(fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);
+        if(fb_display[ivideo->currcon].cmap.len) {
+		fb_get_cmap(&fb_display[ivideo->currcon].cmap, 1, sis_getcolreg, info);
+	}
 
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
 
-	if(!memcmp(&fb_display[con].var, &fb_display[currcon].var,
-	                           sizeof(struct fb_var_screeninfo))) {
-		currcon = con;
+	if(!memcmp(&fb_display[con].var, &fb_display[ivideo->currcon].var,
+	                           	sizeof(struct fb_var_screeninfo))) {
+		ivideo->currcon = con;
 		return 1;
 	}
 
-	currcon = con;
+	ivideo->currcon = con;
 
 	sisfb_do_set_var(&fb_display[con].var, 1, info);
 
@@ -1691,8 +1673,8 @@ sisfb_switch(int con, struct fb_info *in
 
 	sisfb_do_install_cmap(con, info);
 
-	cols = sisbios_mode[sisfb_mode_idx].cols;
-	rows = sisbios_mode[sisfb_mode_idx].rows;
+	cols = sisbios_mode[ivideo->sisfb_mode_idx].cols;
+	rows = sisbios_mode[ivideo->sisfb_mode_idx].rows;
 	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);
 
 	sisfb_update_var(con, info);
@@ -1703,49 +1685,35 @@ sisfb_switch(int con, struct fb_info *in
 static void
 sisfb_blank(int blank, struct fb_info *info)
 {
-	sisfb_myblank(blank);
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	sisfb_myblank(ivideo, blank);
 }
 #endif
 
-/* ------------ FBDev related routines for 2.5 series ----------- */
+/* ------------ FBDev related routines for 2.6 series ----------- */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 
 static int
 sisfb_open(struct fb_info *info, int user)
 {
-    return 0;
+    	return 0;
 }
 
 static int
 sisfb_release(struct fb_info *info, int user)
 {
-    return 0;
-}
-
-static int
-sisfb_get_cmap_len(const struct fb_var_screeninfo *var)
-{
-	int rc = 16;		
-
-	switch(var->bits_per_pixel) {
-	case 8:
-		rc = 256;	
-		break;
-	case 16:
-	case 32:
-		rc = 16;
-		break;
-	}
-	return rc;
+    	return 0;
 }
 
 static int
 sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
 		unsigned transp, struct fb_info *info)
 {
-	if(regno >= sisfb_get_cmap_len(&info->var))
-		return 1;
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	if(regno >= sisfb_get_cmap_len(&info->var)) return 1;
 
 	switch(info->var.bits_per_pixel) {
 	case 8:
@@ -1753,7 +1721,7 @@ sisfb_setcolreg(unsigned regno, unsigned
 		outSISREG(SISDACD, (red >> 10));
 		outSISREG(SISDACD, (green >> 10));
 		outSISREG(SISDACD, (blue >> 10));
-		if(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 		        outSISREG(SISDAC2A, regno);
 			outSISREG(SISDAC2D, (red >> 8));
 			outSISREG(SISDAC2D, (green >> 8));
@@ -1768,8 +1736,8 @@ sisfb_setcolreg(unsigned regno, unsigned
 		red >>= 8;
 		green >>= 8;
 		blue >>= 8;
-		((u32 *) (info->pseudo_palette))[regno] =
-			(red << 16) | (green << 8) | (blue);
+		((u32 *)(info->pseudo_palette))[regno] =
+				(red << 16) | (green << 8) | (blue);
 		break;
 	}
 	return 0;
@@ -1780,8 +1748,9 @@ sisfb_set_par(struct fb_info *info)
 {
 	int err;
 
-        if((err = sisfb_do_set_var(&info->var, 1, info)))
+        if((err = sisfb_do_set_var(&info->var, 1, info))) {
 		return err;
+	}
 
 	sisfb_get_fix(&info->fix, info->currcon, info);
 
@@ -1789,9 +1758,9 @@ sisfb_set_par(struct fb_info *info)
 }
 
 static int
-sisfb_check_var(struct fb_var_screeninfo *var,
-                   struct fb_info *info)
+sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;
 	unsigned int drate = 0, hrate = 0, maxyres;
 	int found_mode = 0;
@@ -1821,12 +1790,12 @@ sisfb_check_var(struct fb_var_screeninfo
 	}
 
 	search_idx = 0;
-	while( (sisbios_mode[search_idx].mode_no != 0) &&
+	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&
 	       (sisbios_mode[search_idx].xres <= var->xres) ) {
 		if( (sisbios_mode[search_idx].xres == var->xres) &&
 		    (sisbios_mode[search_idx].yres == var->yres) &&
 		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {
-		        if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+		        if(sisfb_validate_mode(ivideo, search_idx, ivideo->currentvbflags) > 0) {
 			   found_mode = 1;
 			   break;
 			}
@@ -1836,11 +1805,11 @@ sisfb_check_var(struct fb_var_screeninfo
 
 	if(!found_mode) {
                 search_idx = 0;
-		while(sisbios_mode[search_idx].mode_no != 0) {
+		while(sisbios_mode[search_idx].mode_no[0] != 0) {
 		   if( (var->xres <= sisbios_mode[search_idx].xres) &&
 		       (var->yres <= sisbios_mode[search_idx].yres) &&
 		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {
-		          if(sisfb_validate_mode(search_idx, ivideo.currentvbflags) > 0) {
+		          if(sisfb_validate_mode(ivideo,search_idx, ivideo->currentvbflags) > 0) {
 			     found_mode = 1;
 			     break;
 			  }
@@ -1864,24 +1833,25 @@ sisfb_check_var(struct fb_var_screeninfo
 		}
 	}
 
-	if( ((ivideo.vbflags & VB_LVDS) ||			/* Slave modes on LVDS and 301B-DH */
-	     ((ivideo.vbflags & VB_30xBDH) && (ivideo.currentvbflags & CRT2_LCD))) &&
+	if( ((ivideo->vbflags & VB_LVDS) ||			/* Slave modes on LVDS and 301B-DH */
+	     ((ivideo->vbflags & VB_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&
 	    (var->bits_per_pixel == 8) ) {
 	    	refresh_rate = 60;
 		recalc_clock = TRUE;
-	} else if( (ivideo.current_htotal == htotal) &&		/* x=x & y=y & c=c -> assume depth change */
-	    	   (ivideo.current_vtotal == vtotal) &&
-	    	   (ivideo.current_pixclock == pixclock) ) {
+	} else if( (ivideo->current_htotal == htotal) &&	/* x=x & y=y & c=c -> assume depth change */
+	    	   (ivideo->current_vtotal == vtotal) &&
+	    	   (ivideo->current_pixclock == pixclock) ) {
 		drate = 1000000000 / pixclock;
 	        hrate = (drate * 1000) / htotal;
 	        refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if( ( (ivideo.current_htotal != htotal) ||	/* x!=x | y!=y & c=c -> invalid pixclock */
-	    	     (ivideo.current_vtotal != vtotal) ) &&
-	    	   (ivideo.current_pixclock == var->pixclock) ) {
-		if(sisfb_lastrates[sisbios_mode[search_idx].mode_no]) {
-			refresh_rate = sisfb_lastrates[sisbios_mode[search_idx].mode_no];
-		} else if(sisfb_parm_rate != -1) {
-			refresh_rate = sisfb_parm_rate;
+	} else if( ( (ivideo->current_htotal != htotal) ||	/* x!=x | y!=y & c=c -> invalid pixclock */
+	    	     (ivideo->current_vtotal != vtotal) ) &&
+	    	   (ivideo->current_pixclock == var->pixclock) ) {
+		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {
+			refresh_rate = ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];
+		} else if(ivideo->sisfb_parm_rate != -1) {
+			/* Sic, sisfb_parm_rate - want to know originally desired rate here */
+			refresh_rate = ivideo->sisfb_parm_rate;
 		} else {
 			refresh_rate = 60;
 		}
@@ -1890,56 +1860,53 @@ sisfb_check_var(struct fb_var_screeninfo
 		drate = 1000000000 / pixclock;
 	   	hrate = (drate * 1000) / htotal;
 	   	refresh_rate = (unsigned int) (hrate * 2 / vtotal);
-	} else if(ivideo.current_refresh_rate) {
-		refresh_rate = ivideo.current_refresh_rate;
+	} else if(ivideo->current_refresh_rate) {
+		refresh_rate = ivideo->current_refresh_rate;
 		recalc_clock = TRUE;
 	} else {
 		refresh_rate = 60;
 		recalc_clock = TRUE;
 	}
 
-	myrateindex = sisfb_search_refresh_rate(refresh_rate, search_idx);
+	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);
 
 	/* Eventually recalculate timing and clock */
 	if(recalc_clock) {
 	   if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;
-	   var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						sisbios_mode[search_idx].mode_no, myrateindex));
-	   sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-		 			sisbios_mode[search_idx].mode_no, myrateindex,
-		 			&var->left_margin, &var->right_margin,
-		 			&var->upper_margin, &var->lower_margin,
-		 			&var->hsync_len, &var->vsync_len,
-		 			&var->sync, &var->vmode);
+	   var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, 
+	   					&ivideo->sishw_ext, 
+						sisbios_mode[search_idx].mode_no[ivideo->mni], 
+						myrateindex));
+	   sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+		 		    sisbios_mode[search_idx].mode_no[ivideo->mni], myrateindex,	var);
 	   if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		var->pixclock <<= 1;
+	      var->pixclock <<= 1;
 	   }
 	}
 
-	if(sisfb_thismonitor.datavalid) {
-	   if(!sisfb_verify_rate(&sisfb_thismonitor, search_idx,
+	if(ivideo->sisfb_thismonitor.datavalid) {
+	   if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,
 	                         myrateindex, refresh_rate)) {
 	      printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 	   }
 	}
 
 	/* Adapt RGB settings */
-	sisfb_bpp_to_var(var);	
+	sisfb_bpp_to_var(ivideo, var);	
 	
 	/* Sanity check for offsets */
-	if (var->xoffset < 0)
-		var->xoffset = 0;
-	if (var->yoffset < 0)
-		var->yoffset = 0;
+	if(var->xoffset < 0) var->xoffset = 0;
+	if(var->yoffset < 0) var->yoffset = 0;
 
 	/* Horiz-panning not supported */
-	if(var->xres != var->xres_virtual)
-		var->xres_virtual = var->xres;
+	if(var->xres != var->xres_virtual) {
+	   var->xres_virtual = var->xres;
+	}
 	
-	if(sisfb_ypan) {
-	   maxyres = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));
+	if(ivideo->sisfb_ypan) {
+	   maxyres = ivideo->heapstart / (var->xres * (var->bits_per_pixel >> 3));
 	   if(maxyres > 32767) maxyres = 32767;
-	   if(sisfb_max) {
+	   if(ivideo->sisfb_max) {
 	      var->yres_virtual = maxyres;
 	   } else {
 	      if(var->yres_virtual > maxyres) {
@@ -1958,319 +1925,251 @@ sisfb_check_var(struct fb_var_screeninfo
 	}
 	
 	/* Truncate offsets to maximum if too high */
-	if(var->xoffset > var->xres_virtual - var->xres)
-		var->xoffset = var->xres_virtual - var->xres - 1;
+	if(var->xoffset > var->xres_virtual - var->xres) {
+	   var->xoffset = var->xres_virtual - var->xres - 1;
+	}
 
-	if(var->yoffset > var->yres_virtual - var->yres)
-		var->yoffset = var->yres_virtual - var->yres - 1;
+	if(var->yoffset > var->yres_virtual - var->yres) {
+	   var->yoffset = var->yres_virtual - var->yres - 1;
+	}
 	
 	/* Set everything else to 0 */
 	var->red.msb_right = 
-	    var->green.msb_right =
-	    var->blue.msb_right =
-	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;		
+	var->green.msb_right =
+	var->blue.msb_right =
+	var->transp.offset = 
+	var->transp.length = 
+	var->transp.msb_right = 0;		
 
 	return 0;
 }
 
 static int
-sisfb_pan_display(struct fb_var_screeninfo *var,
-		     struct fb_info* info)
+sisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
 	int err;
 
-	if(var->xoffset > (var->xres_virtual - var->xres))
+	if(var->xoffset > (var->xres_virtual - var->xres)) {
 		return -EINVAL;
-	if(var->yoffset > (var->yres_virtual - var->yres))
+	}
+	if(var->yoffset > (var->yres_virtual - var->yres)) {
 		return -EINVAL;
+	}
 
 	if(var->vmode & FB_VMODE_YWRAP) {
-		if(var->yoffset < 0 ||
-		   var->yoffset >= info->var.yres_virtual ||
-		   var->xoffset)
+		if((var->yoffset < 0) ||
+		   (var->yoffset >= info->var.yres_virtual) ||
+		   (var->xoffset)) {
 		    	return -EINVAL;
+		}
 	} else {
 		if(var->xoffset + info->var.xres > info->var.xres_virtual ||
-		   var->yoffset + info->var.yres > info->var.yres_virtual)
+		   var->yoffset + info->var.yres > info->var.yres_virtual) {
 			return -EINVAL;
+		}
 	}
 
-	if((err = sisfb_pan_var(var)) < 0) return err;
+	if((err = sisfb_pan_var(ivideo, var)) < 0) return err;
 
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
-	if(var->vmode & FB_VMODE_YWRAP)
+	if(var->vmode & FB_VMODE_YWRAP) {
 		info->var.vmode |= FB_VMODE_YWRAP;
-	else
+	} else {
 		info->var.vmode &= ~FB_VMODE_YWRAP;
-
-	return 0;
-}
-
-static int
-sisfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
-{
-	unsigned long start;
-	unsigned long off;
-	unsigned long len, mmio_off;
-
-	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-
-	start = (unsigned long) ivideo.video_base;
-	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);
-#if 0
-	if (off >= len) {
-		off -= len;
-#endif
-	/* By Jake Page: Treat mmap request with offset beyond heapstart
-	 *               as request for mapping the mmio area 
-	 */
-	mmio_off = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.heapstart);
-	if(off >= mmio_off) {
-		off -= mmio_off;		
-		if(info->var.accel_flags) return -EINVAL;
-
-		start = (unsigned long) ivideo.mmio_base;
-		len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.mmio_size);
 	}
 
-	start &= PAGE_MASK;
-	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;
-
-	off += start;
-	vma->vm_pgoff = off >> PAGE_SHIFT;
-	vma->vm_flags |= VM_IO;   /* by Jake Page; is that really needed? */
-
-#if defined(__i386__) || defined(__x86_64__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-	if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start,
-				vma->vm_page_prot))
-		return -EAGAIN;
-
 	return 0;
 }
 
 static int
 sisfb_blank(int blank, struct fb_info *info)
 {
-	return(sisfb_myblank(blank));
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
+	return(sisfb_myblank(ivideo, blank));
 }
 
 #endif
 
 /* ----------- FBDev related routines for all series ---------- */
 
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int sisfb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg,
-		       struct fb_info *info)
-#else
-static int sisfb_ioctl(struct inode *inode, struct file *file,
-		       unsigned int cmd, unsigned long arg, int con,
-		       struct fb_info *info)
-#endif
-{
-	struct sis_memreq sismemreq;
-	struct ap_data sisapdata;
-	unsigned long sismembase = 0;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	SIS_GLYINFO sisglyinfo;
-#endif
+static int 
+sisfb_ioctl(struct inode *inode, struct file *file,
+            unsigned int cmd, unsigned long arg, 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		       
+	    int con,
+#endif		       
+	    struct fb_info *info)
+{
+	struct sis_video_info 	*ivideo = (struct sis_video_info *)info->par;
+	struct sis_memreq 	sismemreq;
+	struct fb_vblank  	sisvbblank;
+	sisfb_info        	x;
+	u32			gpu32 = 0;
+	static int 		count = 0;
 
 	switch (cmd) {
 	   case FBIO_ALLOC:
-		if(!capable(CAP_SYS_RAWIO))
+		if(!capable(CAP_SYS_RAWIO)) {
 			return -EPERM;
-		if(copy_from_user(&sismemreq, (void *)arg, sizeof(sismemreq)))
+		}
+		if(copy_from_user(&sismemreq, (void *)arg, sizeof(sismemreq))) {
 		   	return -EFAULT;
+		}
         	sis_malloc(&sismemreq);
 		if(copy_to_user((void *)arg, &sismemreq, sizeof(sismemreq))) {
-			sis_free(sismemreq.offset);
+			sis_free((u32)sismemreq.offset);
 		    	return -EFAULT;
 		}
 		break;
+		
 	   case FBIO_FREE:
-		if(!capable(CAP_SYS_RAWIO))
+		if(!capable(CAP_SYS_RAWIO)) {
 			return -EPERM;
-		if(get_user(sismembase, (unsigned long *) arg))
+		}
+		if(get_user(gpu32, (u32 *)arg)) {
 			return -EFAULT;
-		sis_free(sismembase);
+		}
+		sis_free(gpu32);
 		break;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	   case FBIOGET_GLYPH:
-	        if(copy_from_user(&sisglyinfo, (void *)arg, sizeof(sisglyinfo)))
+		
+	   case FBIOGET_VBLANK:
+		sisvbblank.count = 0;
+		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);
+		if(copy_to_user((void *)arg, &sisvbblank, sizeof(sisvbblank))) {
 			return -EFAULT;
-                sis_get_glyph(info, &sisglyinfo);
+		}
 		break;
-	   case FBIOPUT_MODEINFO:
-		{
-			struct mode_info x;
-
-			if(copy_from_user(&x, (void *)arg, sizeof(x)))
-				return -EFAULT;
-
-			ivideo.video_bpp        = x.bpp;
-			ivideo.video_width      = x.xres;
-			ivideo.video_height     = x.yres;
-			ivideo.video_vwidth     = x.v_xres;
-			ivideo.video_vheight    = x.v_yres;
-			ivideo.org_x            = x.org_x;
-			ivideo.org_y            = x.org_y;
-			ivideo.refresh_rate     = x.vrate;
-			ivideo.video_linelength = ivideo.video_vwidth * (ivideo.video_bpp >> 3);
-			sisfb_set_vparms();
-			break;
+		
+	   case SISFB_GET_INFO_SIZE:
+	        return put_user(sizeof(sisfb_info), (u32 *)arg);
+		
+	   case SISFB_GET_INFO_OLD:
+	        if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
-#endif
-	   case FBIOGET_HWCINFO:
-		{
-			unsigned long myhwcoffset = 0;
-
-			if(ivideo.caps & HW_CURSOR_CAP)
-				myhwcoffset = ivideo.hwcursor_vbase -
-				    (unsigned long) ivideo.video_vbase;
-
-			return put_user(myhwcoffset, (unsigned long *)arg);
-
-			break;
+	   case SISFB_GET_INFO:  /* For communication with X driver */
+		x.sisfb_id         = SISFB_ID;
+		x.sisfb_version    = VER_MAJOR;
+		x.sisfb_revision   = VER_MINOR;
+		x.sisfb_patchlevel = VER_LEVEL;
+		x.chip_id = ivideo->chip_id;
+		x.memory = ivideo->video_size / 1024;
+		x.heapstart = ivideo->heapstart / 1024;
+		if(ivideo->modechanged) {
+		   x.fbvidmode = ivideo->mode_no;
+		} else {
+		   x.fbvidmode = ivideo->modeprechange;
 		}
-	   case FBIOGET_DISPINFO:
-	   	sis_dispinfo(&sisapdata);
-		if(copy_to_user((void *)arg, &sisapdata, sizeof(sisapdata)))
+		x.sisfb_caps = ivideo->caps;
+		x.sisfb_tqlen = 512; /* yet fixed */
+		x.sisfb_pcibus = ivideo->pcibus;
+		x.sisfb_pcislot = ivideo->pcislot;
+		x.sisfb_pcifunc = ivideo->pcifunc;
+		x.sisfb_lcdpdc = ivideo->detectedpdc;
+		x.sisfb_lcdpdca = ivideo->detectedpdca;
+		x.sisfb_lcda = ivideo->detectedlcda;
+		x.sisfb_vbflags = ivideo->vbflags;
+		x.sisfb_currentvbflags = ivideo->currentvbflags;
+		x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;
+		x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;
+		x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;
+		x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;
+		x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;
+		x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;
+		x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;
+		x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;
+		x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);
+		x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);
+			
+		if(copy_to_user((void *)arg, &x, sizeof(x))) {
 			return -EFAULT;
-		break;
-	   case SISFB_GET_INFO:  /* For communication with X driver */
-	        {
-			sisfb_info x;
-
-			x.sisfb_id = SISFB_ID;
-			x.sisfb_version = VER_MAJOR;
-			x.sisfb_revision = VER_MINOR;
-			x.sisfb_patchlevel = VER_LEVEL;
-			x.chip_id = ivideo.chip_id;
-			x.memory = ivideo.video_size / 1024;
-			x.heapstart = ivideo.heapstart / 1024;
-			if(ivideo.modechanged) {
-			   x.fbvidmode = ivideo.mode_no;
-			} else {
-			   x.fbvidmode = ivideo.modeprechange;
-			}
-			x.sisfb_caps = ivideo.caps;
-			x.sisfb_tqlen = 512; /* yet fixed */
-			x.sisfb_pcibus = ivideo.pcibus;
-			x.sisfb_pcislot = ivideo.pcislot;
-			x.sisfb_pcifunc = ivideo.pcifunc;
-			x.sisfb_lcdpdc = ivideo.detectedpdc;
-			x.sisfb_lcdpdca = ivideo.detectedpdca;
-			x.sisfb_lcda = ivideo.detectedlcda;
-			x.sisfb_vbflags = ivideo.vbflags;
-			x.sisfb_currentvbflags = ivideo.currentvbflags;
-			x.sisfb_scalelcd = SiS_Pr.UsePanelScaler;
-			x.sisfb_specialtiming = SiS_Pr.SiS_CustomT;
-			x.sisfb_haveemi = SiS_Pr.HaveEMI ? 1 : 0;
-			x.sisfb_haveemilcd = SiS_Pr.HaveEMILCD ? 1 : 0;
-			x.sisfb_emi30 = SiS_Pr.EMI_30;
-			x.sisfb_emi31 = SiS_Pr.EMI_31;
-			x.sisfb_emi32 = SiS_Pr.EMI_32;
-			x.sisfb_emi33 = SiS_Pr.EMI_33;
-			if(copy_to_user((void *)arg, &x, sizeof(x)))
-				return -EFAULT;
-	                break;
+		}
+	        break;
+		
+	   case SISFB_GET_VBRSTATUS_OLD:
+	   	if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_GET_VBRSTATUS:
-	        {
-			if(sisfb_CheckVBRetrace())
-				return put_user(1UL, (unsigned long *) arg);
-			else
-				return put_user(0UL, (unsigned long *) arg);
-			break;
+	        if(sisfb_CheckVBRetrace(ivideo)) {
+			return put_user((u32)1, (u32 *) arg);
+		} else {
+			return put_user((u32)0, (u32 *) arg);
+		}
+		
+	   case SISFB_GET_AUTOMAXIMIZE_OLD:
+	   	if(++count < 50) {
+	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_GET_AUTOMAXIMIZE:
-	        {
-			if(sisfb_max)
-				return put_user(1UL, (unsigned long *) arg);
-			else
-				return put_user(0UL, (unsigned long *) arg);
-			break;
+	        if(ivideo->sisfb_max) return put_user((u32)1, (u32 *)arg);
+		else 	              return put_user((u32)0, (u32 *)arg);
+		
+	   case SISFB_SET_AUTOMAXIMIZE_OLD:
+	   	if(++count < 50) {
+		   printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");
 		}
 	   case SISFB_SET_AUTOMAXIMIZE:
-	        {
-			unsigned long newmax;
+		if(copy_from_user(&gpu32, (u32 *)arg, sizeof(gpu32))) {
+			return -EFAULT;
+		}
+		ivideo->sisfb_max = (gpu32) ? 1 : 0;
+		break;
 
-			if(copy_from_user(&newmax, (unsigned long *)arg, sizeof(newmax)))
-				return -EFAULT;
+	   case SISFB_SET_TVPOSOFFSET:
+		if(copy_from_user(&gpu32, (u32 *)arg, sizeof(gpu32))) {
+			return -EFAULT;
+		}
+		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);
+		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);
+		break;
 
-			if(newmax) sisfb_max = 1;
-			else	   sisfb_max = 0;
-			break;
+	   case SISFB_GET_TVPOSOFFSET:
+	        return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)), (u32 *)arg);
+		
+	   case SISFB_SET_LOCK:
+		if(copy_from_user(&gpu32, (u32 *)arg, sizeof(gpu32))) {
+			return -EFAULT;
 		}
+		ivideo->sisfblocked = (gpu32) ? 1 : 0;
+		break;
+	        
 	   default:
 		return -EINVAL;
 	}
 	return 0;
 }
 
-
 static int
-sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-	      struct fb_info *info)
+sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 {
+	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;
+	
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-	strcpy(fix->id, sis_fb_info->modename);
-#else
-	strcpy(fix->id, myid);
-#endif	
-
-	fix->smem_start = ivideo.video_base;
-
-        if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-	    if(ivideo.sisvga_engine == SIS_300_VGA) {
-	       if(ivideo.video_size > 0x1000000) {
-	          	fix->smem_len = 0xc00000;
-	       } else if(ivideo.video_size > 0x800000)
-		  	fix->smem_len = 0x800000;
-	       else
-		  	fix->smem_len = 0x400000;
-            } else {
-	       	fix->smem_len = ivideo.video_size - 0x100000;
-	    }
-        } else
-		fix->smem_len = sisfb_mem * 1024;
+	strcpy(fix->id, ivideo->myid);
 
+	fix->smem_start  = ivideo->video_base;
+	fix->smem_len    = ivideo->sisfb_mem;
 	fix->type        = FB_TYPE_PACKED_PIXELS;
 	fix->type_aux    = 0;
-	if(ivideo.video_bpp == 8)
-	   fix->visual = FB_VISUAL_PSEUDOCOLOR;
-	else
-	   fix->visual = FB_VISUAL_TRUECOLOR;
+	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
 	fix->xpanstep    = 0;
-
-        if(sisfb_ypan) 	 fix->ypanstep = 1;
-
+	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;
 	fix->ywrapstep   = 0;
-	fix->line_length = ivideo.video_linelength;
-	fix->mmio_start  = ivideo.mmio_base;
-	fix->mmio_len    = ivideo.mmio_size;
-	if(ivideo.sisvga_engine == SIS_300_VGA) 
+	fix->line_length = ivideo->video_linelength;
+	fix->mmio_start  = ivideo->mmio_base;
+	fix->mmio_len    = ivideo->mmio_size;
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 	   fix->accel    = FB_ACCEL_SIS_GLAMOUR;
-	else if((ivideo.chip == SIS_330) || (ivideo.chip == SIS_760))
+	} else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {
 	   fix->accel    = FB_ACCEL_SIS_XABRE;
-	else
+	} else {
 	   fix->accel    = FB_ACCEL_SIS_GLAMOUR_2;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	fix->reserved[0] = ivideo.video_size & 0xFFFF;
-	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;
-	fix->reserved[2] = ivideo.caps;
-#endif
+	}
 
 	return 0;
 }
@@ -2286,437 +2185,414 @@ static struct fb_ops sisfb_ops = {
 	.fb_get_cmap	= sisfb_get_cmap,
 	.fb_set_cmap	= sisfb_set_cmap,
         .fb_pan_display = sisfb_pan_display,
-	.fb_ioctl	= sisfb_ioctl,
-	.fb_mmap	= sisfb_mmap,
+	.fb_ioctl	= sisfb_ioctl
 };
 #endif
 
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 static struct fb_ops sisfb_ops = {
-	.owner        =	THIS_MODULE,
-	.fb_open      = sisfb_open,
-	.fb_release   = sisfb_release,
-	.fb_check_var = sisfb_check_var,
-	.fb_set_par   = sisfb_set_par,
-	.fb_setcolreg = sisfb_setcolreg,
+	.owner          = THIS_MODULE,
+	.fb_open        = sisfb_open,
+	.fb_release     = sisfb_release,
+	.fb_check_var   = sisfb_check_var,
+	.fb_set_par     = sisfb_set_par,
+	.fb_setcolreg   = sisfb_setcolreg,
         .fb_pan_display = sisfb_pan_display,
-        .fb_blank     = sisfb_blank,
-	.fb_fillrect  = fbcon_sis_fillrect,
-	.fb_copyarea  = fbcon_sis_copyarea,
-	.fb_imageblit = cfb_imageblit,
-	.fb_cursor    = soft_cursor,	
-	.fb_sync      = fbcon_sis_sync,
-	.fb_ioctl     =	sisfb_ioctl,
-	.fb_mmap      =	sisfb_mmap,
+        .fb_blank       = sisfb_blank,
+	.fb_fillrect    = fbcon_sis_fillrect,
+	.fb_copyarea    = fbcon_sis_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_cursor      = soft_cursor,	
+	.fb_sync        = fbcon_sis_sync,
+	.fb_ioctl       = sisfb_ioctl
 };
 #endif
 
-
 /* ---------------- Chip generation dependent routines ---------------- */
 
-#ifdef CONFIG_FB_SIS_300 /* for SiS 300/630/540/730 */
-
-static int __devinit sisfb_get_dram_size_300(void)
+static struct pci_dev * sisfb_get_northbridge(int basechipid)
 {
 	struct pci_dev *pdev = NULL;
-	int pdev_valid = 0;
-	u8  pci_data, reg;
-	u16 nbridge_id;
-
-	switch(ivideo.chip) {
-	   case SIS_540:
-		nbridge_id = PCI_DEVICE_ID_SI_540;
-		break;
-	   case SIS_630:
-		nbridge_id = PCI_DEVICE_ID_SI_630;
-		break;
-	   case SIS_730:
-		nbridge_id = PCI_DEVICE_ID_SI_730;
-		break;
-	   default:
-		nbridge_id = 0;
-		break;
+	int nbridgenum, nbridgeidx, i;
+	const unsigned short nbridgeids[] = { 
+		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */
+		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */
+		PCI_DEVICE_ID_SI_730,
+		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */
+		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */
+		PCI_DEVICE_ID_SI_651,
+		PCI_DEVICE_ID_SI_740,
+		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760 VGA */
+		PCI_DEVICE_ID_SI_741,
+		PCI_DEVICE_ID_SI_660,
+		PCI_DEVICE_ID_SI_760
+	};
+		
+    	switch(basechipid) {
+#ifdef CONFIG_FB_SIS_300	
+	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;
+	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;
+#endif			
+#ifdef CONFIG_FB_SIS_315			
+	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;
+	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;
+	case SIS_660:	nbridgeidx = 7; nbridgenum = 4; break;
+#endif			
+	default:	return NULL;
 	}
-
-	if(nbridge_id == 0) {   /* 300 */
-
-	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE,reg);
-		ivideo.video_size =
-		        ((unsigned int) ((reg & SIS_DRAM_SIZE_MASK) + 1) << 20);
-
-	} else {		/* 540, 630, 730 */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74)
-		pci_for_each_dev(pdev) {
-#else
-		while((pdev = pci_find_device(PCI_VENDOR_ID_SI, PCI_ANY_ID, pdev))) {
-#endif
-			if ((pdev->vendor == PCI_VENDOR_ID_SI)
-				       && (pdev->device == nbridge_id)) {
-				pci_read_config_byte(pdev, IND_BRI_DRAM_STATUS, &pci_data);
-				pci_data = (pci_data & BRI_DRAM_SIZE_MASK) >> 4;
-				ivideo.video_size = (unsigned int)(1 << (pci_data+21));
-				pdev_valid = 1;
-
-				reg = SIS_DATA_BUS_64 << 6;
-				switch (pci_data) {
-				   case BRI_DRAM_SIZE_2MB:
-					reg |= SIS_DRAM_SIZE_2MB;
-					break;
-				   case BRI_DRAM_SIZE_4MB:
-					reg |= SIS_DRAM_SIZE_4MB;
-					break;
-				   case BRI_DRAM_SIZE_8MB:
-					reg |= SIS_DRAM_SIZE_8MB;
-					break;
-				   case BRI_DRAM_SIZE_16MB:
-					reg |= SIS_DRAM_SIZE_16MB;
-					break;
-				   case BRI_DRAM_SIZE_32MB:
-					reg |= SIS_DRAM_SIZE_32MB;
-					break;
-				   case BRI_DRAM_SIZE_64MB:
-					reg |= SIS_DRAM_SIZE_64MB;
-					break;
-				}
-				outSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-				break;
-			}  
-		}   
-	
-		if (!pdev_valid)  return -1;
+	for(i = 0; i < nbridgenum; i++) {
+		if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;
 	}
-	return 0;
+	return pdev;
 }
 
-#endif  /* CONFIG_FB_SIS_300 */
-
-
-#ifdef CONFIG_FB_SIS_315    /* for SiS 315/550/650/740/330/661/741/760 */
-
-static int __devinit sisfb_get_dram_size_315(void)
+static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo)
 {
-	u8  reg = 0;
-
-	if(ivideo.chip == SIS_550 ||
-	   ivideo.chip == SIS_650 ||
-	   ivideo.chip == SIS_740) {
-
-                inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-		reg &= 0x3f;
-		reg++;
-		reg <<= 2;
-		ivideo.video_size = reg << 20;
-		return 0;
-
-	} else if(ivideo.chip == SIS_661 ||
-	          ivideo.chip == SIS_741) {
-
-		inSISIDXREG(SISCR, 0x79, reg);
-		reg &= 0xf0;
-		reg >>= 4;
-		ivideo.video_size = (1 << reg) << 20;
-		return 0;
-
-	} else if(ivideo.chip == SIS_660 ||
-		  ivideo.chip == SIS_760) {
+	u8 reg;
+	
+	ivideo->video_size = 0;
 
-		ivideo.video_size = 0;
+	switch(ivideo->chip) {
+#ifdef CONFIG_FB_SIS_300 
+	case SIS_300:
+	        inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = ((reg & 0x3F) + 1) << 20;
+		break;
+	case SIS_540:
+	case SIS_630:
+	case SIS_730:
+	   	if(!ivideo->nbridge) return -1;
+	   	pci_read_config_byte(ivideo->nbridge, 0x63, &reg);
+		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);
+		break;
+#endif  
+#ifdef CONFIG_FB_SIS_315
+	case SIS_315H:
+	case SIS_315PRO:
+	case SIS_315:
+	   	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		switch((reg >> 2) & 0x03) {
+		case 0x01:
+		case 0x03:
+		   ivideo->video_size <<= 1;
+		   break;
+		case 0x02:
+		   ivideo->video_size += (ivideo->video_size/2);
+		}
+	   	break;	
+	case SIS_330:
+	   	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+		if(reg & 0x0c) ivideo->video_size <<= 1;
+	   	break;
+	case SIS_550:
+	case SIS_650:
+	case SIS_740:
+	    	inSISIDXREG(SISSR, 0x14, reg);
+		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;
+		break;
+	case SIS_661:
+	case SIS_741:
+	     	inSISIDXREG(SISCR, 0x79, reg);
+		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
+	   	break;
+	case SIS_660:
+	case SIS_760:
 		inSISIDXREG(SISCR, 0x79, reg);
-		reg &= 0xf0;
-		reg >>= 4;
-		if(reg)	ivideo.video_size = (1 << reg) << 20;
+		reg = (reg & 0xf0) >> 4;
+		if(reg)	ivideo->video_size = (1 << reg) << 20;
 		inSISIDXREG(SISCR, 0x78, reg);
 		reg &= 0x30;
 		if(reg) {
-		   if(reg == 0x10) ivideo.video_size += (32 << 20);
-		   else		   ivideo.video_size += (64 << 20);
-		}
-		return 0;
-
-	} else {	/* 315, 330 */
-
-	        inSISIDXREG(SISSR, IND_SIS_DRAM_SIZE, reg);
-		ivideo.video_size = (1 << ((reg & 0xf0) >> 4)) << 20;
-
-		reg &= SIS315_DUAL_CHANNEL_MASK;
-		reg >>= 2;
-
-		if(ivideo.chip == SIS_330) {
-
-		   if(reg) ivideo.video_size <<= 1;
-		
-		} else {
-		   
-		   switch (reg) {
-		      case SIS315_SINGLE_CHANNEL_2_RANK:
-			   ivideo.video_size <<= 1;
-			   break;
-		      case SIS315_DUAL_CHANNEL_1_RANK:
-			   ivideo.video_size <<= 1;
-			   break;
-		      case SIS315_ASYM_DDR:		/* TW: DDR asymetric */
-			   ivideo.video_size += (ivideo.video_size/2);
-			   break;
-		   }
+		   if(reg == 0x10) ivideo->video_size += (32 << 20);
+		   else		   ivideo->video_size += (64 << 20);
 		}
-
-		return 0;
+	   	break;
+#endif		
+	default:
+		return -1;
 	}
-	
-	return -1;
-	
+	return 0;
 }
 
-#endif   /* CONFIG_FB_SIS_315 */
-
+/* -------------- video bridge device detection --------------- */
 
-/* -------------- video bridge detection --------------- */
-
-static void __devinit sisfb_detect_VB_connect()
+static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo)
 {
-	u8 sr16, sr17, cr32, temp;
-
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
-	
-		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_17, sr17);
-	      
-		if ((sr17 & 0x0F) && (ivideo.chip != SIS_300)) {
+	u8 cr32, temp;
 
+#ifdef CONFIG_FB_SIS_300	
+	if(ivideo->sisvga_engine == SIS_300_VGA) {	
+		inSISIDXREG(SISSR, 0x17, temp);	      
+		if((temp & 0x0F) && (ivideo->chip != SIS_300)) {
 			/* PAL/NTSC is stored on SR16 on such machines */
-			if (!(ivideo.vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-		   		inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_16, sr16);
-				if (sr16 & 0x20)
-					ivideo.vbflags |= TV_PAL;
+			if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
+		   		inSISIDXREG(SISSR, 0x16, temp);
+				if(temp & 0x20)
+					ivideo->vbflags |= TV_PAL;
 				else
-					ivideo.vbflags |= TV_NTSC;
+					ivideo->vbflags |= TV_NTSC;
 			}
-
 		} 
-		
 	}
+#endif
 	
-	inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR32, cr32);
+	inSISIDXREG(SISCR, 0x32, cr32);
 
 	if(cr32 & SIS_CRT1) {
-		sisfb_crt1off = 0;
+		ivideo->sisfb_crt1off = 0;
 	} else {
-		if (cr32 & 0x5F) sisfb_crt1off = 1;
-		else		 sisfb_crt1off = 0;
+		ivideo->sisfb_crt1off = (cr32 & 0xDF) ? 1 : 0;
 	}
 
-	ivideo.vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
+	ivideo->vbflags &= ~(CRT2_TV | CRT2_LCD | CRT2_VGA);
 
-	if(cr32 & SIS_VB_TV)   ivideo.vbflags |= CRT2_TV;
-	if(cr32 & SIS_VB_LCD)  ivideo.vbflags |= CRT2_LCD;
-	if(cr32 & SIS_VB_CRT2) ivideo.vbflags |= CRT2_VGA;
+	if(cr32 & SIS_VB_TV)   ivideo->vbflags |= CRT2_TV;
+	if(cr32 & SIS_VB_LCD)  ivideo->vbflags |= CRT2_LCD;
+	if(cr32 & SIS_VB_CRT2) ivideo->vbflags |= CRT2_VGA;
+	
+	/* Check given parms for hardware compatibility.
+	 * (Cannot do this in the search_xx routines since we don't 
+	 * know what hardware we are running on then)
+	 */ 
+	
+	if(ivideo->chip != SIS_550) {
+	   ivideo->sisfb_dstn = ivideo->sisfb_fstn = 0;
+	}
+	
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) || 
+	       (!(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) ) {
+	      if(ivideo->sisfb_tvplug & TV_YPBPR) {
+	         ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: YPbPr not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvplug != -1) {
+	   if( (ivideo->sisvga_engine != SIS_315_VGA) || 
+	       (!(ivideo->vbflags & (VB_301|VB_301B|VB_302B))) ) {
+	      if(ivideo->sisfb_tvplug & TV_HIVISION) {
+	         ivideo->sisfb_tvplug = -1;
+		 printk(KERN_ERR "sisfb: HiVision not supported\n");
+	      }
+	   }
+	}
+	if(ivideo->sisfb_tvstd != -1) {
+	   if( (!(ivideo->vbflags & VB_SISBRIDGE)) &&
+	       (!((ivideo->sisvga_engine == SIS_315_VGA) && (ivideo->vbflags & VB_CHRONTEL))) ) {
+	      if(ivideo->sisfb_tvstd & (TV_PALN | TV_PALN | TV_NTSCJ)) {
+	         ivideo->sisfb_tvstd = -1;
+	         printk(KERN_ERR "sisfb: PALM/PALN/NTSCJ not supported\n");
+	      }
+	   }
+	}
 		
 	/* Detect/set TV plug & type */
-	if(sisfb_tvplug != -1) ivideo.vbflags |= sisfb_tvplug;
-
-	if(cr32 & SIS_VB_SVIDEO)	  ivideo.vbflags |= TV_SVIDEO;
-	else if (cr32 & SIS_VB_COMPOSITE) ivideo.vbflags |= TV_AVIDEO;
-	else if (cr32 & SIS_VB_SCART) {
-		ivideo.vbflags |= (TV_SCART | TV_PAL);
-		ivideo.vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN);
+	if(ivideo->sisfb_tvplug != -1) {
+		ivideo->vbflags |= ivideo->sisfb_tvplug;
+	} else {
+		if(cr32 & SIS_VB_YPBPR)     	 ivideo->vbflags |= (TV_YPBPR|TV_YPBPR525I); /* default: 480i */
+		else if(cr32 & SIS_VB_HIVISION)  ivideo->vbflags |= TV_HIVISION;
+		else if(cr32 & SIS_VB_SCART)     ivideo->vbflags |= TV_SCART;
+	 	else {
+			if(cr32 & SIS_VB_SVIDEO)    ivideo->vbflags |= TV_SVIDEO;
+			if(cr32 & SIS_VB_COMPOSITE) ivideo->vbflags |= TV_AVIDEO;
+		}
 	}
-
-	if(!(ivideo.vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN))) {
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
-	        	inSISIDXREG(SISSR, IND_SIS_POWER_ON_TRAP, temp);
-			if(temp & 0x01) ivideo.vbflags |= TV_PAL;
-			else		ivideo.vbflags |= TV_NTSC;
-		} else if((ivideo.chip <= SIS_315PRO) || (ivideo.chip >= SIS_330)) {
+	
+	if(!(ivideo->vbflags & (TV_YPBPR | TV_HIVISION))) {
+	    if(ivideo->sisfb_tvstd != -1) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PAL | TV_PALM | TV_PALN | TV_NTSCJ); 
+	       ivideo->vbflags |= ivideo->sisfb_tvstd;
+	    }
+	    if(ivideo->vbflags & TV_SCART) {
+	       ivideo->vbflags &= ~(TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ);
+	       ivideo->vbflags |= TV_PAL;
+	    }
+	    if(!(ivideo->vbflags & (TV_PAL | TV_NTSC | TV_PALM | TV_PALN | TV_NTSCJ))) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+	        	inSISIDXREG(SISSR, 0x38, temp);
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
+		} else if((ivideo->chip <= SIS_315PRO) || (ivideo->chip >= SIS_330)) {
                 	inSISIDXREG(SISSR, 0x38, temp);
-			if(temp & 0x01) ivideo.vbflags |= TV_PAL;
-			else		ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x01) ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
 	    	} else {
 	        	inSISIDXREG(SISCR, 0x79, temp);
-			if(temp & 0x20)	ivideo.vbflags |= TV_PAL;
-			else		ivideo.vbflags |= TV_NTSC;
+			if(temp & 0x20)	ivideo->vbflags |= TV_PAL;
+			else		ivideo->vbflags |= TV_NTSC;
 	    	}
-	}
+	    }
+	} 
 
 	/* Copy forceCRT1 option to CRT1off if option is given */
-    	if(sisfb_forcecrt1 != -1) {
-    		if(sisfb_forcecrt1) sisfb_crt1off = 0;
-		else                sisfb_crt1off = 1;
+    	if(ivideo->sisfb_forcecrt1 != -1) {
+    	   ivideo->sisfb_crt1off = (ivideo->sisfb_forcecrt1) ? 0 : 1;
     	}
-
 }
 
-static void __devinit sisfb_get_VB_type(void)
+static void __devinit sisfb_get_VB_type(struct sis_video_info *ivideo)
 {
-	u8 vb_chipid;
-	u8 reg;
 	char stdstr[]    = "sisfb: Detected";
 	char bridgestr[] = "video bridge";
-	char lvdsstr[]   = "LVDS transmitter";
-  	char chrstr[]    = "Chrontel TV encoder";
-	
-	ivideo.hasVB = HASVB_NONE;
-	sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-	sishw_ext.Is301BDH = FALSE;
+	u8 vb_chipid;
+	u8 reg;
 
 	inSISIDXREG(SISPART4, 0x00, vb_chipid);
-	switch (vb_chipid) {
-	   case 0x01:
-		ivideo.hasVB = HASVB_301;
+	switch(vb_chipid) {
+	case 0x01:
 		inSISIDXREG(SISPART4, 0x01, reg);
 		if(reg < 0xb0) {
-			ivideo.vbflags |= VB_301;
-			sishw_ext.ujVBChipID = VB_CHIP_301;
+			ivideo->vbflags |= VB_301;
 			printk(KERN_INFO "%s SiS301 %s\n", stdstr, bridgestr);
 		} else if(reg < 0xc0) {
-		 	ivideo.vbflags |= VB_301B;
-			sishw_ext.ujVBChipID = VB_CHIP_301B;
+		 	ivideo->vbflags |= VB_301B;
 			inSISIDXREG(SISPART4,0x23,reg);
 			if(!(reg & 0x02)) {
-			   sishw_ext.Is301BDH = TRUE;
-			   ivideo.vbflags |= VB_30xBDH;
+			   ivideo->vbflags |= VB_30xBDH;
 			   printk(KERN_INFO "%s SiS301B-DH %s\n", stdstr, bridgestr);
 			} else {
 			   printk(KERN_INFO "%s SiS301B %s\n", stdstr, bridgestr);
 			}
 		} else if(reg < 0xd0) {
-		 	ivideo.vbflags |= VB_301C;
-			sishw_ext.ujVBChipID = VB_CHIP_301C;
+		 	ivideo->vbflags |= VB_301C;
 			printk(KERN_INFO "%s SiS301C %s\n", stdstr, bridgestr);
 		} else if(reg < 0xe0) {
-			ivideo.vbflags |= VB_301LV;
-			sishw_ext.ujVBChipID = VB_CHIP_301LV;
+			ivideo->vbflags |= VB_301LV;
 			printk(KERN_INFO "%s SiS301LV %s\n", stdstr, bridgestr);
 		} else if(reg <= 0xe1) {
 		        inSISIDXREG(SISPART4,0x39,reg);
 			if(reg == 0xff) {
-			   ivideo.vbflags |= VB_302LV;
-			   sishw_ext.ujVBChipID = VB_CHIP_302LV;
+			   ivideo->vbflags |= VB_302LV;
 			   printk(KERN_INFO "%s SiS302LV %s\n", stdstr, bridgestr);
 			} else {
-			   ivideo.vbflags |= VB_302ELV;
-			   sishw_ext.ujVBChipID = VB_CHIP_302ELV;
+			   ivideo->vbflags |= VB_301C;
+			   printk(KERN_INFO "%s SiS301C(P4) %s\n", stdstr, bridgestr);
+#if 0			
+			   ivideo->vbflags |= VB_302ELV;
 			   printk(KERN_INFO "%s SiS302ELV %s\n", stdstr, bridgestr);
+#endif			   
 			}
 		}
 		break;
-	   case 0x02:
-		ivideo.hasVB = HASVB_302;
-		ivideo.vbflags |= VB_302B;
-		sishw_ext.ujVBChipID = VB_CHIP_302B;
+	case 0x02:
+		ivideo->vbflags |= VB_302B;
 		printk(KERN_INFO "%s SiS302B %s\n", stdstr, bridgestr);
 		break;
 	}
 
-	if((!(ivideo.vbflags & VB_VIDEOBRIDGE)) && (ivideo.chip != SIS_300)) {
-		inSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR37, reg);
+	if((!(ivideo->vbflags & VB_VIDEOBRIDGE)) && (ivideo->chip != SIS_300)) {
+		inSISIDXREG(SISCR, 0x37, reg);
 		reg &= SIS_EXTERNAL_CHIP_MASK;
 		reg >>= 1;
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
 #ifdef CONFIG_FB_SIS_300
-			switch (reg) {
+			switch(reg) {
 			   case SIS_EXTERNAL_CHIP_LVDS:
-				ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 			   case SIS_EXTERNAL_CHIP_TRUMPION:
-				ivideo.hasVB = HASVB_TRUMPION;
-				ivideo.vbflags |= VB_TRUMPION;
-				printk(KERN_INFO "%s Trumpion LCD scaler\n", stdstr);
+				ivideo->vbflags |= VB_TRUMPION;
 				break;
 			   case SIS_EXTERNAL_CHIP_CHRONTEL:
-				ivideo.hasVB = HASVB_CHRONTEL;
-				ivideo.vbflags |= VB_CHRONTEL;
-				printk(KERN_INFO "%s %s\n", stdstr, chrstr);
+				ivideo->vbflags |= VB_CHRONTEL;
 				break;
 			   case SIS_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 1;
 #endif
-		} else if(ivideo.chip < SIS_661) {
+		} else if(ivideo->chip < SIS_661) {
 #ifdef CONFIG_FB_SIS_315
 			switch (reg) {
 	 	   	   case SIS310_EXTERNAL_CHIP_LVDS:
-				ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 		   	   case SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL:
-				ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
 #endif
-		} else if(ivideo.chip >= SIS_661) {
+		} else if(ivideo->chip >= SIS_661) {
 #ifdef CONFIG_FB_SIS_315
 			inSISIDXREG(SISCR, 0x38, reg);
 			reg >>= 5;
 			switch(reg) {
 			   case 0x02:
-			   	ivideo.hasVB = HASVB_LVDS;
-				ivideo.vbflags |= VB_LVDS;
-				printk(KERN_INFO "%s %s\n", stdstr, lvdsstr);
+				ivideo->vbflags |= VB_LVDS;
 				break;
 			   case 0x03:
-			   	ivideo.hasVB = HASVB_LVDS_CHRONTEL;
-				ivideo.vbflags |= (VB_LVDS | VB_CHRONTEL);
-				printk(KERN_INFO "%s %s and %s\n", stdstr, lvdsstr, chrstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CHRONTEL);
 				break;
 			   case 0x04:
-			        ivideo.hasVB = HASVB_NONE;
-				ivideo.vbflags |= (VB_LVDS | VB_CONEXANT);
-				printk(KERN_INFO "%s Conexant video bridge\n", stdstr);
+				ivideo->vbflags |= (VB_LVDS | VB_CONEXANT);
 				break;
 			}
+			if(ivideo->vbflags & VB_CHRONTEL) ivideo->chronteltype = 2;
 #endif
 		}
-
+		if(ivideo->vbflags & VB_LVDS) {
+		   printk(KERN_INFO "%s LVDS transmitter\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_TRUMPION) {
+		   printk(KERN_INFO "%s Trumpion Zurac LCD scaler\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_CHRONTEL) {
+		   printk(KERN_INFO "%s Chrontel TV encoder\n", stdstr);
+		}
+		if(ivideo->vbflags & VB_CONEXANT) {
+		   printk(KERN_INFO "%s Conexant external device\n", stdstr);
+		}
 	}
 	
-	if(ivideo.vbflags & VB_SISBRIDGE) {
-		SiS_Sense30x();
-	} else if(ivideo.vbflags & VB_CHRONTEL) {
-		SiS_SenseCh();
+	if(ivideo->vbflags & VB_SISBRIDGE) {
+		SiS_Sense30x(ivideo);
+	} else if(ivideo->vbflags & VB_CHRONTEL) {
+		SiS_SenseCh(ivideo);
 	}
-
 }
 
 /* ------------------ Sensing routines ------------------ */
 
-static BOOLEAN __devinit sisfb_test_DDC1(void)
+static BOOLEAN __devinit sisfb_test_DDC1(struct sis_video_info *ivideo)
 {
     unsigned short old;
     int count = 48;
 
-    old = SiS_ReadDDC1Bit(&SiS_Pr);
+    old = SiS_ReadDDC1Bit(&ivideo->SiS_Pr);
     do {
-       if(old != SiS_ReadDDC1Bit(&SiS_Pr)) break;
+       	if(old != SiS_ReadDDC1Bit(&ivideo->SiS_Pr)) break;
     } while(count--);
     return (count == -1) ? FALSE : TRUE;
 }
 
-static void __devinit sisfb_sense_crt1(void)
+static void __devinit sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    unsigned char SR1F, CR63=0, CR17;
-    unsigned short temp = 0xffff;
-    int i;
     BOOLEAN mustwait = FALSE;
+    u8  SR1F, CR17;
+#ifdef CONFIG_FB_SIS_315        
+    u8  CR63=0;
+#endif        
+    u16 temp = 0xffff;
+    int i;
 
     inSISIDXREG(SISSR,0x1F,SR1F);
     orSISIDXREG(SISSR,0x1F,0x04);
     andSISIDXREG(SISSR,0x1F,0x3F);
     if(SR1F & 0xc0) mustwait = TRUE;
 
-    if(ivideo.sisvga_engine == SIS_315_VGA) {
-       inSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,CR63);
+#ifdef CONFIG_FB_SIS_315    
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       inSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,CR63);
        CR63 &= 0x40;
-       andSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF);
+       andSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF);
     }
+#endif    
 
     inSISIDXREG(SISCR,0x17,CR17);
     CR17 &= 0x80;
@@ -2728,25 +2604,46 @@ static void __devinit sisfb_sense_crt1(v
     }
 
     if(mustwait) {
-       for(i=0; i < 10; i++) sisfbwaitretracecrt1();
+       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
     }
+    
+#ifdef CONFIG_FB_SIS_315    
+    if(ivideo->chip >= SIS_330) {
+       andSISIDXREG(SISCR,0x32,~0x20);
+       if(ivideo->chip >= SIS_340) {
+          outSISIDXREG(SISCR, 0x57, 0x4a);
+       } else {
+          outSISIDXREG(SISCR, 0x57, 0x5f);
+       }
+       orSISIDXREG(SISCR, 0x53, 0x02);
+       while((inSISREG(SISINPSTAT)) & 0x01)    break;
+       while(!((inSISREG(SISINPSTAT)) & 0x01)) break;
+       if((inSISREG(SISMISCW)) & 0x10) temp = 1;
+       andSISIDXREG(SISCR, 0x53, 0xfd);
+       andSISIDXREG(SISCR, 0x57, 0x00);  
+    }
+#endif    
+    
+    if(temp == 0xffff) {
+       i = 3;
+       do {
+          temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine, 0, 0, NULL);
+       } while(((temp == 0) || (temp == 0xffff)) && i--);
 
-    i = 3;
-    do {
-       temp = SiS_HandleDDC(&SiS_Pr, ivideo.vbflags, ivideo.sisvga_engine, 0, 0, NULL);
-    } while(((temp == 0) || (temp == 0xffff)) && i--);
-
-    if((temp == 0) || (temp == 0xffff)) {
-       if(sisfb_test_DDC1()) temp = 1;
+       if((temp == 0) || (temp == 0xffff)) {
+          if(sisfb_test_DDC1(ivideo)) temp = 1;
+       }
     }
 
     if((temp) && (temp != 0xffff)) {
        orSISIDXREG(SISCR,0x32,0x20);
     }
 
-    if(ivideo.sisvga_engine == SIS_315_VGA) {
-       setSISIDXREG(SISCR,SiS_Pr.SiS_MyCR63,0xBF,CR63);
+#ifdef CONFIG_FB_SIS_315    
+    if(ivideo->sisvga_engine == SIS_315_VGA) {
+       setSISIDXREG(SISCR,ivideo->SiS_Pr.SiS_MyCR63,0xBF,CR63);
     }
+#endif    
 
     setSISIDXREG(SISCR,0x17,0x7F,CR17);
 
@@ -2754,216 +2651,205 @@ static void __devinit sisfb_sense_crt1(v
 }
 
 /* Determine and detect attached devices on SiS30x */
-static int __devinit SISDoSense(int tempbl, int tempbh, int tempcl, int tempch)
+static int __devinit SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
-    int temp;
+    int temp, mytest, result, i, j;
+    
+    for(j = 0; j < 10; j++) {
+       result = 0;
+       for(i = 0; i < 3; i++) {
+          mytest = test;
+          outSISIDXREG(SISPART4,0x11,(type & 0x00ff));
+          temp = (type >> 8) | (mytest & 0x00ff);
+          setSISIDXREG(SISPART4,0x10,0xe0,temp);
+          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
+          mytest >>= 8;
+          mytest &= 0x7f;
+          inSISIDXREG(SISPART4,0x03,temp);
+          temp ^= 0x0e;
+          temp &= mytest;
+          if(temp == mytest) result++;
+#if 1
+	  outSISIDXREG(SISPART4,0x11,0x00);
+	  andSISIDXREG(SISPART4,0x10,0xe0);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
+#endif
+       }
+       if((result == 0) || (result >= 2)) break;
+    }
+    return(result);
+}
 
-    outSISIDXREG(SISPART4,0x11,tempbl);
-    temp = tempbh | tempcl;
-    setSISIDXREG(SISPART4,0x10,0xe0,temp);
-    SiS_DDC2Delay(&SiS_Pr, 0x1000);
-    tempch &= 0x7f;
-    inSISIDXREG(SISPART4,0x03,temp);
-    temp ^= 0x0e;
-    temp &= tempch;
-    return((temp == tempch));
-}
-
-static void __devinit SiS_Sense30x(void)
-{
-  u8 backupP4_0d,backupP2_00;
-  u8 svhs_bl, svhs_bh;
-  u8 svhs_cl, svhs_ch;
-  u8 cvbs_bl, cvbs_bh;
-  u8 cvbs_cl, cvbs_ch;
-  u8 vga2_bl, vga2_bh;
-  u8 vga2_cl, vga2_ch;
-  int myflag, result, haveresult, i, j;
-  char stdstr[] = "sisfb: Detected";
-  char tvstr[]  = "TV connected to";
-
-  inSISIDXREG(SISPART4,0x0d,backupP4_0d);
-  outSISIDXREG(SISPART4,0x0d,(backupP4_0d | 0x04));
-
-  inSISIDXREG(SISPART2,0x00,backupP2_00);
-  outSISIDXREG(SISPART2,0x00,(backupP2_00 | 0x1c));
-
-  if(ivideo.sisvga_engine == SIS_300_VGA) {
-
-	if(ivideo.vbflags & (VB_301B|VB_301C|VB_302B|VB_301LV|VB_302LV)) {
-	   	vga2_bh = 0x01; vga2_bl = 0x90;
-	   	svhs_bh = 0x01; svhs_bl = 0x6b;
-	   	cvbs_bh = 0x01; cvbs_bl = 0x74;
-	} else {
-		vga2_bh = 0x00; vga2_bl = 0xd1;
-        	svhs_bh = 0x00; svhs_bl = 0xb9;
-		cvbs_bh = 0x00; cvbs_bl = 0xb3;
-		inSISIDXREG(SISPART4,0x01,myflag);
-	        if(myflag & 0x04) {
-	           vga2_bh = 0x00; vga2_bl = 0xfd;
-	           svhs_bh = 0x00; svhs_bl = 0xdd;
-	      	   cvbs_bh = 0x00; cvbs_bl = 0xee;
-	        }
-	}
+static void __devinit SiS_Sense30x(struct sis_video_info *ivideo)
+{
+    u8  backupP4_0d,backupP2_00,backupP2_4d,backupSR_1e,biosflag=0;
+    u16 svhs=0, svhs_c=0;
+    u16 cvbs=0, cvbs_c=0;
+    u16 vga2=0, vga2_c=0;
+    int myflag, result;
+    char stdstr[] = "sisfb: Detected";
+    char tvstr[]  = "TV connected to";
+  
+    if(ivideo->vbflags & VB_301) {
+       svhs = 0x00b9; cvbs = 0x00b3; vga2 = 0x00d1;
+       inSISIDXREG(SISPART4,0x01,myflag);
+       if(myflag & 0x04) {
+	  svhs = 0x00dd; cvbs = 0x00ee; vga2 = 0x00fd;
+       }
+    } else if(ivideo->vbflags & (VB_301B | VB_302B)) {
+       svhs = 0x016b; cvbs = 0x0174; vga2 = 0x0190;
+    } else if(ivideo->vbflags & (VB_301LV | VB_302LV)) {
+       svhs = 0x0200; cvbs = 0x0100;
+    } else if(ivideo->vbflags & (VB_301C | VB_302ELV)) {
+       svhs = 0x016b; cvbs = 0x0110; vga2 = 0x0190;
+    } else return;
+
+    vga2_c = 0x0e08; svhs_c = 0x0404; cvbs_c = 0x0804;
+    if(ivideo->vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
+       svhs_c = 0x0408; cvbs_c = 0x0808;
+    }
+    biosflag = 2;
 
-	vga2_ch = 0x0e;	vga2_cl = 0x08;
-	svhs_ch = 0x04;	svhs_cl = 0x04;
-	cvbs_ch = 0x08; cvbs_cl = 0x04;
-	if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
-	   	vga2_bh = 0x00; vga2_bl = 0x00;
-	   	vga2_ch = 0x00; vga2_cl = 0x00;
-	}
-	if(ivideo.chip == SIS_300) {
-	   inSISIDXREG(SISSR,0x3b,myflag);
-	   if(!(myflag & 0x01)) {
-	      	vga2_bh = 0x00; vga2_bl = 0x00;
-	      	vga2_ch = 0x00; vga2_cl = 0x00;
-	   }
-	}
+    if(ivideo->chip == SIS_300) {
+       inSISIDXREG(SISSR,0x3b,myflag);
+       if(!(myflag & 0x01)) vga2 = vga2_c = 0;
+    }
+  
+    inSISIDXREG(SISSR,0x1e,backupSR_1e);
+    orSISIDXREG(SISSR,0x1e,0x20);
+    
+    inSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    if(ivideo->vbflags & VB_301C) {
+       setSISIDXREG(SISPART4,0x0d,~0x07,0x01);
+    } else {
+       orSISIDXREG(SISPART4,0x0d,0x04);
+    }
+    SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
 
-  } else {
-
-	if(ivideo.vbflags & (VB_301B|VB_302B)) {
-		vga2_bh = 0x01; vga2_bl = 0x90;
-		svhs_bh = 0x01; svhs_bl = 0x6b;
-		cvbs_bh = 0x01; cvbs_bl = 0x74;
-	} else if(ivideo.vbflags & (VB_301C|VB_302ELV)) {
-	      	vga2_bh = 0x01; vga2_bl = 0x90;
-	      	svhs_bh = 0x01; svhs_bl = 0x6b;
-	      	cvbs_bh = 0x01; cvbs_bl = 0x10;
-	} else if(ivideo.vbflags & (VB_301LV|VB_302LV)) {
-	      	vga2_bh = 0x00; vga2_bl = 0x00;
-	      	svhs_bh = 0x02; svhs_bl = 0x00;
-	      	cvbs_bh = 0x01; cvbs_bl = 0x00;
-	} else {
-		vga2_bh = 0x00; vga2_bl = 0xd1;
-        	svhs_bh = 0x00; svhs_bl = 0xb9;
-		cvbs_bh = 0x00; cvbs_bl = 0xb3;
-		inSISIDXREG(SISPART4,0x01,myflag);
-	        if(myflag & 0x04) {
-	           vga2_bh = 0x00; vga2_bl = 0xfd;
-	           svhs_bh = 0x00; svhs_bl = 0xdd;
-	           cvbs_bh = 0x00; cvbs_bl = 0xee;
-	        }
-	}
+    inSISIDXREG(SISPART2,0x00,backupP2_00);
+    outSISIDXREG(SISPART2,0x00,((backupP2_00 | 0x1c) & 0xfc));
 
-	if(ivideo.vbflags & (VB_301LV|VB_302LV|VB_302ELV)) {
-	   vga2_bh = 0x00; vga2_bl = 0x00;
-	   vga2_ch = 0x00; vga2_cl = 0x00;
-	   svhs_ch = 0x04; svhs_cl = 0x08;
-	   cvbs_ch = 0x08; cvbs_cl = 0x08;
-	} else {
-	   vga2_ch = 0x0e; vga2_cl = 0x08;
-	   svhs_ch = 0x04; svhs_cl = 0x04;
-	   cvbs_ch = 0x08; cvbs_cl = 0x04;
-	}
-    } 
-
-    if(vga2_ch || vga2_cl || vga2_bh || vga2_bl) {
-       haveresult = 0;
-       for(j = 0; j < 10; j++) {
-          result = 0;
-          for(i = 0; i < 3; i++) {
-             if(SISDoSense(vga2_bl, vga2_bh, vga2_cl, vga2_ch))
-	        result++;
-          }
-	  if((result == 0) || (result >= 2)) break;
-       }
-       if(result) {
-          printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
-	  orSISIDXREG(SISCR, 0x32, 0x10);
-       } else {
-	  andSISIDXREG(SISCR, 0x32, ~0x10);
-       }
+    inSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    if(ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV)) {
+       outSISIDXREG(SISPART2,0x4d,(backupP2_4d & ~0x10));
     }
-
-    haveresult = 0;
-    for(j = 0; j < 10; j++) {
-       result = 0;
-       for(i = 0; i < 3; i++) {
-          if(SISDoSense(svhs_bl, svhs_bh, svhs_cl, svhs_ch))
-	        result++;
+    
+    if(!(ivideo->vbflags & VB_301C)) {
+       SISDoSense(ivideo, 0, 0);
+    }
+  
+    andSISIDXREG(SISCR, 0x32, ~0x14);
+  
+    if(vga2_c || vga2) {
+       if(SISDoSense(ivideo, vga2, vga2_c)) {
+          if(biosflag & 0x01) {
+	     printk(KERN_INFO "%s %s SCART output\n", stdstr, tvstr);  
+	     orSISIDXREG(SISCR, 0x32, 0x04);
+	  } else {
+	     printk(KERN_INFO "%s secondary VGA connection\n", stdstr);
+	     orSISIDXREG(SISCR, 0x32, 0x10);
+	  }
        }
-       if((result == 0) || (result >= 2)) break;
     }
-    if(result) {
-        printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
-	ivideo.vbflags |= TV_SVIDEO;
-	orSISIDXREG(SISCR, 0x32, 0x02);
-	andSISIDXREG(SISCR, 0x32, ~0x05);
+  
+    andSISIDXREG(SISCR, 0x32, 0x3f);
+    
+    if(ivideo->vbflags & VB_301C) {
+       orSISIDXREG(SISPART4,0x0d,0x04);
     }
 
-    if(!result) {
+    if((ivideo->sisvga_engine == SIS_315_VGA) && 
+       (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV|VB_302ELV))) {
+       outSISIDXREG(SISPART2,0x4d,(backupP2_4d | 0x10));
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x2000);
+       if((result = SISDoSense(ivideo, svhs, 0x0604))) {
+          if((result = SISDoSense(ivideo, cvbs, 0x0804))) {
+	     printk(KERN_INFO "%s %s YPbPr component output\n", stdstr, tvstr);  
+	     orSISIDXREG(SISCR,0x32,0x80);
+	  }
+       }
+       outSISIDXREG(SISPART2,0x4d,backupP2_4d);
+    }
+  
+    andSISIDXREG(SISCR, 0x32, ~0x03);
 
-	haveresult = 0;
-       	for(j = 0; j < 10; j++) {
-           result = 0;
-           for(i = 0; i < 3; i++) {
-              if(SISDoSense(cvbs_bl, cvbs_bh, cvbs_cl, cvbs_ch))
-	        result++;
-           }
-           if((result == 0) || (result >= 2)) break;
-        }
-	if(result) {
-	    printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
-	    ivideo.vbflags |= TV_AVIDEO;
-	    orSISIDXREG(SISCR, 0x32, 0x01);
-	    andSISIDXREG(SISCR, 0x32, ~0x06);
-	} else {
-	    andSISIDXREG(SISCR, 0x32, ~0x07);
-	}
+    if(!(ivideo->vbflags & TV_YPBPR)) {
+       if((result = SISDoSense(ivideo, svhs, svhs_c))) {
+          printk(KERN_INFO "%s %s SVIDEO output\n", stdstr, tvstr);
+          orSISIDXREG(SISCR, 0x32, 0x02);
+       }
+       if((biosflag & 0x02) || (!result)) {
+          if(SISDoSense(ivideo, cvbs, cvbs_c)) {
+	     printk(KERN_INFO "%s %s COMPOSITE output\n", stdstr, tvstr);
+	     orSISIDXREG(SISCR, 0x32, 0x01);
+          }
+       }
     }
-    SISDoSense(0, 0, 0, 0);
+
+    SISDoSense(ivideo, 0, 0);
 
     outSISIDXREG(SISPART2,0x00,backupP2_00);
     outSISIDXREG(SISPART4,0x0d,backupP4_0d);
+    outSISIDXREG(SISSR,0x1e,backupSR_1e);
+    
+    if(ivideo->vbflags & VB_301C) {
+       inSISIDXREG(SISPART2,0x00,biosflag);
+       if(biosflag & 0x20) {
+          for(myflag = 2; myflag > 0; myflag--) {
+	     biosflag ^= 0x20;
+	     outSISIDXREG(SISPART2,0x00,biosflag);
+	  }
+       }
+    }
+    
+    outSISIDXREG(SISPART2,0x00,backupP2_00);
 }
 
 /* Determine and detect attached TV's on Chrontel */
-static void __devinit SiS_SenseCh(void)
+static void __devinit SiS_SenseCh(struct sis_video_info *ivideo)
 {
-   u8 temp1, temp2;
+    u8 temp1, temp2;
 #ifdef CONFIG_FB_SIS_300
-   unsigned char test[3];
-   int i;
+    unsigned char test[3];
+    int i;
 #endif
-   char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
+    char stdstr[] = "sisfb: Chrontel: Detected TV connected to";
 
-   if(ivideo.chip < SIS_315H) {
+    if(ivideo->chip < SIS_315H) {
 
 #ifdef CONFIG_FB_SIS_300
-       SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
-       SiS_SetChrontelGPIO(&SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
-       SiS_DDC2Delay(&SiS_Pr, 1000);
-       temp1 = SiS_GetCH700x(&SiS_Pr, 0x25);
+       ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 1;		/* Chrontel 700x */
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x9c);	/* Set general purpose IO for Chrontel communication */
+       SiS_DDC2Delay(&ivideo->SiS_Pr, 1000);
+       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
        /* See Chrontel TB31 for explanation */
-       temp2 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
        if(((temp2 & 0x07) == 0x01) || (temp2 & 0x04)) {
-	  SiS_SetCH700x(&SiS_Pr, 0x0b0e);
-	  SiS_DDC2Delay(&SiS_Pr, 300);
+	  SiS_SetCH700x(&ivideo->SiS_Pr, 0x0b0e);
+	  SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
        }
-       temp2 = SiS_GetCH700x(&SiS_Pr, 0x25);
+       temp2 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x25);
        if(temp2 != temp1) temp1 = temp2;
 
        if((temp1 >= 0x22) && (temp1 <= 0x50)) {
 	   /* Read power status */
-	   temp1 = SiS_GetCH700x(&SiS_Pr, 0x0e);
+	   temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0e);
 	   if((temp1 & 0x03) != 0x03) {
      	        /* Power all outputs */
-		SiS_SetCH700x(&SiS_Pr, 0x0B0E);
-		SiS_DDC2Delay(&SiS_Pr, 300);
+		SiS_SetCH700x(&ivideo->SiS_Pr, 0x0B0E);
+		SiS_DDC2Delay(&ivideo->SiS_Pr, 300);
 	   }
 	   /* Sense connected TV devices */
 	   for(i = 0; i < 3; i++) {
-	       SiS_SetCH700x(&SiS_Pr, 0x0110);
-	       SiS_DDC2Delay(&SiS_Pr, 0x96);
-	       SiS_SetCH700x(&SiS_Pr, 0x0010);
-	       SiS_DDC2Delay(&SiS_Pr, 0x96);
-	       temp1 = SiS_GetCH700x(&SiS_Pr, 0x10);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x0110);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       SiS_SetCH700x(&ivideo->SiS_Pr, 0x0010);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	       temp1 = SiS_GetCH700x(&ivideo->SiS_Pr, 0x10);
 	       if(!(temp1 & 0x08))       test[i] = 0x02;
 	       else if(!(temp1 & 0x02))  test[i] = 0x01;
 	       else                      test[i] = 0;
-	       SiS_DDC2Delay(&SiS_Pr, 0x96);
+	       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
 	   }
 
 	   if(test[0] == test[1])      temp1 = test[0];
@@ -2976,369 +2862,211 @@ static void __devinit SiS_SenseCh(void)
 	   }
 	   if(temp1 == 0x02) {
 		printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-		ivideo.vbflags |= TV_SVIDEO;
+		ivideo->vbflags |= TV_SVIDEO;
 		orSISIDXREG(SISCR, 0x32, 0x02);
 		andSISIDXREG(SISCR, 0x32, ~0x05);
 	   } else if (temp1 == 0x01) {
 		printk(KERN_INFO "%s CVBS output\n", stdstr);
-		ivideo.vbflags |= TV_AVIDEO;
+		ivideo->vbflags |= TV_AVIDEO;
 		orSISIDXREG(SISCR, 0x32, 0x01);
 		andSISIDXREG(SISCR, 0x32, ~0x06);
 	   } else {
- 		SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
+ 		SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
 		andSISIDXREG(SISCR, 0x32, ~0x07);
 	   }
        } else if(temp1 == 0) {
-	  SiS_SetCH70xxANDOR(&SiS_Pr, 0x010E,0xF8);
+	  SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, 0x010E,0xF8);
 	  andSISIDXREG(SISCR, 0x32, ~0x07);
        }
        /* Set general purpose IO for Chrontel communication */
-       SiS_SetChrontelGPIO(&SiS_Pr, 0x00);
+       SiS_SetChrontelGPIO(&ivideo->SiS_Pr, 0x00);
 #endif
 
-   } else {
+    } else {
 
 #ifdef CONFIG_FB_SIS_315
-	SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
-        temp1 = SiS_GetCH701x(&SiS_Pr, 0x49);
-	SiS_SetCH701x(&SiS_Pr, 0x2049);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
+	ivideo->SiS_Pr.SiS_IF_DEF_CH70xx = 2;		/* Chrontel 7019 */
+        temp1 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, 0x2049);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
 	temp2 |= 0x01;
-	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
 	temp2 ^= 0x01;
-	SiS_SetCH701x(&SiS_Pr, (temp2 << 8) | 0x20);
-	SiS_DDC2Delay(&SiS_Pr, 0x96);
-	temp2 = SiS_GetCH701x(&SiS_Pr, 0x20);
-	SiS_SetCH701x(&SiS_Pr, (temp1 << 8) | 0x49);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp2 << 8) | 0x20);
+	SiS_DDC2Delay(&ivideo->SiS_Pr, 0x96);
+	temp2 = SiS_GetCH701x(&ivideo->SiS_Pr, 0x20);
+	SiS_SetCH701x(&ivideo->SiS_Pr, (temp1 << 8) | 0x49);
         temp1 = 0;
 	if(temp2 & 0x02) temp1 |= 0x01;
 	if(temp2 & 0x10) temp1 |= 0x01;
 	if(temp2 & 0x04) temp1 |= 0x02;
 	if( (temp1 & 0x01) && (temp1 & 0x02) ) temp1 = 0x04;
 	switch(temp1) {
-	case 0x01:
-	     printk(KERN_INFO "%s CVBS output\n", stdstr);
-	     ivideo.vbflags |= TV_AVIDEO;
-	     orSISIDXREG(SISCR, 0x32, 0x01);
-	     andSISIDXREG(SISCR, 0x32, ~0x06);
-             break;
-	case 0x02:
-	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
-	     ivideo.vbflags |= TV_SVIDEO;
-	     orSISIDXREG(SISCR, 0x32, 0x02);
-	     andSISIDXREG(SISCR, 0x32, ~0x05);
-             break;
-	case 0x04:
-	     printk(KERN_INFO "%s SCART output\n", stdstr);
-	     orSISIDXREG(SISCR, 0x32, 0x04);
-	     andSISIDXREG(SISCR, 0x32, ~0x03);
-             break;
-	default:
-	     andSISIDXREG(SISCR, 0x32, ~0x07);
-	}
-#endif
-
-   }
-}
-
-
-/* ------------------------ Heap routines -------------------------- */
-
-static int __devinit
-sisfb_heap_init(void)
-{
-	SIS_OH *poh;
-	u8 temp=0;
-#ifdef CONFIG_FB_SIS_315
-	int            agp_enabled = 1;
-	u32            agp_size;
-	unsigned long  *cmdq_baseport = 0;
-	unsigned long  *read_port = 0;
-	unsigned long  *write_port = 0;
-	SIS_CMDTYPE    cmd_type;
-#ifndef AGPOFF
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-	struct agp_kern_info  *agp_info;
-	struct agp_memory     *agp;
-#else
-	agp_kern_info  *agp_info;
-	agp_memory     *agp;
-#endif
-	unsigned long  agp_phys;
-#endif
-#endif
-/*     The heap start is either set manually using the "mem" parameter, or
- *     defaults as follows:
- *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
- *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
- *     -) If 4MB or less is available, let it start at 4MB.
- *     This is for avoiding a clash with X driver which uses the beginning
- *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
- *     in XF86Config-4.
- *     The heap start can also be specified by parameter "mem" when starting the sisfb
- *     driver. sisfb mem=1024 lets heap starts at 1MB, etc.
- *
- *     On the 315 and Xabre series, the default is a 1MB heap since DRI is not
- *     supported there.
- */
-     if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {
-        if(ivideo.sisvga_engine == SIS_300_VGA) {
-           if (ivideo.video_size > 0x1000000) {
-	        ivideo.heapstart = 0xc00000;
-	   } else if (ivideo.video_size > 0x800000) {
-	        ivideo.heapstart = 0x800000;
-	   } else {
-		ivideo.heapstart = 0x400000;
-	   }
-	} else {
-	   ivideo.heapstart = ivideo.video_size - 0x100000;
-	}
-     } else {
-           ivideo.heapstart = sisfb_mem * 1024;
-     }
-     sisfb_heap_start = (unsigned long) (ivideo.video_vbase + ivideo.heapstart);
-     printk(KERN_INFO "sisfb: Memory heap starting at %dK\n",
-     					(int)(ivideo.heapstart / 1024));
-
-     sisfb_heap_end = (unsigned long) ivideo.video_vbase + ivideo.video_size;
-     sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;
-
-#ifdef CONFIG_FB_SIS_315
-     if(ivideo.sisvga_engine == SIS_315_VGA) {
-        /* Now initialize the 315/330 series' command queue mode.
-	 * On 315, there are three queue modes available which
-	 * are chosen by setting bits 7:5 in SR26:
-	 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
-	 *    track of the queue, the FIFO, command parsing and so
-	 *    on. This is the one comparable to the 300 series.
-	 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
-	 *    have to do queue management himself. Register 0x85c4 will
-	 *    hold the location of the next free queue slot, 0x85c8
-	 *    is the "queue read pointer" whose way of working is
-	 *    unknown to me. Anyway, this mode would require a
-	 *    translation of the MMIO commands to some kind of
-	 *    accelerator assembly and writing these commands
-	 *    to the memory location pointed to by 0x85c4.
-	 *    We will not use this, as nobody knows how this
-	 *    "assembly" works, and as it would require a complete
-	 *    re-write of the accelerator code.
-	 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
-	 *    queue in AGP memory space.
-	 *
-	 * SR26 bit 4 is called "Bypass H/W queue".
-	 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
-	 * SR26 bit 0 resets the queue
-	 * Size of queue memory is encoded in bits 3:2 like this:
-	 *    00  (0x00)  512K
-	 *    01  (0x04)  1M
-	 *    10  (0x08)  2M
-	 *    11  (0x0C)  4M
-	 * The queue location is to be written to 0x85C0.
-	 *
-         */
-	cmdq_baseport = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE);
-	write_port    = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT);
-	read_port     = (unsigned long *)(ivideo.mmio_vbase + MMIO_QUEUE_READPORT);
-
-	DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
-
-	agp_size  = COMMAND_QUEUE_AREA_SIZE;
-
-#ifndef AGPOFF
-	if (sisfb_queuemode == AGP_CMD_QUEUE) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-		agp_info = vmalloc(sizeof(*agp_info));
-		memset((void*)agp_info, 0x00, sizeof(*agp_info));
-#else
-		agp_info = vmalloc(sizeof(agp_kern_info));
-		memset((void*)agp_info, 0x00, sizeof(agp_kern_info));
-#endif
-		agp_copy_info(agp_info);
-
-		agp_backend_acquire();
-
-		agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE/PAGE_SIZE,
-					  AGP_NORMAL_MEMORY);
-		if (agp == NULL) {
-			DPRINTK("sisfb: Allocating AGP buffer failed.\n");
-			agp_enabled = 0;
-		} else {
-			if (agp_bind_memory(agp, agp->pg_start) != 0) {
-				DPRINTK("sisfb: AGP: Failed to bind memory\n");
-				/* TODO: Free AGP memory here */
-				agp_enabled = 0;
-			} else {
-				agp_enable(0);
-			}
-		}
+	case 0x01:
+	     printk(KERN_INFO "%s CVBS output\n", stdstr);
+	     ivideo->vbflags |= TV_AVIDEO;
+	     orSISIDXREG(SISCR, 0x32, 0x01);
+	     andSISIDXREG(SISCR, 0x32, ~0x06);
+             break;
+	case 0x02:
+	     printk(KERN_INFO "%s SVIDEO output\n", stdstr);
+	     ivideo->vbflags |= TV_SVIDEO;
+	     orSISIDXREG(SISCR, 0x32, 0x02);
+	     andSISIDXREG(SISCR, 0x32, ~0x05);
+             break;
+	case 0x04:
+	     printk(KERN_INFO "%s SCART output\n", stdstr);
+	     orSISIDXREG(SISCR, 0x32, 0x04);
+	     andSISIDXREG(SISCR, 0x32, ~0x03);
+             break;
+	default:
+	     andSISIDXREG(SISCR, 0x32, ~0x07);
 	}
-#else
-	agp_enabled = 0;
 #endif
+    }
+}
 
-	/* Now select the queue mode */
+/* ------------------------ Heap routines -------------------------- */
 
-	if((agp_enabled) && (sisfb_queuemode == AGP_CMD_QUEUE)) {
-		cmd_type = AGP_CMD_QUEUE;
-		printk(KERN_INFO "sisfb: Using AGP queue mode\n");
-        } else if (sisfb_queuemode == VM_CMD_QUEUE) {
-		cmd_type = VM_CMD_QUEUE;
-		printk(KERN_INFO "sisfb: Using VRAM queue mode\n");
+static u32 __devinit
+sisfb_getheapstart(struct sis_video_info *ivideo)
+{	
+	u32 ret = ivideo->sisfb_parm_mem * 1024;
+	u32 max = ivideo->video_size - ivideo->hwcursor_size;
+	u32 def;
+	
+	/* Calculate heap start = end of memory for console
+	 * 
+	 * CCCCCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDHHHHQQQQQQQQQQ
+	 * C = console, D = heap, H = HWCursor, Q = cmd-queue
+	 * 
+	 * Basically given by "mem" parameter
+	 *
+	 * maximum = videosize - cmd_queue - hwcursor 
+	 *           (results in a heap of size 0)
+	 * default = SiS 300: depends on videosize 
+	 *           SiS 315/330: 32k below max   
+	 */
+	
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   max -= TURBO_QUEUE_AREA_SIZE;
+	   if(ivideo->video_size > 0x1000000) {
+	      def = 0xc00000;
+	   } else if(ivideo->video_size > 0x800000) {
+	      def = 0x800000;
+	   } else {
+	      def = 0x400000;
+	   }
 	} else {
-		printk(KERN_INFO "sisfb: Using MMIO queue mode\n");
-		cmd_type = MMIO_CMD;
-	}
-
-	switch (agp_size) {
-	   case 0x80000:
-		temp = SIS_CMD_QUEUE_SIZE_512k;
-		break;
-	   case 0x100000:
-		temp = SIS_CMD_QUEUE_SIZE_1M;
-		break;
-	   case 0x200000:
-		temp = SIS_CMD_QUEUE_SIZE_2M;
-		break;
-	   case 0x400000:
-		temp = SIS_CMD_QUEUE_SIZE_4M;
-		break;
+	   max -= COMMAND_QUEUE_AREA_SIZE;
+	   def = max - 0x8000;
 	}
+	
+        if((!ret) || (ret > max) || (ivideo->cardnumber != 0)) {
+	   ret = def;
+        } 
+	
+	return ret;
+}
 
-	switch (cmd_type) {
-	   case AGP_CMD_QUEUE:
-#ifndef AGPOFF
-		DPRINTK("sisfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
-			agp_info->aper_base, agp->physical, agp_size/1024);
-
-		agp_phys = agp_info->aper_base + agp->physical;
-
-		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, 0);
-		outSISIDXREG(SISCR,  IND_SIS_AGP_IO_PAD, SIS_AGP_2X);
-
-                outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		temp |= SIS_AGP_CMDQUEUE_ENABLE;
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
-
-		*cmdq_baseport = agp_phys;
-
-		ivideo.caps |= AGP_CMD_QUEUE_CAP;
-#endif
-		break;
-
-	   case VM_CMD_QUEUE:
-		sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		temp |= SIS_VRAM_CMDQUEUE_ENABLE;
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
-
-		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
-
-		ivideo.caps |= VM_CMD_QUEUE_CAP;
-
-		break;
-
-	   default:  /* MMIO */
-	   	sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
-
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		/* Set Auto_Correction bit */
-		temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
-		outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+static int __devinit
+sisfb_heap_init(struct sis_video_info *ivideo)
+{
+     SIS_OH *poh;
 
-		*cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE;
+     ivideo->heapstart = ivideo->sisfb_mem = sisfb_getheapstart(ivideo);
+     
+     ivideo->sisfb_heap_start = ivideo->video_vbase + ivideo->heapstart;
+     ivideo->sisfb_heap_end   = ivideo->video_vbase + ivideo->video_size;
+     
+     /* Initialize command queue (We use MMIO only) */
 
-		ivideo.caps |= MMIO_CMD_QUEUE_CAP;
+#ifdef CONFIG_FB_SIS_315
+     if(ivideo->sisvga_engine == SIS_315_VGA) {
+        u32 tempq = 0;
+	u8  temp = 0;
+	     
+        ivideo->sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
+
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, SIS_CMD_QUEUE_RESET);
+
+	tempq = MMIO_IN32(ivideo->mmio_vbase, MMIO_QUEUE_READPORT);
+	MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_WRITEPORT, tempq);
+
+	temp = SIS_CMD_QUEUE_SIZE_512k;
+	temp |= (SIS_MMIO_CMD_ENABLE | SIS_CMD_AUTO_CORR);
+	outSISIDXREG(SISSR, IND_SIS_CMDQUEUE_SET, temp);
+	
+	tempq = (u32)(ivideo->video_size - COMMAND_QUEUE_AREA_SIZE);
+	MMIO_OUT32(ivideo->mmio_vbase, MMIO_QUEUE_PHYBASE, tempq);
 
-		break;
-	}
-     } /* sisvga_engine = 315 */
+	ivideo->caps |= MMIO_CMD_QUEUE_CAP;
+     } 
 #endif
 
 #ifdef CONFIG_FB_SIS_300
-     if(ivideo.sisvga_engine == SIS_300_VGA) {
-  	    /* Now initialize TurboQueue. TB is always located at the very
-	     * top of the video RAM. */
-	    if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) {
-		unsigned int  tqueue_pos;
-		u8 tq_state;
-
-		tqueue_pos = (ivideo.video_size -
-		       TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
-
-		temp = (u8) (tqueue_pos & 0xff);
-
-		inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-		tq_state |= 0xf0;
-		tq_state &= 0xfc;
-		tq_state |= (u8) (tqueue_pos >> 8);
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
-
-		outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, temp);
-
-		ivideo.caps |= TURBO_QUEUE_CAP;
+     if(ivideo->sisvga_engine == SIS_300_VGA) {
+     	unsigned long tqueue_pos;
+	u8 tq_state;
+ 
+	ivideo->sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
+
+	tqueue_pos = (ivideo->video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024);
+
+	inSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
+	tq_state |= 0xf0;
+	tq_state &= 0xfc;
+	tq_state |= (u8)(tqueue_pos >> 8);
+	outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_SET, tq_state);
 
-		sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE;
-		sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE;
+	outSISIDXREG(SISSR, IND_SIS_TURBOQUEUE_ADR, (u8)(tqueue_pos & 0xff));
 
-	    }
+	ivideo->caps |= TURBO_QUEUE_CAP;
      }
 #endif
-     /* Now reserve memory for the HWCursor. It is always located at the very
-        top of the videoRAM, right below the TB memory area (if used). */
-     if(sisfb_heap_size >= ivideo.hwcursor_size) {
-		sisfb_heap_end -= ivideo.hwcursor_size;
-		sisfb_heap_size -= ivideo.hwcursor_size;
-		ivideo.hwcursor_vbase = sisfb_heap_end;
-
-		ivideo.caps |= HW_CURSOR_CAP;
-     }
-
-     sisfb_heap.poha_chain = NULL;
-     sisfb_heap.poh_freelist = NULL;
 
-     poh = sisfb_poh_new_node();
-
-     if(poh == NULL)  return 1;
+     /* Reserve memory for the HWCursor */
+     ivideo->sisfb_heap_end -= ivideo->hwcursor_size;
+     ivideo->hwcursor_vbase = ivideo->sisfb_heap_end;
+     ivideo->caps |= HW_CURSOR_CAP;
+     
+     ivideo->sisfb_heap_size = ivideo->sisfb_heap_end - ivideo->sisfb_heap_start;
+     
+     if(ivideo->cardnumber == 0) {
+      
+     	printk(KERN_INFO "sisfb: Memory heap starting at %dK, size %dK\n",
+     		(int)(ivideo->heapstart / 1024), (int)(ivideo->sisfb_heap_size / 1024));
+     
+	sisfb_heap.vinfo = ivideo;
 	
-     poh->poh_next = &sisfb_heap.oh_free;
-     poh->poh_prev = &sisfb_heap.oh_free;
-     poh->size = sisfb_heap_end - sisfb_heap_start + 1;
-     poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase;
-
-     DPRINTK("sisfb: Heap start:0x%p, end:0x%p, len=%dk\n",
-		(char *) sisfb_heap_start, (char *) sisfb_heap_end,
-		(unsigned int) poh->size / 1024);
-
-     DPRINTK("sisfb: First Node offset:0x%x, size:%dk\n",
-		(unsigned int) poh->offset, (unsigned int) poh->size / 1024);
-
-     sisfb_heap.oh_free.poh_next = poh;
-     sisfb_heap.oh_free.poh_prev = poh;
-     sisfb_heap.oh_free.size = 0;
-     sisfb_heap.max_freesize = poh->size;
+     	sisfb_heap.poha_chain = NULL;
+     	sisfb_heap.poh_freelist = NULL;
 
-     sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
-     sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
-     sisfb_heap.oh_used.size = SENTINEL;
+     	poh = sisfb_poh_new_node();
+     	if(poh == NULL) return 1;
+	
+     	poh->poh_next = &sisfb_heap.oh_free;
+     	poh->poh_prev = &sisfb_heap.oh_free;
+     	poh->size = ivideo->sisfb_heap_size;
+     	poh->offset = ivideo->heapstart;
+
+     	sisfb_heap.oh_free.poh_next = poh;
+     	sisfb_heap.oh_free.poh_prev = poh;
+     	sisfb_heap.oh_free.size = 0;
+     	sisfb_heap.max_freesize = poh->size;
+
+     	sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used;
+     	sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used;
+     	sisfb_heap.oh_used.size = SENTINEL;
+	
+     } else {
+     
+        printk(KERN_INFO "Skipped heap initialization for secondary cards\n");
+	
+     }
 
      return 0;
 }
@@ -3352,13 +3080,13 @@ sisfb_poh_new_node(void)
 	SIS_OH        *poh;
 
 	if(sisfb_heap.poh_freelist == NULL) {
-		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
+		poha = kmalloc(SIS_OH_ALLOC_SIZE, GFP_KERNEL);
 		if(!poha) return NULL;
 
 		poha->poha_next = sisfb_heap.poha_chain;
 		sisfb_heap.poha_chain = poha;
 
-		cOhs = (OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
+		cOhs = (SIS_OH_ALLOC_SIZE - sizeof(SIS_OHALLOC)) / sizeof(SIS_OH) + 1;
 
 		poh = &poha->aoh[0];
 		for(i = cOhs - 1; i != 0; i--) {
@@ -3377,14 +3105,14 @@ sisfb_poh_new_node(void)
 }
 
 static SIS_OH *
-sisfb_poh_allocate(unsigned long size)
+sisfb_poh_allocate(u32 size)
 {
 	SIS_OH *pohThis;
 	SIS_OH *pohRoot;
 	int     bAllocated = 0;
 
 	if(size > sisfb_heap.max_freesize) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
@@ -3400,7 +3128,7 @@ sisfb_poh_allocate(unsigned long size)
 	}
 
 	if(!bAllocated) {
-		DPRINTK("sisfb: Can't allocate %dk size on offscreen\n",
+		DPRINTK("sisfb: Can't allocate %dk video memory\n",
 			(unsigned int) size / 1024);
 		return (NULL);
 	}
@@ -3458,15 +3186,15 @@ sisfb_insert_node(SIS_OH *pohList, SIS_O
 }
 
 static SIS_OH *
-sisfb_poh_free(unsigned long base)
+sisfb_poh_free(u32 base)
 {
 	SIS_OH *pohThis;
 	SIS_OH *poh_freed;
 	SIS_OH *poh_prev;
 	SIS_OH *poh_next;
-	unsigned long ulUpper;
-	unsigned long ulLower;
-	int foundNode = 0;
+	u32     ulUpper;
+	u32     ulLower;
+	int     foundNode = 0;
 
 	poh_freed = sisfb_heap.oh_used.poh_next;
 
@@ -3479,7 +3207,7 @@ sisfb_poh_free(unsigned long base)
 		poh_freed = poh_freed->poh_next;
 	}
 
-	if(!foundNode)  return(NULL);
+	if(!foundNode) return(NULL);
 
 	sisfb_heap.max_freesize += poh_freed->size;
 
@@ -3492,8 +3220,7 @@ sisfb_poh_free(unsigned long base)
 	while(pohThis != &sisfb_heap.oh_free) {
 		if(pohThis->offset == ulUpper) {
 			poh_next = pohThis;
-		}
-			else if((pohThis->offset + pohThis->size) == ulLower) {
+		} else if((pohThis->offset + pohThis->size) == ulLower) {
 			poh_prev = pohThis;
 		}
 		pohThis = pohThis->poh_next;
@@ -3539,29 +3266,35 @@ sisfb_free_node(SIS_OH *poh)
 void
 sis_malloc(struct sis_memreq *req)
 {
-	SIS_OH *poh;
-
-	poh = sisfb_poh_allocate(req->size);
+	struct sis_video_info *ivideo = sisfb_heap.vinfo;
+	SIS_OH *poh = NULL;
+	
+	if((ivideo) && (!ivideo->havenoheap)) {
+	   poh = sisfb_poh_allocate((u32)req->size);
+	}
 
 	if(poh == NULL) {
-		req->offset = 0;
-		req->size = 0;
-		DPRINTK("sisfb: Video RAM allocation failed\n");
+	   req->offset = req->size = 0;
+	   DPRINTK("sisfb: Video RAM allocation failed\n");
 	} else {
-		DPRINTK("sisfb: Video RAM allocation succeeded: 0x%p\n",
-			(char *) (poh->offset + (unsigned long) ivideo.video_vbase));
-
-		req->offset = poh->offset;
-		req->size = poh->size;
+	   req->offset = poh->offset;
+	   req->size = poh->size;
+	   DPRINTK("sisfb: Video RAM allocation succeeded: 0x%lx\n",
+	   	    (poh->offset + ivideo->video_vbase));
 	}
 }
 
+/* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */
+
 void
-sis_free(unsigned long base)
+sis_free(u32 base)
 {
+	struct sis_video_info *ivideo = sisfb_heap.vinfo;
 	SIS_OH *poh;
+	
+	if((!ivideo) || (ivideo->havenoheap)) return;
 
-	poh = sisfb_poh_free(base);
+	poh = sisfb_poh_free((u32)base);
 
 	if(poh == NULL) {
 		DPRINTK("sisfb: sisfb_poh_free() failed at base 0x%x\n",
@@ -3572,101 +3305,285 @@ sis_free(unsigned long base)
 /* --------------------- SetMode routines ------------------------- */
 
 static void
-sisfb_pre_setmode(void)
+sisfb_pre_setmode(struct sis_video_info *ivideo)
 {
-	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0;
+	u8 cr30 = 0, cr31 = 0, cr33 = 0, cr35 = 0, cr38 = 0;
+	int tvregnum = 0;
 	
-	ivideo.currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
+	ivideo->currentvbflags &= (VB_VIDEOBRIDGE | VB_DISPTYPE_DISP2);
 
 	inSISIDXREG(SISCR, 0x31, cr31);
 	cr31 &= ~0x60;
 	cr31 |= 0x04;
 	
-	cr33 = ivideo.rate_idx & 0x0F;
+	cr33 = ivideo->rate_idx & 0x0F;
 
-	SiS_SetEnableDstn(&SiS_Pr, FALSE);
-	SiS_SetEnableFstn(&SiS_Pr, FALSE);
+#ifdef CONFIG_FB_SIS_315			
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(ivideo->chip >= SIS_661) {
+	      inSISIDXREG(SISCR, 0x38, cr38);
+	      cr38 &= ~0x07;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   } else {
+	      tvregnum = 0x38;
+	      inSISIDXREG(SISCR, tvregnum, cr38);
+	      cr38 &= ~0x3b;  /* Clear LCDA/DualEdge and YPbPr bits */
+	   }
+	}
+#endif	   	
+#ifdef CONFIG_FB_SIS_300
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   tvregnum = 0x35;
+	   inSISIDXREG(SISCR, tvregnum, cr38);
+	}
+#endif	
+	
+	SiS_SetEnableDstn(&ivideo->SiS_Pr, FALSE);
+	SiS_SetEnableFstn(&ivideo->SiS_Pr, FALSE);
 
-	switch (ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+	switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
+	
 	   case CRT2_TV:
-		ivideo.disp_state = DISPTYPE_TV;
-		if (ivideo.vbflags & TV_SVIDEO) {
-			cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_SVIDEO;
-			ivideo.TV_plug = TVPLUG_SVIDEO;
-		} else if (ivideo.vbflags & TV_AVIDEO) {
-			cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_AVIDEO;
-			ivideo.TV_plug = TVPLUG_COMPOSITE;
-		} else if (ivideo.vbflags & TV_SCART) {
-			cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
-			ivideo.currentvbflags |= TV_SCART;
-			ivideo.TV_plug = TVPLUG_SCART;
-		}
-		cr31 |= SIS_DRIVER_MODE;
-
-		if(!(ivideo.vbflags & TV_HIVISION)) {
-	        	if (ivideo.vbflags & TV_PAL) {
-		 		cr31 |= 0x01;
-				cr35 |= 0x01;
-				ivideo.currentvbflags |= TV_PAL;
-				ivideo.TV_type = TVMODE_PAL;
-                	} else {
-		       		cr31 &= ~0x01;
-				cr35 &= ~0x01;
-				ivideo.currentvbflags |= TV_NTSC;
-				ivideo.TV_type = TVMODE_NTSC;
-			}
-		}
-		break;
+	      cr38 &= ~0xc0;   /* Clear PAL-M / PAL-N bits */
+	      if((ivideo->vbflags & TV_YPBPR) && (ivideo->vbflags & (VB_301C|VB_301LV|VB_302LV))) {
+#ifdef CONFIG_FB_SIS_315	      
+	         if(ivideo->chip >= SIS_661) {
+	            cr38 |= 0x04;
+	            if(ivideo->vbflags & TV_YPBPR525P)       cr35 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr35 |= 0x40;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr35 |= 0x60;
+		    cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 
+		    cr35 &= ~0x01;		    
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+	         } else if(ivideo->sisvga_engine == SIS_315_VGA) {
+	            cr30 |= (0x80 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    cr38 |= 0x08;
+	            if(ivideo->vbflags & TV_YPBPR525P)       cr38 |= 0x10;
+		    else if(ivideo->vbflags & TV_YPBPR750P)  cr38 |= 0x20;
+		    else if(ivideo->vbflags & TV_YPBPR1080I) cr38 |= 0x30;
+		    cr31 &= ~0x01;
+		    ivideo->currentvbflags |= (TV_YPBPR | (ivideo->vbflags & TV_YPBPRALL));
+	         }
+#endif		 
+	      } else if((ivideo->vbflags & TV_HIVISION) && (ivideo->vbflags & (VB_301|VB_301B|VB_302B))) {
+	         if(ivideo->chip >= SIS_661) {
+	            cr38 |= 0x04;
+	            cr35 |= 0x60;
+	         } else {
+	            cr30 |= 0x80;
+	         }
+		 cr30 |= SIS_SIMULTANEOUS_VIEW_ENABLE; 
+	         cr31 |= 0x01;
+	         cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_HIVISION;
+	      } else if(ivideo->vbflags & TV_SCART) {
+		 cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		 cr31 |= 0x01;
+		 cr35 |= 0x01;
+		 ivideo->currentvbflags |= TV_SCART;
+	      } else {
+		 if(ivideo->vbflags & TV_SVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_SVIDEO;
+		 }
+		 if(ivideo->vbflags & TV_AVIDEO) {
+		    cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE);
+		    ivideo->currentvbflags |= TV_AVIDEO;
+		 }
+	      }
+	      cr31 |= SIS_DRIVER_MODE;
+
+	      if(ivideo->vbflags & (TV_AVIDEO|TV_SVIDEO)) {
+	         if(ivideo->vbflags & TV_PAL) {
+		    cr31 |= 0x01; cr35 |= 0x01;
+		    ivideo->currentvbflags |= TV_PAL;
+		    if(ivideo->vbflags & TV_PALM) {
+		       cr38 |= 0x40; cr35 |= 0x04; 
+		       ivideo->currentvbflags |= TV_PALM;
+		    } else if(ivideo->vbflags & TV_PALN) {
+		       cr38 |= 0x80; cr35 |= 0x08; 
+		       ivideo->currentvbflags |= TV_PALN;
+	  	    }
+                 } else {
+		    cr31 &= ~0x01; cr35 &= ~0x01;
+		    ivideo->currentvbflags |= TV_NTSC;
+		    if(ivideo->vbflags & TV_NTSCJ) {
+		       cr38 |= 0x40; cr35 |= 0x02; 
+		       ivideo->currentvbflags |= TV_NTSCJ;
+	 	    }
+		 }
+	      }
+	      break;
+	      
 	   case CRT2_LCD:
-		ivideo.disp_state = DISPTYPE_LCD;
-		cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		cr31 |= SIS_DRIVER_MODE;
-		SiS_SetEnableDstn(&SiS_Pr, sisfb_dstn);
-	        SiS_SetEnableFstn(&SiS_Pr, sisfb_fstn);
-		break;		
+	      cr30  = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      SiS_SetEnableDstn(&ivideo->SiS_Pr, ivideo->sisfb_dstn);
+	      SiS_SetEnableFstn(&ivideo->SiS_Pr, ivideo->sisfb_fstn);
+	      break;		
+	      
 	   case CRT2_VGA:
-		ivideo.disp_state = DISPTYPE_CRT2;
-		cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
-		cr31 |= SIS_DRIVER_MODE;
-		if(sisfb_nocrt2rate) {
-			cr33 |= (sisbios_mode[sisfb_mode_idx].rate_idx << 4);
-		} else {
-			cr33 |= ((ivideo.rate_idx & 0x0F) << 4);
-		}
-		break;
+	      cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE);
+	      cr31 |= SIS_DRIVER_MODE;
+	      if(ivideo->sisfb_nocrt2rate) {
+		 cr33 |= (sisbios_mode[ivideo->sisfb_mode_idx].rate_idx << 4);
+	      } else {
+		 cr33 |= ((ivideo->rate_idx & 0x0F) << 4);
+	      }
+	      break;
+	      
 	   default:	/* disable CRT2 */
-		cr30 = 0x00;
-		cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
+	      cr30 = 0x00;
+	      cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE);
 	}
 
-	if(ivideo.chip >= SIS_661) {
-	   cr31 &= ~0x01;
-	   /* Leave overscan bit alone */
-	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35);
-	}
-	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR30, cr30);
-	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR31, cr31);
-	outSISIDXREG(SISCR, IND_SIS_SCRATCH_REG_CR33, cr33);
+	outSISIDXREG(SISCR, 0x30, cr30);
+	outSISIDXREG(SISCR, 0x33, cr33);
 
-#ifdef CONFIG_FB_SIS_315
-        if(ivideo.sisvga_engine == SIS_315_VGA) {
-	   /* Clear LCDA and PAL-N/M bits */
-	   andSISIDXREG(SISCR,0x38,~0x03);
-	   if(ivideo.chip < SIS_661) {
-	      andSISIDXREG(SISCR,0x38,~0xc0);
-	   }
-	}
+	if(ivideo->chip >= SIS_661) {
+#ifdef CONFIG_FB_SIS_315		
+	   cr31 &= ~0x01;                          /* Clear PAL flag (now in CR35) */
+	   setSISIDXREG(SISCR, 0x35, ~0x10, cr35); /* Leave overscan bit alone */
+	   cr38 &= 0x07;                           /* Use only LCDA and HiVision/YPbPr bits */
+	   setSISIDXREG(SISCR, 0x38, 0xf8, cr38);
+#endif	   
+	} else if(ivideo->chip != SIS_300) {
+	   outSISIDXREG(SISCR, tvregnum, cr38);
+	}
+	outSISIDXREG(SISCR, 0x31, cr31);
+
+	if(ivideo->accel) sisfb_syncaccel(ivideo);
+
+	ivideo->SiS_Pr.SiS_UseOEM = ivideo->sisfb_useoem;
+}
+
+/* Fix SR11 for 661 and later */
+#ifdef CONFIG_FB_SIS_315 
+static void    
+sisfb_fixup_SR11(struct sis_video_info *ivideo)
+{
+    u8  tmpreg;
+    
+    if(ivideo->chip >= SIS_661) {
+       inSISIDXREG(SISSR,0x11,tmpreg);
+       if(tmpreg & 0x20) {
+          inSISIDXREG(SISSR,0x3e,tmpreg);
+	  tmpreg = (tmpreg + 1) & 0xff;
+	  outSISIDXREG(SISSR,0x3e,tmpreg);   	  
+	  inSISIDXREG(SISSR,0x11,tmpreg);
+       }
+       if(tmpreg & 0xf0) {
+          andSISIDXREG(SISSR,0x11,0x0f);
+       }
+    }
+}    
 #endif
 
-	if(ivideo.accel) sisfb_syncaccel();
+static void sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val)
+{
+   if(val > 32) val = 32;
+   if(val < -32) val = -32;
+   ivideo->tvxpos = val;
+   
+   if(ivideo->sisfblocked) return;
+   if(!ivideo->modechanged) return;
+
+   if(ivideo->currentvbflags & CRT2_TV) {
+
+      if(ivideo->vbflags & VB_CHRONTEL) {
+
+	 int x = ivideo->tvx;
+
+	 switch(ivideo->chronteltype) {
+	 case 1:
+	     x += val;
+	     if(x < 0) x = 0;
+	     outSISIDXREG(SISSR,0x05,0x86);
+	     SiS_SetCH700x(&ivideo->SiS_Pr, (((x & 0xff) << 8) | 0x0a));
+	     SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, (((x & 0x0100) << 1) | 0x08),0xFD);
+	     break;
+	 case 2:
+	     /* Not supported by hardware */
+	     break;
+	 }
+
+      } else if(ivideo->vbflags & VB_SISBRIDGE) {
+
+	 u8 p2_1f,p2_20,p2_2b,p2_42,p2_43;
+	 unsigned short temp;
+
+	 p2_1f = ivideo->p2_1f;
+	 p2_20 = ivideo->p2_20;
+	 p2_2b = ivideo->p2_2b;
+	 p2_42 = ivideo->p2_42;
+	 p2_43 = ivideo->p2_43;
+
+	 temp = p2_1f | ((p2_20 & 0xf0) << 4);
+	 temp += (val * 2);
+	 p2_1f = temp & 0xff;
+	 p2_20 = (temp & 0xf00) >> 4;
+	 p2_2b = ((p2_2b & 0x0f) + (val * 2)) & 0x0f;
+	 temp = p2_43 | ((p2_42 & 0xf0) << 4);
+	 temp += (val * 2);
+	 p2_43 = temp & 0xff;
+	 p2_42 = (temp & 0xf00) >> 4;
+	 outSISIDXREG(SISPART2,0x1f,p2_1f);
+	 setSISIDXREG(SISPART2,0x20,0x0F,p2_20);
+	 setSISIDXREG(SISPART2,0x2b,0xF0,p2_2b);
+	 setSISIDXREG(SISPART2,0x42,0x0F,p2_42);
+	 outSISIDXREG(SISPART2,0x43,p2_43);
+      }
+   }
+}
+ 
+static void sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val)
+{
+   if(val > 32) val = 32;
+   if(val < -32) val = -32;
+   ivideo->tvypos = val;
+   
+   if(ivideo->sisfblocked) return;
+   if(!ivideo->modechanged) return;
+      
+   if(ivideo->currentvbflags & CRT2_TV) {
+
+      if(ivideo->vbflags & VB_CHRONTEL) {
+
+	 int y = ivideo->tvy;
+	 
+	 switch(ivideo->chronteltype) {
+	 case 1:
+	    y -= val;
+	    if(y < 0) y = 0;
+	    outSISIDXREG(SISSR,0x05,0x86);
+	    SiS_SetCH700x(&ivideo->SiS_Pr, (((y & 0xff) << 8) | 0x0b));
+	    SiS_SetCH70xxANDOR(&ivideo->SiS_Pr, ((y & 0x0100) | 0x08),0xFE);
+	    break;
+	 case 2:
+	    /* Not supported by hardware */
+	    break;
+	 }
 
-	SiS_Pr.SiS_UseOEM = sisfb_useoem;
+      } else if(ivideo->vbflags & VB_SISBRIDGE) {
+	 
+	 char p2_01, p2_02;
+	 val /= 2;  
+	 p2_01 = ivideo->p2_01;
+	 p2_02 = ivideo->p2_02;
+
+	 p2_01 += val; 
+	 p2_02 += val; 
+	 while((p2_01 <= 0) || (p2_02 <= 0)) {
+	    p2_01 += 2;
+	    p2_02 += 2;
+	 }
+	 outSISIDXREG(SISPART2,0x01,p2_01);
+	 outSISIDXREG(SISPART2,0x02,p2_02);
+      }
+   }
 }
 
 static void
-sisfb_post_setmode(void)
+sisfb_post_setmode(struct sis_video_info *ivideo)
 {
 	u8 reg;
 	BOOLEAN crt1isoff = FALSE;
@@ -3675,32 +3592,23 @@ sisfb_post_setmode(void)
 	u8 reg1;
 #endif
 
-	/* Now we actually HAVE changed the display mode */
-        ivideo.modechanged = 1;
-
-	/* We can't switch off CRT1 if bridge is in slave mode */
-	if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-		inSISIDXREG(SISPART1, 0x00, reg);
-#ifdef CONFIG_FB_SIS_300
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
-			if((reg & 0xa0) == 0x20) {
-				doit = FALSE;
-			}
-		}
-#endif
+	outSISIDXREG(SISSR,0x05,0x86);
+	
 #ifdef CONFIG_FB_SIS_315
-		if(ivideo.sisvga_engine == SIS_315_VGA) {
-			if((reg & 0x50) == 0x10) {
-				doit = FALSE;
-			}
-		}
+	sisfb_fixup_SR11(ivideo);
 #endif
-	} else sisfb_crt1off = 0;
 
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	/* Now we actually HAVE changed the display mode */
+        ivideo->modechanged = 1;
+
+	/* We can't switch off CRT1 if bridge is in slave mode */
+	if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+		if(sisfb_bridgeisslave(ivideo)) doit = FALSE;
+	} else ivideo->sisfb_crt1off = 0;
 
 #ifdef CONFIG_FB_SIS_300
-	   if((sisfb_crt1off) && (doit)) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   if((ivideo->sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg = 0x00;
 	   } else {
@@ -3708,12 +3616,11 @@ sisfb_post_setmode(void)
 		reg = 0x80;
 	   }
 	   setSISIDXREG(SISCR, 0x17, 0x7f, reg);
+	}
 #endif
-
-	} else {
-
 #ifdef CONFIG_FB_SIS_315
-	   if((sisfb_crt1off) && (doit)) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if((ivideo->sisfb_crt1off) && (doit)) {
 	        crt1isoff = TRUE;
 		reg  = 0x40;
 		reg1 = 0xc0;
@@ -3723,66 +3630,89 @@ sisfb_post_setmode(void)
 		reg1 = 0x00;
 
 	   }
-	   setSISIDXREG(SISCR, SiS_Pr.SiS_MyCR63, ~0x40, reg);
+	   setSISIDXREG(SISCR, ivideo->SiS_Pr.SiS_MyCR63, ~0x40, reg);
 	   setSISIDXREG(SISSR, 0x1f, ~0xc0, reg1);
-#endif
-
 	}
+#endif
 
 	if(crt1isoff) {
-	   ivideo.currentvbflags &= ~VB_DISPTYPE_CRT1;
-	   ivideo.currentvbflags |= VB_SINGLE_MODE;
-	   ivideo.disp_state |= DISPMODE_SINGLE;
+	   ivideo->currentvbflags &= ~VB_DISPTYPE_CRT1;
+	   ivideo->currentvbflags |= VB_SINGLE_MODE;
 	} else {
-	   ivideo.currentvbflags |= VB_DISPTYPE_CRT1;
-	   ivideo.disp_state |= DISPTYPE_CRT1;
-	   if(ivideo.currentvbflags & VB_DISPTYPE_CRT2) {
-	  	ivideo.currentvbflags |= VB_MIRROR_MODE;
-		ivideo.disp_state |= DISPMODE_MIRROR;
+	   ivideo->currentvbflags |= VB_DISPTYPE_CRT1;
+	   if(ivideo->currentvbflags & VB_DISPTYPE_CRT2) {
+	  	ivideo->currentvbflags |= VB_MIRROR_MODE;
 	   } else {
-	 	ivideo.currentvbflags |= VB_SINGLE_MODE;
-		ivideo.disp_state |= DISPMODE_SINGLE;
+	 	ivideo->currentvbflags |= VB_SINGLE_MODE;
 	   }
 	}
 
         andSISIDXREG(SISSR, IND_SIS_RAMDAC_CONTROL, ~0x04);
+	
+	if(ivideo->currentvbflags & CRT2_TV) {
+	   if(ivideo->vbflags & VB_SISBRIDGE) {
+	      inSISIDXREG(SISPART2,0x1f,ivideo->p2_1f);
+	      inSISIDXREG(SISPART2,0x20,ivideo->p2_20);
+	      inSISIDXREG(SISPART2,0x2b,ivideo->p2_2b);
+	      inSISIDXREG(SISPART2,0x42,ivideo->p2_42);
+	      inSISIDXREG(SISPART2,0x43,ivideo->p2_43);
+	      inSISIDXREG(SISPART2,0x01,ivideo->p2_01);
+	      inSISIDXREG(SISPART2,0x02,ivideo->p2_02);
+	   } else if(ivideo->vbflags & VB_CHRONTEL) {
+	      if(ivideo->chronteltype == 1) {
+	         ivideo->tvx = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0a);
+	         ivideo->tvx |= (((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x02) >> 1) << 8);
+	         ivideo->tvy = SiS_GetCH700x(&ivideo->SiS_Pr, 0x0b);
+	         ivideo->tvy |= ((SiS_GetCH700x(&ivideo->SiS_Pr, 0x08) & 0x01) << 8);
+ 	      }
+	   }
+	}
+
+	if(ivideo->tvxpos) {
+   	   sisfb_set_TVxposoffset(ivideo, ivideo->tvxpos);
+	}
+	if(ivideo->tvypos) {
+   	   sisfb_set_TVyposoffset(ivideo, ivideo->tvypos);
+	}
 
-	if((ivideo.currentvbflags & CRT2_TV) && (ivideo.vbflags & VB_301)) {  /* Set filter for SiS301 */
+	if((ivideo->currentvbflags & CRT2_TV) && (ivideo->vbflags & VB_301)) {  /* Set filter for SiS301 */
+	
+	   	unsigned char filter_tb = 0;
 
-		switch (ivideo.video_width) {
+		switch (ivideo->video_width) {
 		   case 320:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 4 : 12;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 4 : 12;
 			break;
 		   case 640:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 5 : 13;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 5 : 13;
 			break;
 		   case 720:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 6 : 14;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 6 : 14;
 			break;
 		   case 400:
 		   case 800:
-			filter_tb = (ivideo.vbflags & TV_NTSC) ? 7 : 15;
+			filter_tb = (ivideo->vbflags & TV_NTSC) ? 7 : 15;
 			break;
 		   default:
-			filter = -1;
+			ivideo->sisfb_filter = -1;
 			break;
 		}
 
-		orSISIDXREG(SISPART1, ivideo.CRT2_write_enable, 0x01);
+		orSISIDXREG(SISPART1, ivideo->CRT2_write_enable, 0x01);
 
-		if(ivideo.vbflags & TV_NTSC) {
+		if(ivideo->vbflags & TV_NTSC) {
 
 		        andSISIDXREG(SISPART2, 0x3a, 0x1f);
 
-			if (ivideo.vbflags & TV_SVIDEO) {
+			if (ivideo->vbflags & TV_SVIDEO) {
 
 			        andSISIDXREG(SISPART2, 0x30, 0xdf);
 
-			} else if (ivideo.vbflags & TV_AVIDEO) {
+			} else if (ivideo->vbflags & TV_AVIDEO) {
 
 			        orSISIDXREG(SISPART2, 0x30, 0x20);
 
-				switch (ivideo.video_width) {
+				switch (ivideo->video_width) {
 				case 640:
 				        outSISIDXREG(SISPART2, 0x35, 0xEB);
 					outSISIDXREG(SISPART2, 0x36, 0x04);
@@ -3805,19 +3735,19 @@ sisfb_post_setmode(void)
 				}
 			}
 
-		} else if(ivideo.vbflags & TV_PAL) {
+		} else if(ivideo->vbflags & TV_PAL) {
 
 			andSISIDXREG(SISPART2, 0x3A, 0x1F);
 
-			if (ivideo.vbflags & TV_SVIDEO) {
+			if (ivideo->vbflags & TV_SVIDEO) {
 
 			        andSISIDXREG(SISPART2, 0x30, 0xDF);
 
-			} else if (ivideo.vbflags & TV_AVIDEO) {
+			} else if (ivideo->vbflags & TV_AVIDEO) {
 
 			        orSISIDXREG(SISPART2, 0x30, 0x20);
 
-				switch (ivideo.video_width) {
+				switch (ivideo->video_width) {
 				case 640:
 					outSISIDXREG(SISPART2, 0x35, 0xF1);
 					outSISIDXREG(SISPART2, 0x36, 0xF7);
@@ -3841,11 +3771,11 @@ sisfb_post_setmode(void)
 			}
 		}
 
-		if((filter >= 0) && (filter <= 7)) {
-			outSISIDXREG(SISPART2, 0x35, (sis_TV_filter[filter_tb].filter[filter][0]));
-			outSISIDXREG(SISPART2, 0x36, (sis_TV_filter[filter_tb].filter[filter][1]));
-			outSISIDXREG(SISPART2, 0x37, (sis_TV_filter[filter_tb].filter[filter][2]));
-			outSISIDXREG(SISPART2, 0x38, (sis_TV_filter[filter_tb].filter[filter][3]));
+		if((ivideo->sisfb_filter >= 0) && (ivideo->sisfb_filter <= 7)) {
+		   outSISIDXREG(SISPART2,0x35,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][0]));
+		   outSISIDXREG(SISPART2,0x36,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][1]));
+		   outSISIDXREG(SISPART2,0x37,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][2]));
+		   outSISIDXREG(SISPART2,0x38,(sis_TV_filter[filter_tb].filter[ivideo->sisfb_filter][3]));
 		}
 	  
 	}
@@ -3856,30 +3786,28 @@ int __init sisfb_setup(char *options)
 {
 	char *this_opt;
 	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	sisfb_fontname[0] = '\0';
-#endif
-
-	ivideo.refresh_rate = 0;
-	SiS_Pr.SiS_CustomT = CUT_NONE;
-	SiS_Pr.UsePanelScaler = -1;
-	SiS_Pr.CenterScreen = -1;
-	SiS_Pr.LVDSHL = -1;
-#if !defined(__i386__) && !defined(__x86_64__)
-       	sisfb_resetcard = 0;
-	sisfb_videoram = 0;
-#endif
+	sisfb_setdefaultparms();
 
         printk(KERN_DEBUG "sisfb: Options %s\n", options);
 
-	if(!options || !(*options))
+	if(!options || !(*options)) {
 		return 0;
+	}
 
 	while((this_opt = strsep(&options, ",")) != NULL) {
 
 		if(!(*this_opt)) continue;
-
-		if(!strnicmp(this_opt, "mode:", 5)) {
+		
+		if(!strnicmp(this_opt, "off", 3)) {
+			sisfb_off = 1;
+		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
+			/* Need to check crt2 type first for fstn/dstn */
+			sisfb_search_crt2type(this_opt + 14);
+		} else if(!strnicmp(this_opt, "tvmode:",7)) {
+		        sisfb_search_tvstd(this_opt + 7);
+                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
+			sisfb_search_tvstd(this_opt + 7);
+		} else if(!strnicmp(this_opt, "mode:", 5)) {
 			sisfb_search_mode(this_opt + 5, FALSE);
 		} else if(!strnicmp(this_opt, "vesa:", 5)) {
 			sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), FALSE);
@@ -3893,40 +3821,30 @@ int __init sisfb_setup(char *options)
 			   sisfb_fontname[sizeof(sisfb_fontname) - 1] = '\0';
 			}
 #endif
-		} else if(!strnicmp(this_opt, "vrate:", 6)) {
-			ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0);
-			sisfb_parm_rate = ivideo.refresh_rate;
 		} else if(!strnicmp(this_opt, "rate:", 5)) {
-			ivideo.refresh_rate = simple_strtoul(this_opt + 5, NULL, 0);
-			sisfb_parm_rate = ivideo.refresh_rate;
-		} else if(!strnicmp(this_opt, "off", 3)) {
-			sisfb_off = 1;
-		} else if(!strnicmp(this_opt, "crt1off", 7)) {
-			sisfb_crt1off = 1;
+			sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
 		} else if(!strnicmp(this_opt, "filter:", 7)) {
-			filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
-		} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) {
-			sisfb_search_crt2type(this_opt + 14);
+			sisfb_filter = (int)simple_strtoul(this_opt + 7, NULL, 0);
 		} else if(!strnicmp(this_opt, "forcecrt1:", 10)) {
 			sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
-                } else if(!strnicmp(this_opt, "tvmode:",7)) {
-		        sisfb_search_tvstd(this_opt + 7);
-                } else if(!strnicmp(this_opt, "tvstandard:",11)) {
-			sisfb_search_tvstd(this_opt + 7);
                 } else if(!strnicmp(this_opt, "mem:",4)) {
-		        sisfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
-		} else if(!strnicmp(this_opt, "queuemode:", 10)) {
-			sisfb_search_queuemode(this_opt + 10);
+		        sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
 		} else if(!strnicmp(this_opt, "pdc:", 4)) {
 		        sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
 		} else if(!strnicmp(this_opt, "pdc1:", 5)) {
 		        sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
 		} else if(!strnicmp(this_opt, "noaccel", 7)) {
 			sisfb_accel = 0;
+		} else if(!strnicmp(this_opt, "accel", 5)) {
+			sisfb_accel = -1;			
 		} else if(!strnicmp(this_opt, "noypan", 6)) {
 		        sisfb_ypan = 0;
+		} else if(!strnicmp(this_opt, "ypan", 4)) {
+		        sisfb_ypan = -1;
 		} else if(!strnicmp(this_opt, "nomax", 5)) {
 		        sisfb_max = 0;
+		} else if(!strnicmp(this_opt, "max", 3)) {
+		        sisfb_max = -1;
 		} else if(!strnicmp(this_opt, "userom:", 7)) {
 			sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
 		} else if(!strnicmp(this_opt, "useoem:", 7)) {
@@ -3937,15 +3855,27 @@ int __init sisfb_setup(char *options)
 		        unsigned long temp = 2;
 		        temp = simple_strtoul(this_opt + 9, NULL, 0);
 		        if((temp == 0) || (temp == 1)) {
-			   SiS_Pr.UsePanelScaler = temp ^ 1;
+			   sisfb_scalelcd = temp ^ 1;
+		        }
+		} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) {
+		        int temp = 0;
+		        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+		        if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvxposoffset = temp;
+		        }
+		} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) {
+		        int temp = 0;
+		        temp = (int)simple_strtol(this_opt + 13, NULL, 0);
+		        if((temp >= -32) && (temp <= 32)) {
+			   sisfb_tvyposoffset = temp;
 		        }
 		} else if(!strnicmp(this_opt, "specialtiming:", 14)) {
 			sisfb_search_specialtiming(this_opt + 14);
 		} else if(!strnicmp(this_opt, "lvdshl:", 7)) {
-		        unsigned long temp = 4;
+		        int temp = 4;
 		        temp = simple_strtoul(this_opt + 7, NULL, 0);
 		        if((temp >= 0) && (temp <= 3)) {
-			   SiS_Pr.LVDSHL = temp;
+			   sisfb_lvdshl = temp;
 		        }
 		} else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
 			sisfb_search_mode(this_opt, TRUE);
@@ -3959,18 +3889,18 @@ int __init sisfb_setup(char *options)
 			printk(KERN_INFO "sisfb: Invalid option %s\n", this_opt);
 		}
 
-		/* Acceleration only with MMIO mode */
-		if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
-			sisfb_accel = 0;
-		}
-
 	}
+	
+	
+	
 	return 0;
 }
 #endif
 
 static char * __devinit sis_find_rom(struct pci_dev *pdev)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	
 #if defined(__i386__) || defined(__x86_64__)
         u32  segstart;
         unsigned char *rom_base, *rom;
@@ -3979,38 +3909,38 @@ static char * __devinit sis_find_rom(str
 
         for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
 
-                rom_base = (unsigned char *)ioremap(segstart, 0x10000);
-		if(!rom_base) continue;
+            rom_base = (unsigned char *)ioremap(segstart, 0x10000);
+	    if(!rom_base) continue;
 
-		if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
-		   iounmap(rom_base);
-                   continue;
-		}
+	    if((readb(rom_base) != 0x55) || (readb(rom_base + 1) != 0xaa)) {
+	       iounmap(rom_base);
+               continue;
+	    }
 
-		romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
-		if(romptr > (0x10000 - 8)) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	    if(romptr > (0x10000 - 8)) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		rom = rom_base + romptr;
+	    rom = rom_base + romptr;
 
-		if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
-		   (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    if((readb(rom)     != 'P') || (readb(rom + 1) != 'C') ||
+	       (readb(rom + 2) != 'I') || (readb(rom + 3) != 'R')) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		pciid = readb(rom + 4) | (readb(rom + 5) << 8);
-		if(pciid != 0x1039) {
-		   iounmap(rom_base);
-		   continue;
-		}
+	    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
+	    if(pciid != 0x1039) {
+	       iounmap(rom_base);
+	       continue;
+	    }
 
-		pciid = readb(rom + 6) | (readb(rom + 7) << 8);
-		if(pciid == ivideo.chip_id) return rom_base;
+	    pciid = readb(rom + 6) | (readb(rom + 7) << 8);
+	    if(pciid == ivideo->chip_id) return rom_base;
 
-		iounmap(rom_base);
+	    iounmap(rom_base);
         }
 #else
 	unsigned char *rom_base, *rom, *myrombase = NULL;
@@ -4020,12 +3950,12 @@ static char * __devinit sis_find_rom(str
 
 	pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &backup);
 	pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
-			(ivideo.video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
+			(ivideo->video_base & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
 
-	rom_base = ioremap(ivideo.video_base, 65536);
+	rom_base = ioremap(ivideo->video_base, 65536);
 	if(rom_base) {
 	   if((readb(rom_base) == 0x55) && (readb(rom_base + 1) == 0xaa)) {
-	      romptr = (unsigned short)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
+	      romptr = (u16)(readb(rom_base + 0x18) | (readb(rom_base + 0x19) << 8));
 	      if(romptr <= (0x10000 - 8)) {
 	         rom = rom_base + romptr;
 		 if((readb(rom)     == 'P') && (readb(rom + 1) == 'C') &&
@@ -4033,7 +3963,7 @@ static char * __devinit sis_find_rom(str
 		    pciid = readb(rom + 4) | (readb(rom + 5) << 8);
 		    if(pciid == 0x1039) {
 		       pciid = readb(rom + 6) | (readb(rom + 7) << 8);
-		       if(pciid == ivideo.chip_id) {
+		       if(pciid == ivideo->chip_id) {
 		          if((myrombase = vmalloc(65536))) {
 			     memcpy_fromio(myrombase, rom_base, 65536);
 			  }
@@ -4052,8 +3982,9 @@ static char * __devinit sis_find_rom(str
 
 #ifdef SIS300
 static int __devinit
-sisfb_chkbuswidth300(ULONG FBAddress)
+sisfb_chkbuswidth300(struct pci_dev *pdev, ULONG FBAddress)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	int i, j;
 	USHORT temp;
 	UCHAR reg;
@@ -4091,9 +4022,10 @@ sisfb_chkbuswidth300(ULONG FBAddress)
 }
 
 static void __devinit
-sisfb_setramsize300(void)
+sisfb_setramsize300(struct pci_dev *pdev)
 {
-  	ULONG 	FBAddr = (ULONG)sishw_ext.pjVideoMemoryAddress, Addr;
+	struct  sis_video_info *ivideo = pci_get_drvdata(pdev);
+  	ULONG 	FBAddr = (ULONG)ivideo->sishw_ext.pjVideoMemoryAddress, Addr;
 	USHORT 	SR13, SR14=0, buswidth, Done, data, TotalCapacity, PhysicalAdrOtherPage=0;
 	int     PseudoRankCapacity, PseudoTotalCapacity, PseudoAdrPinCount;
    	int     RankCapacity, AdrPinCount, BankNumHigh, BankNumMid, MB2Bank;
@@ -4118,7 +4050,7 @@ sisfb_setramsize300(void)
 			{0x09,0x08,0x01,0x01,0x00}
 		};
 
-        buswidth = sisfb_chkbuswidth300(FBAddr);
+        buswidth = sisfb_chkbuswidth300(pdev, FBAddr);
 
    	MB2Bank = 16;
    	Done = 0;
@@ -4180,38 +4112,39 @@ sisfb_setramsize300(void)
    	}  /* for i */
 }
 
-static void __devinit sisfb_post_sis300(void)
+static void __devinit sisfb_post_sis300(struct pci_dev *pdev)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
 	u8  reg, v1, v2, v3, v4, v5, v6, v7, v8;
 	u16 index, rindex, memtype = 0;
 
-	outSISIDXREG(SISSR,0x05,SIS_PASSWORD);
+	outSISIDXREG(SISSR,0x05,0x86);
 
-	if(sishw_ext.UseROM) {
-	   if(sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
-	      memtype = sishw_ext.pjVirtualRomBase[0x52];
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x52] & 0x80) {
+	      memtype = ivideo->sishw_ext.pjVirtualRomBase[0x52];
  	   } else {
 	      inSISIDXREG(SISSR,0x3a,memtype);
 	   }
 	   memtype &= 0x07;
 	}
 
-	if(ivideo.revision_id <= 0x13) {
+	if(ivideo->revision_id <= 0x13) {
 	   v1 = 0x44; v2 = 0x42; v3 = 0x80;
 	   v4 = 0x44; v5 = 0x42; v6 = 0x80;
 	} else {
 	   v1 = 0x68; v2 = 0x43; v3 = 0x80;  /* Assume 125Mhz MCLK */
 	   v4 = 0x68; v5 = 0x43; v6 = 0x80;  /* Assume 125Mhz ECLK */
-	   if(sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.UseROM) {
 	      index = memtype * 5;
 	      rindex = index + 0x54;
-	      v1 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v2 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v3 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v1 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v2 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v3 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
 	      rindex = index + 0x7c;
-	      v4 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v5 = sishw_ext.pjVirtualRomBase[rindex++];
-	      v6 = sishw_ext.pjVirtualRomBase[rindex++];
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[rindex++];
 	   }
 	}
 	outSISIDXREG(SISSR,0x28,v1);
@@ -4221,23 +4154,23 @@ static void __devinit sisfb_post_sis300(
 	outSISIDXREG(SISSR,0x2f,v5);
 	outSISIDXREG(SISSR,0x30,v6);
 	v1 = 0x10;
-	if(sishw_ext.UseROM) v1 = sishw_ext.pjVirtualRomBase[0xa4];
+	if(ivideo->sishw_ext.UseROM) v1 = ivideo->sishw_ext.pjVirtualRomBase[0xa4];
 	outSISIDXREG(SISSR,0x07,v1);       /* DAC speed */
 	outSISIDXREG(SISSR,0x11,0x0f);     /* DDC, power save */
 	v1 = 0x01; v2 = 0x43; v3 = 0x1e; v4 = 0x2a;
 	v5 = 0x06; v6 = 0x00; v7 = 0x00; v8 = 0x00;
-	if(sishw_ext.UseROM) {
+	if(ivideo->sishw_ext.UseROM) {
 	   memtype += 0xa5;
-	   v1 = sishw_ext.pjVirtualRomBase[memtype];
-	   v2 = sishw_ext.pjVirtualRomBase[memtype + 8];
-	   v3 = sishw_ext.pjVirtualRomBase[memtype + 16];
-	   v4 = sishw_ext.pjVirtualRomBase[memtype + 24];
-	   v5 = sishw_ext.pjVirtualRomBase[memtype + 32];
-	   v6 = sishw_ext.pjVirtualRomBase[memtype + 40];
-	   v7 = sishw_ext.pjVirtualRomBase[memtype + 48];
-	   v8 = sishw_ext.pjVirtualRomBase[memtype + 56];
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[memtype];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 8];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 16];
+	   v4 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 24];
+	   v5 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 32];
+	   v6 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 40];
+	   v7 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 48];
+	   v8 = ivideo->sishw_ext.pjVirtualRomBase[memtype + 56];
 	}
-	if(ivideo.revision_id >= 0x80) v3 &= 0xfd;
+	if(ivideo->revision_id >= 0x80) v3 &= 0xfd;
 	outSISIDXREG(SISSR,0x15,v1);       /* Ram type (assuming 0, BIOS 0xa5 step 8) */
 	outSISIDXREG(SISSR,0x16,v2);
 	outSISIDXREG(SISSR,0x17,v3);
@@ -4248,20 +4181,20 @@ static void __devinit sisfb_post_sis300(
 	outSISIDXREG(SISSR,0x1c,v8);	   /* ---- */
 	andSISIDXREG(SISSR,0x15,0xfb);
 	orSISIDXREG(SISSR,0x15,0x04);
-	if(sishw_ext.UseROM) {
-	   if(sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
+	if(ivideo->sishw_ext.UseROM) {
+	   if(ivideo->sishw_ext.pjVirtualRomBase[0x53] & 0x02) {
 	      orSISIDXREG(SISSR,0x19,0x20);
 	   }
 	}
 	v1 = 0x04;			   /* DAC pedestal (BIOS 0xe5) */
-	if(ivideo.revision_id >= 0x80) v1 |= 0x01;
+	if(ivideo->revision_id >= 0x80) v1 |= 0x01;
 	outSISIDXREG(SISSR,0x1f,v1);
 	outSISIDXREG(SISSR,0x20,0xa0);     /* linear & relocated io */
 	v1 = 0xf6; v2 = 0x0d; v3 = 0x00;
-	if(sishw_ext.UseROM) {
-	   v1 = sishw_ext.pjVirtualRomBase[0xe8];
-	   v2 = sishw_ext.pjVirtualRomBase[0xe9];
-	   v3 = sishw_ext.pjVirtualRomBase[0xea];
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe8];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe9];
+	   v3 = ivideo->sishw_ext.pjVirtualRomBase[0xea];
 	}
 	outSISIDXREG(SISSR,0x23,v1);
 	outSISIDXREG(SISSR,0x24,v2);
@@ -4272,21 +4205,21 @@ static void __devinit sisfb_post_sis300(
 	orSISIDXREG(SISPART1,0x24,0x01);   /* unlock crt2 */
 	outSISIDXREG(SISPART1,0x00,0x00);
 	v1 = 0x40; v2 = 0x11;
-	if(sishw_ext.UseROM) {
-	   v1 = sishw_ext.pjVirtualRomBase[0xec];
-	   v2 = sishw_ext.pjVirtualRomBase[0xeb];
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xec];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xeb];
 	}
 	outSISIDXREG(SISPART1,0x02,v1);
-	if(ivideo.revision_id >= 0x80) v2 &= ~0x01;
+	if(ivideo->revision_id >= 0x80) v2 &= ~0x01;
 	inSISIDXREG(SISPART4,0x00,reg);
 	if((reg == 1) || (reg == 2)) {
 	   outSISIDXREG(SISCR,0x37,0x02);
 	   outSISIDXREG(SISPART2,0x00,0x1c);
 	   v4 = 0x00; v5 = 0x00; v6 = 0x10;
-	   if(sishw_ext.UseROM) {
-	      v4 = sishw_ext.pjVirtualRomBase[0xf5];
-	      v5 = sishw_ext.pjVirtualRomBase[0xf6];
-	      v6 = sishw_ext.pjVirtualRomBase[0xf7];
+	   if(ivideo->sishw_ext.UseROM) {
+	      v4 = ivideo->sishw_ext.pjVirtualRomBase[0xf5];
+	      v5 = ivideo->sishw_ext.pjVirtualRomBase[0xf6];
+	      v6 = ivideo->sishw_ext.pjVirtualRomBase[0xf7];
 	   }
 	   outSISIDXREG(SISPART4,0x0d,v4);
 	   outSISIDXREG(SISPART4,0x0e,v5);
@@ -4316,10 +4249,10 @@ static void __devinit sisfb_post_sis300(
 	} else {
 #endif
 	   /* Need to map max FB size for finding out about RAM size */
-	   sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x4000000);
-	   if(sishw_ext.pjVideoMemoryAddress) {
-	      sisfb_setramsize300();
-	      iounmap(sishw_ext.pjVideoMemoryAddress);
+	   ivideo->sishw_ext.pjVideoMemoryAddress = ioremap(ivideo->video_base, 0x4000000);
+	   if(ivideo->sishw_ext.pjVideoMemoryAddress) {
+	      sisfb_setramsize300(pdev);
+	      iounmap(ivideo->sishw_ext.pjVideoMemoryAddress);
 	   } else {
 	      printk(KERN_DEBUG "sisfb: Failed to map memory for size detection, assuming 8MB\n");
 	      outSISIDXREG(SISSR,0x13,0x28);  /* ? */
@@ -4328,9 +4261,9 @@ static void __devinit sisfb_post_sis300(
 #if !defined(__i386__) && !defined(__x86_64__)
 	}
 #endif
-	if(sishw_ext.UseROM) {
-	   v1 = sishw_ext.pjVirtualRomBase[0xe6];
-	   v2 = sishw_ext.pjVirtualRomBase[0xe7];
+	if(ivideo->sishw_ext.UseROM) {
+	   v1 = ivideo->sishw_ext.pjVirtualRomBase[0xe6];
+	   v2 = ivideo->sishw_ext.pjVirtualRomBase[0xe7];
 	} else {
 	   inSISIDXREG(SISSR,0x3a,reg);
 	   if((reg & 0x30) == 0x30) {
@@ -4346,182 +4279,203 @@ static void __devinit sisfb_post_sis300(
 }
 #endif
 
-
 int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data];
-	u32 reg32;
+	struct sisfb_chip_info 	*chipinfo = &sisfb_chip_info[ent->driver_data];
+	struct sis_video_info 	*ivideo = NULL;
+	struct fb_info 		*sis_fb_info = NULL;
 	u16 reg16;
 	u8  reg;
-	int sisvga_enabled = 0;
+	int sisvga_enabled = 0, i;
 
 	if(sisfb_off) return -ENXIO;
 
-	sisfb_thismonitor.datavalid = FALSE;
-
-	memset(&sishw_ext, 0, sizeof(sishw_ext));
-	
-	memset(&ivideo, 0, sizeof(ivideo));
-	ivideo.detectedpdc  = 0xff;
-	ivideo.detectedpdca = 0xff;
-	ivideo.detectedlcda = 0xff;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-        memset(&sisfb_lastrates[0], 0, 128);
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	memset(&sis_disp, 0, sizeof(sis_disp));
-#endif
-
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
-	sis_fb_info = framebuffer_alloc(0, &pdev->dev);
+	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
+	if(!sis_fb_info) return -ENOMEM;
 #else
-	sis_fb_info = kmalloc(sizeof(*sis_fb_info), GFP_KERNEL);
-#endif
+	sis_fb_info = kmalloc(sizeof(*sis_fb_info) + sizeof(*ivideo), GFP_KERNEL);
 	if(!sis_fb_info) return -ENOMEM;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3))
-	memset(sis_fb_info, 0, sizeof(*sis_fb_info));
+	memset(sis_fb_info, 0, sizeof(*sis_fb_info) + sizeof(*ivideo));
+	sis_fb_info->par = ((char *)sis_fb_info + sizeof(*sis_fb_info));
 #endif
 
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-	strcpy(sis_fb_info->modename, chipinfo->chip_name);
-#else
-	strcpy(myid, chipinfo->chip_name);
-#endif
+	ivideo = (struct sis_video_info *)sis_fb_info->par;
+	ivideo->memyselfandi = sis_fb_info;
+	
+	if(card_list == NULL) {
+	   ivideo->cardnumber = 0;
+	} else { 
+	   struct sis_video_info *countvideo = card_list;
+	   ivideo->cardnumber = 1;
+	   while((countvideo = countvideo->next)) ivideo->cardnumber++;
+	}
 
-	ivideo.chip_id = pdev->device;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo.revision_id);
-	sishw_ext.jChipRevision = ivideo.revision_id;
+	strncpy(ivideo->myid, chipinfo->chip_name, 30);
+
+	ivideo->chip_id = pdev->device;
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
+	ivideo->sishw_ext.jChipRevision = ivideo->revision_id;
 	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
 	sisvga_enabled = reg16 & 0x01;
-	ivideo.pcibus = pdev->bus->number;
-	ivideo.pcislot = PCI_SLOT(pdev->devfn);
-	ivideo.pcifunc = PCI_FUNC(pdev->devfn);
-	ivideo.subsysvendor = pdev->subsystem_vendor;
-	ivideo.subsysdevice = pdev->subsystem_device;
-
-	ivideo.chip = chipinfo->chip;
-	ivideo.sisvga_engine = chipinfo->vgaengine;
-	ivideo.hwcursor_size = chipinfo->hwcursor_size;
-	ivideo.CRT2_write_enable = chipinfo->CRT2_write_enable;
+	ivideo->pcibus = pdev->bus->number;
+	ivideo->pcislot = PCI_SLOT(pdev->devfn);
+	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
+	ivideo->subsysvendor = pdev->subsystem_vendor;
+	ivideo->subsysdevice = pdev->subsystem_device;
+#ifdef SIS_CONFIG_COMPAT				
+	ivideo->ioctl32registered = 0;
+	ivideo->ioctl32vblankregistered = 0;
+#endif	
 
-	/* Patch special cases */
-	switch(ivideo.chip_id) {
-#ifdef CONFIG_FB_SIS_300
-	   case PCI_DEVICE_ID_SI_630_VGA:
-		{
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07301039) {
-				ivideo.chip = SIS_730;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 730");
-#else
-				strcpy(myid, "SIS 730");
-#endif
-			}
-			break;
-		}
-#endif
-#ifdef CONFIG_FB_SIS_315
-	   case PCI_DEVICE_ID_SI_650_VGA:
-	   	{
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07401039) {
-				ivideo.chip = SIS_740;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 740");
-#else
-				strcpy(myid, "SIS 740");
-#endif
-			}
-			break;
-		}
-	   case PCI_DEVICE_ID_SI_660_VGA:
-	   	{
-			sisfb_set_reg4(0xCF8, 0x80000000);
-			reg32 = sisfb_get_reg3(0xCFC);
-			if(reg32 == 0x07601039) {
-				ivideo.chip = SIS_760;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 760");
-#else
-				strcpy(myid, "SIS 760");
-#endif
-			} else if(reg32 == 0x06601039) {
-				ivideo.chip = SIS_660;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 660");
-#else
-				strcpy(myid, "SIS 660");
-#endif
-			} else if(reg32 == 0x07411039) {
-				ivideo.chip = SIS_741;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 741");
-#else
-				strcpy(myid, "SIS 741");
+#ifndef MODULE
+	if(sisfb_mode_idx == -1) {
+		sisfb_get_vga_mode_from_kernel();
+	}
 #endif
-			} else {
-				ivideo.chip = SIS_661;
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
-				strcpy(sis_fb_info->modename, "SIS 661");
-#else
-				strcpy(myid, "SIS 661");
+
+	ivideo->chip = chipinfo->chip;
+	ivideo->sisvga_engine = chipinfo->vgaengine;
+	ivideo->hwcursor_size = chipinfo->hwcursor_size;
+	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
+	ivideo->mni = chipinfo->mni;
+	
+	ivideo->detectedpdc  = 0xff;
+	ivideo->detectedpdca = 0xff;
+	ivideo->detectedlcda = 0xff;
+	
+	ivideo->sisfb_thismonitor.datavalid = FALSE;
+	
+	ivideo->sisfb_parm_mem = sisfb_parm_mem;
+	ivideo->sisfb_accel = sisfb_accel;
+	ivideo->sisfb_ypan = sisfb_ypan;
+	ivideo->sisfb_max = sisfb_max;
+	ivideo->sisfb_userom = sisfb_userom;
+	ivideo->sisfb_useoem = sisfb_useoem;
+	ivideo->sisfb_mode_idx = sisfb_mode_idx;
+	ivideo->sisfb_parm_rate = sisfb_parm_rate;
+	ivideo->sisfb_crt1off = sisfb_crt1off;
+	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
+	ivideo->sisfb_crt2type = sisfb_crt2type;
+	ivideo->sisfb_crt2flags = sisfb_crt2flags;
+	/* pdc(a), scalelcd, special timing, lvdshl handled below */
+	ivideo->sisfb_dstn = sisfb_dstn;
+	ivideo->sisfb_fstn = sisfb_fstn;
+	ivideo->sisfb_tvplug = sisfb_tvplug;
+	ivideo->sisfb_tvstd = sisfb_tvstd;
+	ivideo->tvxpos = sisfb_tvxposoffset;
+	ivideo->tvypos = sisfb_tvyposoffset;
+	ivideo->sisfb_filter = sisfb_filter;
+	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)		
+	ivideo->sisfb_inverse = sisfb_inverse;
+#endif	
+	
+	ivideo->refresh_rate = 0;
+	if(ivideo->sisfb_parm_rate != -1) {
+	   ivideo->refresh_rate = ivideo->sisfb_parm_rate;
+	}
+	
+	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
+	ivideo->SiS_Pr.CenterScreen = -1;
+	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
+	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;
+	
+	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
+        ivideo->SiS_Pr.SiS_CHOverScan = -1;
+        ivideo->SiS_Pr.SiS_ChSW = FALSE;
+	ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
+	ivideo->SiS_Pr.HaveEMI = FALSE;
+	ivideo->SiS_Pr.HaveEMILCD = FALSE;
+	ivideo->SiS_Pr.OverruleEMI = FALSE;
+	ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
+	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
+	ivideo->SiS_Pr.PDC  = -1;
+	ivideo->SiS_Pr.PDCA = -1;
+#ifdef CONFIG_FB_SIS_315	
+	if(ivideo->chip >= SIS_330) {
+	   ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
+	   if(ivideo->chip >= SIS_661) {
+	      ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
+	   }
+	}
 #endif
-			}
+	
+	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));
+	
+	pci_set_drvdata(pdev, ivideo);
+	
+	/* Patch special cases */
+	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
+		switch(ivideo->nbridge->device) {
+#ifdef CONFIG_FB_SIS_300		
+		case PCI_DEVICE_ID_SI_730:
+		   	ivideo->chip = SIS_730;
+			strcpy(ivideo->myid, "SiS 730");
+		   	break;
+#endif			
+#ifdef CONFIG_FB_SIS_315
+		case PCI_DEVICE_ID_SI_651:
+			/* ivideo->chip is ok */
+			strcpy(ivideo->myid, "SiS 651");
+			break;
+		case PCI_DEVICE_ID_SI_740:
+		   	ivideo->chip = SIS_740;
+			strcpy(ivideo->myid, "SiS 740");
+			break;
+		case PCI_DEVICE_ID_SI_661:
+		   	ivideo->chip = SIS_661;
+			strcpy(ivideo->myid, "SiS 661");
+			break;
+		case PCI_DEVICE_ID_SI_741:
+		   	ivideo->chip = SIS_741;
+			strcpy(ivideo->myid, "SiS 741");
+			break;
+		case PCI_DEVICE_ID_SI_760:
+		   	ivideo->chip = SIS_760;
+			strcpy(ivideo->myid, "SiS 760");
 			break;
-		}
 #endif
+		}
 	}
+	
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	strcpy(sis_fb_info->modename, ivideo->myid);
+#endif
 
-	sishw_ext.jChipType = ivideo.chip;
+	ivideo->sishw_ext.jChipType = ivideo->chip;
 
-	if( (sishw_ext.jChipType == SIS_315PRO) ||
-	    (sishw_ext.jChipType == SIS_315) )
-		sishw_ext.jChipType = SIS_315H;
-
-	ivideo.video_base = pci_resource_start(pdev, 0);
-	ivideo.mmio_base = pci_resource_start(pdev, 1);
-	sishw_ext.ulIOAddress = SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
-	ivideo.vga_base = sishw_ext.ulIOAddress;
+#ifdef CONFIG_FB_SIS_315	
+	if((ivideo->sishw_ext.jChipType == SIS_315PRO) ||
+	   (ivideo->sishw_ext.jChipType == SIS_315)) {
+		ivideo->sishw_ext.jChipType = SIS_315H;
+	}
+#endif		
 
-	ivideo.mmio_size =  pci_resource_len(pdev, 1);
+	ivideo->video_base = pci_resource_start(pdev, 0);
+	ivideo->mmio_base  = pci_resource_start(pdev, 1);
+	ivideo->mmio_size  = pci_resource_len(pdev, 1);
+	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
+	ivideo->sishw_ext.ulIOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;
 
 	if(!sisvga_enabled) {
-	   if(pci_enable_device(pdev)) {
-	      kfree(sis_fb_info);
-	      return -EIO;
-	   }
+	   	if(pci_enable_device(pdev)) {
+	      		pci_set_drvdata(pdev, NULL);
+	      		kfree(sis_fb_info);
+	      		return -EIO;
+	   	}
 	} 
-
-	SiS_Pr.SiS_Backup70xx = 0xff;
-        SiS_Pr.SiS_CHOverScan = -1;
-        SiS_Pr.SiS_ChSW = FALSE;
-	SiS_Pr.SiS_UseLCDA = FALSE;
-	SiS_Pr.HaveEMI = FALSE;
-	SiS_Pr.HaveEMILCD = FALSE;
-	SiS_Pr.OverruleEMI = FALSE;
-	SiS_Pr.SiS_SensibleSR11 = FALSE;
-	SiS_Pr.SiS_MyCR63 = 0x63;
-	SiS_Pr.PDC = -1;
-	SiS_Pr.PDCA = -1;
-	if(ivideo.chip >= SIS_661) {
-	   SiS_Pr.SiS_SensibleSR11 = TRUE;
-	   SiS_Pr.SiS_MyCR63 = 0x53;
-	}
-	SiSRegInit(&SiS_Pr, sishw_ext.ulIOAddress);
+	
+	SiSRegInit(&ivideo->SiS_Pr, ivideo->sishw_ext.ulIOAddress);
 
 #ifdef CONFIG_FB_SIS_300
 	/* Find PCI systems for Chrontel/GPIO communication setup */
-	if(ivideo.chip == SIS_630) {
-	   int i=0;
+	if(ivideo->chip == SIS_630) {
+	   i=0;
            do {
-	      if(mychswtable[i].subsysVendor == ivideo.subsysvendor &&
-	         mychswtable[i].subsysCard   == ivideo.subsysdevice) {
-		 SiS_Pr.SiS_ChSW = TRUE;
+	      if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
+	         mychswtable[i].subsysCard   == ivideo->subsysdevice) {
+		 ivideo->SiS_Pr.SiS_ChSW = TRUE;
 		 printk(KERN_DEBUG "sisfb: Identified [%s %s] requiring Chrontel/GPIO setup\n",
 		        mychswtable[i].vendorName, mychswtable[i].cardName);
 		 break;
@@ -4531,26 +4485,26 @@ int __devinit sisfb_probe(struct pci_dev
 	}
 #endif
 
-        outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
+        outSISIDXREG(SISSR, 0x05, 0x86);
 
 	if( (!sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
 		  	      || (sisfb_resetcard)
 #endif
 			      			   ) {
-	   int i;
 	   for(i = 0x30; i <= 0x3f; i++) {
-	       outSISIDXREG(SISCR,i,0x00);
+	      outSISIDXREG(SISCR,i,0x00);
 	   }
 	}
 
 	inSISIDXREG(SISCR,0x34,reg);
-	ivideo.modeprechange = ((reg & 0x7f)) ? (reg & 0x7f) : 0x03;
+	ivideo->modeprechange = ((reg & 0x7f)) ? (reg & 0x7f) : 0x03;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)		
 #ifdef MODULE	
 	if((reg & 0x80) && (reg != 0xff)) {
-	   if((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF) {
+	   if((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF) {
 	      printk(KERN_INFO "sisfb: Cannot initialize display mode, X server is active\n");
+	      pci_set_drvdata(pdev, NULL);
 	      kfree(sis_fb_info);
 	      return -EBUSY;
 	   }
@@ -4558,84 +4512,82 @@ int __devinit sisfb_probe(struct pci_dev
 #endif	
 #endif
 
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
-	   	sishw_ext.bIntegratedMMEnabled = TRUE;
-	} else if(ivideo.sisvga_engine == SIS_300_VGA) {
-		if(ivideo.chip == SIS_300) {
-			sishw_ext.bIntegratedMMEnabled = TRUE;
-		} else {
-		        inSISIDXREG(SISSR, IND_SIS_SCRATCH_REG_1A, reg);
-			if(reg & SIS_SCRATCH_REG_1A_MASK)
-				sishw_ext.bIntegratedMMEnabled = TRUE;
-			else
-				sishw_ext.bIntegratedMMEnabled = FALSE;
-		}
+	ivideo->sishw_ext.bIntegratedMMEnabled = TRUE;
+#ifdef CONFIG_FB_SIS_300		   	
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
+	   if(ivideo->chip != SIS_300) {
+	      inSISIDXREG(SISSR, 0x1a, reg);
+	      if(!(reg & 0x10)) {
+		 ivideo->sishw_ext.bIntegratedMMEnabled = FALSE;
+	      }
+	   }	
 	}
+#endif	
 
-	ivideo.bios_vbase = ivideo.bios_abase = NULL;
-	if(sisfb_userom) {
-	    sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
+	ivideo->bios_vbase = ivideo->bios_abase = NULL;
+	if(ivideo->sisfb_userom) {
+	    ivideo->sishw_ext.pjVirtualRomBase = sis_find_rom(pdev);
 #if defined(__i386__) || defined(__x86_64__)
-	    ivideo.bios_vbase = sishw_ext.pjVirtualRomBase;	/* mapped */
+	    ivideo->bios_vbase = ivideo->sishw_ext.pjVirtualRomBase;	/* mapped */
 #else
-	    ivideo.bios_abase = sishw_ext.pjVirtualRomBase;	/* allocated */
+	    ivideo->bios_abase = ivideo->sishw_ext.pjVirtualRomBase;	/* allocated */
 #endif
-	    if(sishw_ext.pjVirtualRomBase) {
-		printk(KERN_INFO "sisfb: Video ROM found and %s to %p\n",
-			ivideo.bios_vbase ? "mapped" : "copied",
-		        sishw_ext.pjVirtualRomBase);
-		sishw_ext.UseROM = TRUE;
+	    if(ivideo->sishw_ext.pjVirtualRomBase) {
+		printk(KERN_INFO "sisfb: Video ROM found and %s to 0x%p\n",
+			ivideo->bios_vbase ? "mapped" : "copied",
+		        ivideo->sishw_ext.pjVirtualRomBase);
+		ivideo->sishw_ext.UseROM = TRUE;
 	    } else {
-	        sishw_ext.UseROM = FALSE;
+	        ivideo->sishw_ext.UseROM = FALSE;
 	        printk(KERN_INFO "sisfb: Video ROM not found\n");
 	    }
 	} else {
-	    sishw_ext.pjVirtualRomBase = NULL;
-	    sishw_ext.UseROM = FALSE;
+	    ivideo->sishw_ext.pjVirtualRomBase = NULL;
+	    ivideo->sishw_ext.UseROM = FALSE;
 	    printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
 	}
-	sishw_ext.bSkipDramSizing = 0;
 
         /* Find systems for special custom timing */
-	if(SiS_Pr.SiS_CustomT == CUT_NONE) {
-	   int i=0, j;
+	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
+	   int j;
 	   unsigned char *biosver = NULL;
            unsigned char *biosdate = NULL;
 	   BOOLEAN footprint;
-	   unsigned long chksum = 0;
+	   u32 chksum = 0;
 
-	   if(sishw_ext.UseROM) {
-	      biosver = sishw_ext.pjVirtualRomBase + 0x06;
-	      biosdate = sishw_ext.pjVirtualRomBase + 0x2c;
-              for(i=0; i<32768; i++) chksum += sishw_ext.pjVirtualRomBase[i];
+	   if(ivideo->sishw_ext.UseROM) {
+	      biosver = ivideo->sishw_ext.pjVirtualRomBase + 0x06;
+	      biosdate = ivideo->sishw_ext.pjVirtualRomBase + 0x2c;
+              for(i=0; i<32768; i++) chksum += ivideo->sishw_ext.pjVirtualRomBase[i];
 	   }
 
 	   i=0;
            do {
-	      if( (mycustomttable[i].chipID == ivideo.chip) &&
+	      if( (mycustomttable[i].chipID == ivideo->chip) &&
 	          ((!strlen(mycustomttable[i].biosversion)) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 		   (!strncmp(mycustomttable[i].biosversion, biosver, strlen(mycustomttable[i].biosversion))))) &&
 	          ((!strlen(mycustomttable[i].biosdate)) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 		   (!strncmp(mycustomttable[i].biosdate, biosdate, strlen(mycustomttable[i].biosdate))))) &&
 		  ((!mycustomttable[i].bioschksum) ||
-		   (sishw_ext.UseROM &&
+		   (ivideo->sishw_ext.UseROM &&
 	           (mycustomttable[i].bioschksum == chksum)))	&&
-		  (mycustomttable[i].pcisubsysvendor == ivideo.subsysvendor) &&
-		  (mycustomttable[i].pcisubsyscard == ivideo.subsysdevice) ) {
+		  (mycustomttable[i].pcisubsysvendor == ivideo->subsysvendor) &&
+		  (mycustomttable[i].pcisubsyscard == ivideo->subsysdevice) ) {
 		 footprint = TRUE;
-	         for(j=0; j<5; j++) {
+	         for(j = 0; j < 5; j++) {
 	            if(mycustomttable[i].biosFootprintAddr[j]) {
-		       if(sishw_ext.UseROM) {
-	                  if(sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
-		      		mycustomttable[i].biosFootprintData[j])
-		          footprint = FALSE;
+		       if(ivideo->sishw_ext.UseROM) {
+	                  if(ivideo->sishw_ext.pjVirtualRomBase[mycustomttable[i].biosFootprintAddr[j]] !=
+		      		mycustomttable[i].biosFootprintData[j]) {
+		             footprint = FALSE;
+			  }
 		       } else footprint = FALSE;
 		    }
 	         }
 	         if(footprint) {
-	 	    SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
+	 	    ivideo->SiS_Pr.SiS_CustomT = mycustomttable[i].SpecialID;
 		    printk(KERN_DEBUG "sisfb: Identified [%s %s], special timing applies\n",
 		        mycustomttable[i].vendorName,
 			mycustomttable[i].cardName);
@@ -4649,495 +4601,486 @@ int __devinit sisfb_probe(struct pci_dev
 	}
 
 #ifdef CONFIG_FB_SIS_300
-	/* Mode numbers for 1280x768 are different for 300 and 315 series */
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
-		sisbios_mode[MODEINDEX_1280x768].mode_no = 0x55;
-		sisbios_mode[MODEINDEX_1280x768+1].mode_no = 0x5a;
-		sisbios_mode[MODEINDEX_1280x768+2].mode_no = 0x5b;
-		sisbios_mode[MODEINDEX_1280x768+3].mode_no = 0x5b;
-	}
-#endif
-
-	sishw_ext.pSR = vmalloc(sizeof(SIS_DSReg) * SR_BUFFER_SIZE);
-	if(sishw_ext.pSR == NULL) {
-		printk(KERN_ERR "sisfb: Fatal error: Allocating SRReg space failed.\n");
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		kfree(sis_fb_info);
-		return -ENODEV;
-	}
-	sishw_ext.pSR[0].jIdx = sishw_ext.pSR[0].jVal = 0xFF;
-
-	sishw_ext.pCR = vmalloc(sizeof(SIS_DSReg) * CR_BUFFER_SIZE);
-	if(sishw_ext.pCR == NULL) {
-		printk(KERN_ERR "sisfb: Fatal error: Allocating CRReg space failed.\n");
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		vfree(sishw_ext.pSR);
-		kfree(sis_fb_info);
-		return -ENODEV;
-	}
-	sishw_ext.pCR[0].jIdx = sishw_ext.pCR[0].jVal = 0xFF;
-
-#ifdef CONFIG_FB_SIS_300
-	if(ivideo.sisvga_engine == SIS_300_VGA) {
+	if(ivideo->sisvga_engine == SIS_300_VGA) {
 		if( (!sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
 		    		      || (sisfb_resetcard)
 #endif
 		  					   ) {
-			if(ivideo.chip == SIS_300) sisfb_post_sis300();
-		}
-		if(sisfb_get_dram_size_300()) {
-			printk(KERN_ERR "sisfb: Fatal error: Unable to determine RAM size\n");
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			kfree(sis_fb_info);
-			return -ENODEV;
+			if(ivideo->chip == SIS_300) sisfb_post_sis300(pdev);
 		}
 	}
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
 		if( (!sisvga_enabled)
 #if !defined(__i386__) && !defined(__x86_64__)
 		    		     || (sisfb_resetcard)
 #endif
 		  					  ) {
-			if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) {
+			if((ivideo->sisfb_mode_idx < 0) || 
+			   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
 				/* TODO: POSTing 315/330 not supported yet */
-				/* Mapping Max FB Size for 315 Init */
-			      	sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, 0x8000000);
-				outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
-				sishw_ext.bSkipDramSizing = TRUE;
-				sishw_ext.pSR[0].jIdx = 0x13;
-				sishw_ext.pSR[1].jIdx = 0x14;
-				sishw_ext.pSR[2].jIdx = 0xFF;
-				inSISIDXREG(SISSR, 0x13, sishw_ext.pSR[0].jVal);
-				inSISIDXREG(SISSR, 0x14, sishw_ext.pSR[1].jVal);
-				sishw_ext.pSR[2].jVal = 0xFF;
-				iounmap(sishw_ext.pjVideoMemoryAddress);
 			}
 		}
-		if(sisfb_get_dram_size_315()) {
-			printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			kfree(sis_fb_info);
-			return -ENODEV;
-		}
 	}
 #endif
 
-	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
+	if(sisfb_get_dram_size(ivideo)) {
+		printk(KERN_INFO "sisfb: Fatal error: Unable to determine RAM size.\n");
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		pci_set_drvdata(pdev, NULL);
+		kfree(sis_fb_info);
+		return -ENODEV;
+	}
+
+	if((ivideo->sisfb_mode_idx < 0) || 
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 
 	        /* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
 	        orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
                 /* Enable 2D accelerator engine */
 	        orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
 	}
 
-	sishw_ext.ulVideoMemorySize = ivideo.video_size;
+	
 
 	if(sisfb_pdc != 0xff) {
-	   if(ivideo.sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
-	   else				           sisfb_pdc &= 0x1f;
-	   SiS_Pr.PDC = sisfb_pdc;
+	   if(ivideo->sisvga_engine == SIS_300_VGA) sisfb_pdc &= 0x3c;
+	   else				            sisfb_pdc &= 0x1f;
+	   ivideo->SiS_Pr.PDC = sisfb_pdc;
 	}
-	if(ivideo.sisvga_engine == SIS_315_VGA) {
-	   if(sisfb_pdca != 0xff) SiS_Pr.PDCA = sisfb_pdca & 0x1f;
+#ifdef CONFIG_FB_SIS_315	
+	if(ivideo->sisvga_engine == SIS_315_VGA) {
+	   if(sisfb_pdca != 0xff) ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
 	}
+#endif
 
-	if(!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) {
+	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve frame buffer memory\n");
 		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		vfree(sishw_ext.pSR);
-		vfree(sishw_ext.pCR);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
 
-	if(!request_mem_region(ivideo.mmio_base, ivideo.mmio_size, "sisfb MMIO")) {
+	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
 		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
-		release_mem_region(ivideo.video_base, ivideo.video_size);
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-		vfree(sishw_ext.pSR);
-		vfree(sishw_ext.pCR);
+		release_mem_region(ivideo->video_base, ivideo->video_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 		kfree(sis_fb_info);
 		return -ENODEV;
 	}
-
-	ivideo.video_vbase = sishw_ext.pjVideoMemoryAddress = ioremap(ivideo.video_base, ivideo.video_size);
-	if(!ivideo.video_vbase) {
+	
+	ivideo->video_vbase = (unsigned long)ioremap(ivideo->video_base, ivideo->video_size);
+	ivideo->sishw_ext.pjVideoMemoryAddress = (unsigned char *)ivideo->video_vbase;	
+	if(!ivideo->video_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map frame buffer memory\n");
-	   	release_mem_region(ivideo.video_base, ivideo.video_size);
-	   	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-	   	vfree(sishw_ext.pSR);
-	   	vfree(sishw_ext.pCR);
+	   	release_mem_region(ivideo->video_base, ivideo->video_size);
+	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 	   	kfree(sis_fb_info);
 	   	return -ENODEV;
 	}
 
-	ivideo.mmio_vbase = ioremap(ivideo.mmio_base, ivideo.mmio_size);
-	if(!ivideo.mmio_vbase) {
+	ivideo->mmio_vbase = (unsigned long)ioremap(ivideo->mmio_base, ivideo->mmio_size);
+	if(!ivideo->mmio_vbase) {
 	   	printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
-	   	iounmap(ivideo.video_vbase);
-	   	release_mem_region(ivideo.video_base, ivideo.video_size);
-	   	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
-		if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-	   	vfree(sishw_ext.pSR);
-	   	vfree(sishw_ext.pCR);
+	   	iounmap((void *)ivideo->video_vbase);
+	   	release_mem_region(ivideo->video_base, ivideo->video_size);
+	   	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+		if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+		if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+		pci_set_drvdata(pdev, NULL);
 	   	kfree(sis_fb_info);
 	   	return -ENODEV;
 	}
 
-	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
-	       	ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024);
-
-	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
-	       	ivideo.mmio_base, ivideo.mmio_vbase, ivideo.mmio_size / 1024);
+	printk(KERN_INFO "sisfb: Framebuffer at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	       	ivideo->video_base, ivideo->video_vbase, ivideo->video_size / 1024);
 
-	if(sisfb_heap_init()) {
+	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
+	       	ivideo->mmio_base, ivideo->mmio_vbase, ivideo->mmio_size / 1024);
+		
+	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
 		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
 	}
+	
+	/* Used for clearing the screen only, therefore respect our mem limit */
+	ivideo->sishw_ext.ulVideoMemorySize = ivideo->sisfb_mem;
 
-	ivideo.mtrr = (unsigned int) 0;
+	ivideo->mtrr = 0;
 	
-	ivideo.vbflags = 0;
+	ivideo->vbflags = 0;
+	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
+	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
+	ivideo->defmodeidx    = DEFAULT_MODE;
 
-	ivideo.newrom = SiSDetermineROMLayout661(&SiS_Pr, &sishw_ext);
+	ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr, &ivideo->sishw_ext);
 
-	if((sisfb_mode_idx < 0) || ((sisbios_mode[sisfb_mode_idx].mode_no) != 0xFF)) { 
-	
-		sishw_ext.ujVBChipID = VB_CHIP_UNKNOWN;
-		sishw_ext.Is301BDH = FALSE;
+	if((ivideo->sisfb_mode_idx < 0) || 
+	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) { 
 
-		sisfb_sense_crt1();
+		sisfb_sense_crt1(ivideo);
 	
-		sisfb_get_VB_type();
+		sisfb_get_VB_type(ivideo);
 		
-		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-			sisfb_detect_VB_connect();
+		if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+			sisfb_detect_VB_connect(ivideo);
 		}
 		
-		ivideo.currentvbflags = ivideo.vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
+		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);
 		
-		if(ivideo.vbflags & VB_VIDEOBRIDGE) {
-		   if(sisfb_crt2type != -1) {
-		      if((sisfb_crt2type == CRT2_LCD) && (ivideo.vbflags & CRT2_LCD)) {
-		         ivideo.currentvbflags |= CRT2_LCD;
-		      } else if(sisfb_crt2type != CRT2_LCD) {
-		         ivideo.currentvbflags |= sisfb_crt2type;
+		if(ivideo->vbflags & VB_VIDEOBRIDGE) {
+		   if(ivideo->sisfb_crt2type != -1) {
+		      if((ivideo->sisfb_crt2type == CRT2_LCD) && (ivideo->vbflags & CRT2_LCD)) {
+		         ivideo->currentvbflags |= CRT2_LCD;
+		      } else if(ivideo->sisfb_crt2type != CRT2_LCD) {
+		         ivideo->currentvbflags |= ivideo->sisfb_crt2type;
 		      }
 		   } else {
 		      /* Chrontel 700x TV detection often unreliable, therefore use a
 		       * different default order on such machines
 		       */
-		      if((ivideo.sisvga_engine == SIS_300_VGA) && (ivideo.vbflags & VB_CHRONTEL)) {
-		         if(ivideo.vbflags & CRT2_LCD)      ivideo.currentvbflags |= CRT2_LCD;
-		         else if(ivideo.vbflags & CRT2_TV)  ivideo.currentvbflags |= CRT2_TV;
-		         else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
+		      if((ivideo->sisvga_engine == SIS_300_VGA) && (ivideo->vbflags & VB_CHRONTEL)) {
+		         if(ivideo->vbflags & CRT2_LCD)      ivideo->currentvbflags |= CRT2_LCD;
+		         else if(ivideo->vbflags & CRT2_TV)  ivideo->currentvbflags |= CRT2_TV;
+		         else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
 		      } else {
-		         if(ivideo.vbflags & CRT2_TV)       ivideo.currentvbflags |= CRT2_TV;
-		         else if(ivideo.vbflags & CRT2_LCD) ivideo.currentvbflags |= CRT2_LCD;
-		         else if(ivideo.vbflags & CRT2_VGA) ivideo.currentvbflags |= CRT2_VGA;
+		         if(ivideo->vbflags & CRT2_TV)       ivideo->currentvbflags |= CRT2_TV;
+		         else if(ivideo->vbflags & CRT2_LCD) ivideo->currentvbflags |= CRT2_LCD;
+		         else if(ivideo->vbflags & CRT2_VGA) ivideo->currentvbflags |= CRT2_VGA;
 		      }
 		   }
 		}
 
-		if(ivideo.vbflags & CRT2_LCD) {
-		   inSISIDXREG(SISCR, IND_SIS_LCD_PANEL, reg);
+		if(ivideo->vbflags & CRT2_LCD) {
+		   inSISIDXREG(SISCR, 0x36, reg);
 		   reg &= 0x0f;
-		   if(ivideo.sisvga_engine == SIS_300_VGA) {
-		      sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
-		   } else if(ivideo.chip >= SIS_661) {
-		      sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
+		   if(ivideo->sisvga_engine == SIS_300_VGA) {
+		      ivideo->sishw_ext.ulCRT2LCDType = sis300paneltype[reg];
+		   } else if(ivideo->chip >= SIS_661) {
+		      ivideo->sishw_ext.ulCRT2LCDType = sis661paneltype[reg];
 		   } else {
-		      sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+		      ivideo->sishw_ext.ulCRT2LCDType = sis310paneltype[reg];
+		      if((ivideo->chip == SIS_550) && (sisfb_fstn)) {
+		         if((ivideo->sishw_ext.ulCRT2LCDType != LCD_640x480_2) &&
+			    (ivideo->sishw_ext.ulCRT2LCDType != LCD_640x480_3)) {			 
+		      	    ivideo->sishw_ext.ulCRT2LCDType = LCD_320x480;
+			 }
+		      }
+		   }
+		   if(ivideo->sishw_ext.ulCRT2LCDType == LCD_UNKNOWN) {
+		      ivideo->sishw_ext.ulCRT2LCDType = LCD_1024x768;
+		      printk(KERN_DEBUG "sisfb: Illegal panel ID (%02x), assuming 1024x768\n", reg);
+		   }
+		   for(i = 0; i < SIS_LCD_NUMBER; i++) {
+		      if(ivideo->sishw_ext.ulCRT2LCDType == sis_lcd_data[i].lcdtype) {
+		         ivideo->lcdxres = sis_lcd_data[i].xres;
+			 ivideo->lcdyres = sis_lcd_data[i].yres;
+			 ivideo->lcddefmodeidx = sis_lcd_data[i].default_mode_idx;
+			 break;
+		      }
 		   }
+		   if(ivideo->SiS_Pr.SiS_CustomT == CUT_BARCO1366) {
+	   		ivideo->lcdxres = 1360; ivideo->lcdyres = 1024; ivideo->lcddefmodeidx = 99;
+		   } else if(ivideo->SiS_Pr.SiS_CustomT == CUT_PANEL848) {
+	   		ivideo->lcdxres =  848; ivideo->lcdyres =  480; ivideo->lcddefmodeidx = 47;
+		   }
+		   printk(KERN_DEBUG "sisfb: Detected %dx%d flat panel\n", 
+		   		ivideo->lcdxres, ivideo->lcdyres);
 		}
 	
 #ifdef CONFIG_FB_SIS_300
                 /* Save the current PanelDelayCompensation if the LCD is currently used */
-		if(ivideo.sisvga_engine == SIS_300_VGA) {
-	           if(ivideo.vbflags & (VB_LVDS | VB_30xBDH)) {
+		if(ivideo->sisvga_engine == SIS_300_VGA) {
+	           if(ivideo->vbflags & (VB_LVDS | VB_30xBDH)) {
 		       int tmp;
 		       inSISIDXREG(SISCR,0x30,tmp);
 		       if(tmp & 0x20) {
 		          /* Currently on LCD? If yes, read current pdc */
-		          inSISIDXREG(SISPART1,0x13,ivideo.detectedpdc);
-			  ivideo.detectedpdc &= 0x3c;
-			  if(SiS_Pr.PDC == -1) {
+		          inSISIDXREG(SISPART1,0x13,ivideo->detectedpdc);
+			  ivideo->detectedpdc &= 0x3c;
+			  if(ivideo->SiS_Pr.PDC == -1) {
 			     /* Let option override detection */
-			     SiS_Pr.PDC = ivideo.detectedpdc;
+			     ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
 			  }
 			  printk(KERN_INFO "sisfb: Detected LCD PDC 0x%02x\n",
-  			         ivideo.detectedpdc);
+  			         ivideo->detectedpdc);
 		       }
-		       if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		       if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
 		          printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x\n",
-				 SiS_Pr.PDC);
+				 ivideo->SiS_Pr.PDC);
 		       }
 	           }
 		}
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-		if(ivideo.sisvga_engine == SIS_315_VGA) {
+		if(ivideo->sisvga_engine == SIS_315_VGA) {
 
 		   /* Try to find about LCDA */
-		   if(ivideo.vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
+		   if(ivideo->vbflags & (VB_301C | VB_302B | VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISPART1,0x13,tmp);
 		      if(tmp & 0x04) {
-		         SiS_Pr.SiS_UseLCDA = TRUE;
-		         ivideo.detectedlcda = 0x03;
+		         ivideo->SiS_Pr.SiS_UseLCDA = TRUE;
+		         ivideo->detectedlcda = 0x03;
 		         printk(KERN_DEBUG
 			        "sisfb: BIOS uses LCDA for low resolution and text modes\n");
 		      }
 	           }
 
 		   /* Save PDC */
-		   if(ivideo.vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
+		   if(ivideo->vbflags & (VB_301LV | VB_302LV | VB_302ELV)) {
 		      int tmp;
 		      inSISIDXREG(SISCR,0x30,tmp);
-		      if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
+		      if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
 		         /* Currently on LCD? If yes, read current pdc */
 			 u8 pdc;
 		         inSISIDXREG(SISPART1,0x2D,pdc);
-			 ivideo.detectedpdc  = (pdc & 0x0f) << 1;
-			 ivideo.detectedpdca = (pdc & 0xf0) >> 3;
+			 ivideo->detectedpdc  = (pdc & 0x0f) << 1;
+			 ivideo->detectedpdca = (pdc & 0xf0) >> 3;
 			 inSISIDXREG(SISPART1,0x35,pdc);
-			 ivideo.detectedpdc |= ((pdc >> 7) & 0x01);
+			 ivideo->detectedpdc |= ((pdc >> 7) & 0x01);
 			 inSISIDXREG(SISPART1,0x20,pdc);
-			 ivideo.detectedpdca |= ((pdc >> 6) & 0x01);
-			 if(ivideo.newrom) {
+			 ivideo->detectedpdca |= ((pdc >> 6) & 0x01);
+			 if(ivideo->newrom) {
 			    /* New ROM invalidates other PDC resp. */
-			    if(ivideo.detectedlcda != 0xff) {
-			       ivideo.detectedpdc = 0xff;
+			    if(ivideo->detectedlcda != 0xff) {
+			       ivideo->detectedpdc = 0xff;
 			    } else {
-			       ivideo.detectedpdca = 0xff;
+			       ivideo->detectedpdca = 0xff;
 			    }
 			 }
-			 if(SiS_Pr.PDC == -1) {
-			    if(ivideo.detectedpdc != 0xff) {
-			       SiS_Pr.PDC = ivideo.detectedpdc;
+			 if(ivideo->SiS_Pr.PDC == -1) {
+			    if(ivideo->detectedpdc != 0xff) {
+			       ivideo->SiS_Pr.PDC = ivideo->detectedpdc;
 			    }
 			 }
-			 if(SiS_Pr.PDCA == -1) {
-			    if(ivideo.detectedpdca != 0xff) {
-			       SiS_Pr.PDCA = ivideo.detectedpdca;
+			 if(ivideo->SiS_Pr.PDCA == -1) {
+			    if(ivideo->detectedpdca != 0xff) {
+			       ivideo->SiS_Pr.PDCA = ivideo->detectedpdca;
 			    }
 			 }
-			 if(ivideo.detectedpdc != 0xff) {
+			 if(ivideo->detectedpdc != 0xff) {
 			    printk(KERN_INFO
 			         "sisfb: Detected LCD PDC 0x%02x (for LCD=CRT2)\n",
-  			          ivideo.detectedpdc);
+  			          ivideo->detectedpdc);
 			 }
-			 if(ivideo.detectedpdca != 0xff) {
+			 if(ivideo->detectedpdca != 0xff) {
 			    printk(KERN_INFO
 			         "sisfb: Detected LCD PDC1 0x%02x (for LCD=CRT1)\n",
-  			          ivideo.detectedpdca);
+  			          ivideo->detectedpdca);
 			 }
 		      }
 
 		      /* Save EMI */
-		      if(ivideo.vbflags & (VB_302LV | VB_302ELV)) {
-		         inSISIDXREG(SISPART4,0x30,SiS_Pr.EMI_30);
-			 inSISIDXREG(SISPART4,0x31,SiS_Pr.EMI_31);
-			 inSISIDXREG(SISPART4,0x32,SiS_Pr.EMI_32);
-			 inSISIDXREG(SISPART4,0x33,SiS_Pr.EMI_33);
-			 SiS_Pr.HaveEMI = TRUE;
-			 if((tmp & 0x20) || (ivideo.detectedlcda != 0xff)) {
-			  	SiS_Pr.HaveEMILCD = TRUE;
+		      if(ivideo->vbflags & (VB_302LV | VB_302ELV)) {
+		         inSISIDXREG(SISPART4,0x30,ivideo->SiS_Pr.EMI_30);
+			 inSISIDXREG(SISPART4,0x31,ivideo->SiS_Pr.EMI_31);
+			 inSISIDXREG(SISPART4,0x32,ivideo->SiS_Pr.EMI_32);
+			 inSISIDXREG(SISPART4,0x33,ivideo->SiS_Pr.EMI_33);
+			 ivideo->SiS_Pr.HaveEMI = TRUE;
+			 if((tmp & 0x20) || (ivideo->detectedlcda != 0xff)) {
+			  	ivideo->SiS_Pr.HaveEMILCD = TRUE;
 			 }
 		      }
 		   }
 
 		   /* Let user override detected PDCs (all bridges) */
-		   if(ivideo.vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
-		      if((SiS_Pr.PDC != -1) && (SiS_Pr.PDC != ivideo.detectedpdc)) {
+		   if(ivideo->vbflags & (VB_301B | VB_301C | VB_301LV | VB_302LV | VB_302ELV)) {
+		      if((ivideo->SiS_Pr.PDC != -1) && (ivideo->SiS_Pr.PDC != ivideo->detectedpdc)) {
 		         printk(KERN_INFO "sisfb: Using LCD PDC 0x%02x (for LCD=CRT2)\n",
-				 SiS_Pr.PDC);
+				 ivideo->SiS_Pr.PDC);
 		      }
-		      if((SiS_Pr.PDCA != -1) && (SiS_Pr.PDCA != ivideo.detectedpdca)) {
+		      if((ivideo->SiS_Pr.PDCA != -1) && (ivideo->SiS_Pr.PDCA != ivideo->detectedpdca)) {
 		         printk(KERN_INFO "sisfb: Using LCD PDC1 0x%02x (for LCD=CRT1)\n",
-				 SiS_Pr.PDCA);
+				 ivideo->SiS_Pr.PDCA);
 		      }
 		   }
 
 		}
 #endif
 
-		if(!sisfb_crt1off) {
-		   	sisfb_handle_ddc(&sisfb_thismonitor, 0);
+		if(!ivideo->sisfb_crt1off) {
+		   	sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
 		} else {
-		   	if((ivideo.vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
-		      	   (ivideo.vbflags & (CRT2_VGA | CRT2_LCD))) {
-		      		sisfb_handle_ddc(&sisfb_thismonitor, 1);
+		   	if((ivideo->vbflags & (VB_301|VB_301B|VB_301C|VB_302B)) &&
+		      	   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
+		      		sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
 		   	}
 		}
 
-		if(sisfb_mode_idx >= 0)
-			sisfb_mode_idx = sisfb_validate_mode(sisfb_mode_idx, ivideo.currentvbflags);
+		if(ivideo->sisfb_mode_idx >= 0) {
+			int bu = ivideo->sisfb_mode_idx;
+			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
+					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
+			if(bu != ivideo->sisfb_mode_idx) {
+				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
+					sisbios_mode[bu].xres,
+					sisbios_mode[bu].yres,
+					sisbios_mode[bu].bpp);
+			}
+		}
 
-		if(sisfb_mode_idx < 0) {
-			switch(ivideo.currentvbflags & VB_DISPTYPE_DISP2) {
+		if(ivideo->sisfb_mode_idx < 0) {
+			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
 			   case CRT2_LCD:
-				sisfb_mode_idx = DEFAULT_LCDMODE;
+				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
 				break;
 			   case CRT2_TV:
-				sisfb_mode_idx = DEFAULT_TVMODE;
+				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
 				break;
 			   default:
-				sisfb_mode_idx = DEFAULT_MODE;
+				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
 				break;
 			}
 		}
 
-		ivideo.mode_no = sisbios_mode[sisfb_mode_idx].mode_no;
+		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];
 
-		if(ivideo.refresh_rate != 0)
-			sisfb_search_refresh_rate(ivideo.refresh_rate, sisfb_mode_idx);
+		if(ivideo->refresh_rate != 0) {
+			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate, ivideo->sisfb_mode_idx);
+		}
 
-		if(ivideo.rate_idx == 0) {
-			ivideo.rate_idx = sisbios_mode[sisfb_mode_idx].rate_idx;
-			ivideo.refresh_rate = 60;
+		if(ivideo->rate_idx == 0) {
+			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
+			ivideo->refresh_rate = 60;
 		}
 
-		if(sisfb_thismonitor.datavalid) {
-			if(!sisfb_verify_rate(&sisfb_thismonitor, sisfb_mode_idx,
-			                      ivideo.rate_idx, ivideo.refresh_rate)) {
+		if(ivideo->sisfb_thismonitor.datavalid) {
+			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, ivideo->sisfb_mode_idx,
+			                      ivideo->rate_idx, ivideo->refresh_rate)) {
 				printk(KERN_INFO "sisfb: WARNING: Refresh rate exceeds monitor specs!\n");
 			}
 		}
 
-		ivideo.video_bpp = sisbios_mode[sisfb_mode_idx].bpp;
-		ivideo.video_vwidth = ivideo.video_width = sisbios_mode[sisfb_mode_idx].xres;
-		ivideo.video_vheight = ivideo.video_height = sisbios_mode[sisfb_mode_idx].yres;
-		ivideo.org_x = ivideo.org_y = 0;
-		ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);
+		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
+		ivideo->video_vwidth = ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
+		ivideo->video_vheight = ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;
+		ivideo->org_x = ivideo->org_y = 0;
+		ivideo->video_linelength = ivideo->video_width * (ivideo->video_bpp >> 3);
 		
-		sisfb_set_vparms();
+		sisfb_set_vparms(ivideo);
 		
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
 
 		/* ---------------- For 2.4: Now switch the mode ------------------ */		
 		
 		printk(KERN_INFO "sisfb: Mode is %dx%dx%d (%dHz)\n",
-	       		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
-			ivideo.refresh_rate);
+	       		ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+			ivideo->refresh_rate);
 
-		sisfb_pre_setmode();
+		sisfb_pre_setmode(ivideo);
 
-		if(SiSSetMode(&SiS_Pr, &sishw_ext, ivideo.mode_no) == 0) {
+		if(SiSSetMode(&ivideo->SiS_Pr, &ivideo->sishw_ext, ivideo->mode_no) == 0) {
 			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
-				ivideo.mode_no);
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+									ivideo->mode_no);
+			iounmap((void *)ivideo->video_vbase);
+			iounmap((void *)ivideo->mmio_vbase);
+			release_mem_region(ivideo->video_base, ivideo->video_size);
+			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+			if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+			pci_set_drvdata(pdev, NULL);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
 		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);
 
-		sisfb_post_setmode();
+		sisfb_post_setmode(ivideo);
 		
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = -1;
-		   default_var.accel_flags |= FB_ACCELF_TEXT;
-		   sisfb_initaccel();
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = -1;
+		   ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+		   sisfb_initaccel(ivideo);
 		}
 
 		/* Maximize regardless of sisfb_max at startup */
-		default_var.yres_virtual = 32767;
-		sisfb_crtc_to_var(&default_var);
+		ivideo->default_var.yres_virtual = 32767;
+		sisfb_crtc_to_var(ivideo, &ivideo->default_var);
 		
-		sis_fb_info->node = -1;
+		sis_fb_info->node  = -1;
 		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-		sis_fb_info->blank = &sisfb_blank;
 		sis_fb_info->fbops = &sisfb_ops;
+		sis_fb_info->disp  = &ivideo->sis_disp;
+		sis_fb_info->blank = &sisfb_blank;
 		sis_fb_info->switch_con = &sisfb_switch;
-		sis_fb_info->updatevar = &sisfb_update_var;
-		sis_fb_info->changevar = NULL;
-		sis_fb_info->disp = &sis_disp;
+		sis_fb_info->updatevar  = &sisfb_update_var;
+		sis_fb_info->changevar  = NULL;
 		strcpy(sis_fb_info->fontname, sisfb_fontname);
 			
-		sisfb_set_disp(-1, &default_var, sis_fb_info);
+		sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);
 		
 #else		/* --------- For 2.6: Setup a somewhat sane default var ------------ */
 
 		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
-	       		ivideo.video_width, ivideo.video_height, ivideo.video_bpp,
-			ivideo.refresh_rate);
+	       		ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
+			ivideo->refresh_rate);
 
-		default_var.xres = default_var.xres_virtual = ivideo.video_width;
-		default_var.yres = default_var.yres_virtual = ivideo.video_height;
-		default_var.bits_per_pixel = ivideo.video_bpp;
+		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
+		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
+		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;
 
-		sisfb_bpp_to_var(&default_var);
+		sisfb_bpp_to_var(ivideo, &ivideo->default_var);
 		
-		default_var.pixclock = (u32) (1000000000 /
-				sisfb_mode_rate_to_dclock(&SiS_Pr, &sishw_ext,
-						ivideo.mode_no, ivideo.rate_idx));
+		ivideo->default_var.pixclock = (u32) (1000000000 /
+				sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+						ivideo->mode_no, ivideo->rate_idx));
 						
-		if(sisfb_mode_rate_to_ddata(&SiS_Pr, &sishw_ext,
-			 ivideo.mode_no, ivideo.rate_idx,
-			 &default_var.left_margin, &default_var.right_margin, 
-			 &default_var.upper_margin, &default_var.lower_margin,
-			 &default_var.hsync_len, &default_var.vsync_len,
-			 &default_var.sync, &default_var.vmode)) {
-		   if((default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
-		      default_var.pixclock <<= 1;
+		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,
+			 	ivideo->mode_no, ivideo->rate_idx, &ivideo->default_var)) {
+		   if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+		      ivideo->default_var.pixclock <<= 1;
 	   	   }
 	        }
-
-		ivideo.accel = 0;
-		if(sisfb_accel) {
-		   ivideo.accel = -1;
-		   default_var.accel_flags |= FB_ACCELF_TEXT;
-		   sisfb_initaccel();
+		
+		ivideo->accel = 0;
+		if(ivideo->sisfb_accel) {
+		   ivideo->accel = -1;
+		   ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
+		   sisfb_initaccel(ivideo);
 		}
 		
-		if(sisfb_ypan) {
+		if(ivideo->sisfb_ypan) {
 		   /* Maximize regardless of sisfb_max at startup */
-	    	   default_var.yres_virtual =
-				ivideo.heapstart / (default_var.xres * (default_var.bits_per_pixel >> 3));
-		   if(default_var.yres_virtual > 32767) default_var.yres_virtual = 32767;
-	    	   if(default_var.yres_virtual <= default_var.yres) {
-	              default_var.yres_virtual = default_var.yres;
+	    	   ivideo->default_var.yres_virtual =
+				ivideo->heapstart / 
+				     (ivideo->default_var.xres * (ivideo->default_var.bits_per_pixel >> 3));
+		   if(ivideo->default_var.yres_virtual > 32767) ivideo->default_var.yres_virtual = 32767;
+	    	   if(ivideo->default_var.yres_virtual <= ivideo->default_var.yres) {
+	              ivideo->default_var.yres_virtual = ivideo->default_var.yres;
 	    	   }
 		}
-
+		
 		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
-		sis_fb_info->var = default_var;
-		sis_fb_info->fix = sisfb_fix;
-		sis_fb_info->par = &ivideo;
-		sis_fb_info->screen_base = ivideo.video_vbase;
+		sis_fb_info->var = ivideo->default_var;
+		sis_fb_info->fix = ivideo->sisfb_fix;
+		sis_fb_info->screen_base = (char *)ivideo->video_vbase;
 		sis_fb_info->fbops = &sisfb_ops;
-#ifdef NEWFBDEV
-		sis_fb_info->class_dev.dev = &pdev->dev;
-#endif
+
 		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
-		sis_fb_info->pseudo_palette = pseudo_palette;
+		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;
 		
 		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
-#endif
+#endif		/* 2.6 */
 
-		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", ivideo.vbflags);
+		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%lx\n", (unsigned long)ivideo->vbflags);
 
 #ifdef CONFIG_MTRR
-		ivideo.mtrr = mtrr_add((unsigned int) ivideo.video_base,
-				(unsigned int) ivideo.video_size,
-				MTRR_TYPE_WRCOMB, 1);
-		if(ivideo.mtrr) {
-			printk(KERN_DEBUG "sisfb: Added MTRRs\n");
+		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
+					MTRR_TYPE_WRCOMB, 1);
+		if(!ivideo->mtrr) {
+			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
 		}
 #endif
 
@@ -5146,38 +5089,72 @@ int __devinit sisfb_probe(struct pci_dev
 #endif
 
 		if(register_framebuffer(sis_fb_info) < 0) {
-			if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-			vfree(sishw_ext.pSR);
-			vfree(sishw_ext.pCR);
-			release_mem_region(ivideo.video_base, ivideo.video_size);
-			release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
 			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
+			iounmap((void *)ivideo->video_vbase);
+			iounmap((void *)ivideo->mmio_vbase);
+			release_mem_region(ivideo->video_base, ivideo->video_size);
+			release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
+			if(ivideo->bios_abase) vfree(ivideo->bios_abase);
+			if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+			pci_set_drvdata(pdev, NULL);
 			kfree(sis_fb_info);
 			return -EINVAL;
 		}
 
-		ivideo.registered = 1;
-
-		pci_set_drvdata(pdev, sis_fb_info);
+		ivideo->registered = 1;
+		
+		/* Enlist us */
+		ivideo->next = card_list;
+		card_list = ivideo;
+		
+#ifdef SIS_CONFIG_COMPAT
+		{
+		int ret;
+		/* Our ioctls are all "32/64bit compatible" */
+		if(register_ioctl32_conversion(FBIOGET_VBLANK, NULL)) {
+		   printk(KERN_ERR "sisfb: Error registering FBIOGET_VBLANK ioctl32 translation\n");
+		} else {
+		   ivideo->ioctl32vblankregistered = 1;
+		}
+		ret =  register_ioctl32_conversion(FBIO_ALLOC,             NULL);
+		ret |= register_ioctl32_conversion(FBIO_FREE,              NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE,    NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_INFO,         NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET,  NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET,  NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_LOCK,         NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS,    NULL);
+		ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
+		ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
+		if(ret)	printk(KERN_ERR "sisfb: Error registering ioctl32 translations\n");
+		else    ivideo->ioctl32registered = 1;
+		}
+#endif
 
+#if 0
+		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO_SIZE ioctl (%x)\n", SISFB_GET_INFO_SIZE);
 		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_INFO ioctl (%x)\n", SISFB_GET_INFO);
 		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_VBRSTATUS ioctl (%x)\n", SISFB_GET_VBRSTATUS);
-
-		printk(KERN_INFO "sisfb: 2D acceleration is %s, scrolling mode %s\n",
-		     sisfb_accel ? "enabled" : "disabled",
-		     sisfb_ypan  ? (sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
+		printk(KERN_DEBUG "sisfb: Installed SISFB_GET_TVPOSOFFSET ioctl (%x)\n", SISFB_GET_TVPOSOFFSET);
+		printk(KERN_DEBUG "sisfb: Installed SISFB_SET_TVPOSOFFSET ioctl (%x)\n", SISFB_SET_TVPOSOFFSET);
+#endif		
+
+		printk(KERN_INFO "sisfb: 2D acceleration is %s, scroll-mode %s\n",
+		     ivideo->sisfb_accel ? "enabled" : "disabled",
+		     ivideo->sisfb_ypan  ? 
+		     	(ivideo->sisfb_max ? "ypan (auto-max)" : "ypan (no auto-max)") : "redraw");
 
 
 		printk(KERN_INFO "fb%d: %s frame buffer device, Version %d.%d.%02d\n",
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	       		GET_FB_IDX(sis_fb_info->node), sis_fb_info->modename,
+	       		GET_FB_IDX(sis_fb_info->node), 
 #else
-	       		sis_fb_info->node, myid,
+	       		sis_fb_info->node, 
 #endif
-			VER_MAJOR, VER_MINOR, VER_LEVEL);
+			ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);
 
 		printk(KERN_INFO "sisfb: (C) 2001-2004 Thomas Winischhofer.\n");
-
+		
 	}	/* if mode = "none" */
 
 	return 0;
@@ -5189,26 +5166,51 @@ int __devinit sisfb_probe(struct pci_dev
 
 static void __devexit sisfb_remove(struct pci_dev *pdev)
 {
+	struct sis_video_info *ivideo = pci_get_drvdata(pdev);
+	struct fb_info        *sis_fb_info = ivideo->memyselfandi;
+	int                   registered = ivideo->registered;
+	
+#ifdef SIS_CONFIG_COMPAT	
+	if(ivideo->ioctl32vblankregistered) {
+		if(unregister_ioctl32_conversion(FBIOGET_VBLANK)) {
+			printk(KERN_ERR "sisfb: Error unregistering FBIOGET_VBLANK ioctl32 translation\n");
+		}
+	}
+	if(ivideo->ioctl32registered) {
+		int ret;
+		ret =  unregister_ioctl32_conversion(FBIO_ALLOC);
+		ret |= unregister_ioctl32_conversion(FBIO_FREE);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO_SIZE);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_INFO);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_TVPOSOFFSET);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_TVPOSOFFSET);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_LOCK);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_VBRSTATUS);
+		ret |= unregister_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE);
+		ret |= unregister_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE);
+		if(ret)	printk(KERN_ERR "sisfb: Error unregistering ioctl32 translations\n");
+	}
+#endif
+	
 	/* Unmap */
-	iounmap(ivideo.video_vbase);
-	iounmap(ivideo.mmio_vbase);
-	if(ivideo.bios_vbase) iounmap(ivideo.bios_vbase);
+	iounmap((void *)ivideo->video_vbase);
+	iounmap((void *)ivideo->mmio_vbase);
+	if(ivideo->bios_vbase) iounmap(ivideo->bios_vbase);
+	if(ivideo->bios_abase)    vfree(ivideo->bios_abase);
 
 	/* Release mem regions */
-	release_mem_region(ivideo.video_base, ivideo.video_size);
-	release_mem_region(ivideo.mmio_base, ivideo.mmio_size);
+	release_mem_region(ivideo->video_base, ivideo->video_size);
+	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
 
 #ifdef CONFIG_MTRR
 	/* Release MTRR region */
-	if(ivideo.mtrr) {
-		mtrr_del(ivideo.mtrr,
-		      (unsigned int)ivideo.video_base,
-	              (unsigned int)ivideo.video_size);
+	if(ivideo->mtrr) {
+		mtrr_del(ivideo->mtrr, ivideo->video_base, ivideo->video_size);
 	}
 #endif
-
+	
 	/* Unregister the framebuffer */
-	if(ivideo.registered) {
+	if(ivideo->registered) {
 		unregister_framebuffer(sis_fb_info);
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3))
 		framebuffer_release(sis_fb_info);
@@ -5217,10 +5219,6 @@ static void __devexit sisfb_remove(struc
 #endif
 	}
 
-	if(sishw_ext.pSR) vfree(sishw_ext.pSR);
-	if(sishw_ext.pCR) vfree(sishw_ext.pCR);
-	if(ivideo.bios_abase) vfree(ivideo.bios_abase);
-
 	pci_set_drvdata(pdev, NULL);
 
 	/* TODO: Restore the initial mode
@@ -5230,7 +5228,7 @@ static void __devexit sisfb_remove(struc
 	 * from machine to machine. Depends on the type
 	 * of integration between chipset and bridge.
 	 */
-	if(ivideo.registered) {
+	if(registered) {
 	   printk(KERN_INFO "sisfb: Restoring of text mode not supported yet\n");
 	}
 };
@@ -5260,7 +5258,6 @@ static unsigned int crt1off = 1;
 static unsigned int mem = 0;
 static char         *forcecrt2type = NULL;
 static int          forcecrt1 = -1;
-static char         *queuemode = NULL;
 static int          pdc = -1;
 static int          pdc1 = -1;
 static int          noaccel = -1;
@@ -5269,232 +5266,249 @@ static int	    nomax = -1;
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int          inverse = 0;
 #endif
-static int          userom = 1;
+static int          userom = -1;
 static int          useoem = -1;
 static char         *tvstandard = NULL;
 static int	    nocrt2rate = 0;
 static int          scalelcd = -1;
 static char	    *specialtiming = NULL;
 static int	    lvdshl = -1;
+static int	    tvxposoffset = 0, tvyposoffset = 0;
+static int	    filter = -1;
 #if !defined(__i386__) && !defined(__x86_64__)
 static int	    resetcard = 0;
 static int	    videoram = 0;
 #endif
 
-MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer driver");
+MODULE_DESCRIPTION("SiS 300/540/630/730/315/550/65x/661/74x/330/760 framebuffer device driver");
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>; SiS; Others");
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>, Others");
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+MODULE_PARM(mem, "i");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM(noypan, "i");
+MODULE_PARM(nomax, "i");
+MODULE_PARM(userom, "i");
+MODULE_PARM(useoem, "i");
 MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode,
-       "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
-         "1024x768x16. Other formats supported include XxY-Depth and\n"
-	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
-	 "number, it will be interpreted as a VESA mode number. (default: none if\n"
-	 "sisfb is a module; this leaves the console untouched and the driver will\n"
-	 "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
-	 "is in the kernel)");
+MODULE_PARM(vesa, "i");
+MODULE_PARM(rate, "i");
+MODULE_PARM(forcecrt1, "i");
+MODULE_PARM(forcecrt2type, "s");
+MODULE_PARM(scalelcd, "i");
+MODULE_PARM(pdc, "i");
+MODULE_PARM(pdc1, "i");
+MODULE_PARM(specialtiming, "s");
+MODULE_PARM(lvdshl, "i");
+MODULE_PARM(tvstandard, "s");
+MODULE_PARM(tvxposoffset, "i");
+MODULE_PARM(tvyposoffset, "i");
+MODULE_PARM(filter, "i");
+MODULE_PARM(nocrt2rate, "i");
+MODULE_PARM(inverse, "i");
+#if !defined(__i386__) && !defined(__x86_64__)
+MODULE_PARM(resetcard, "i");
+MODULE_PARM(videoram, "i");
+#endif
 #endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)	 
-MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode,
-       "\nSelects the desired default display mode in the format XxYxDepth,\n"
-         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
-	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
-	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)");
+module_param(mem, int, 0);
+module_param(noaccel, int, 0);
+module_param(noypan, int, 0);
+module_param(nomax, int, 0);
+module_param(userom, int, 0);
+module_param(useoem, int, 0);
+module_param(mode, charp, 0);
+module_param(vesa, int, 0);
+module_param(rate, int, 0);
+module_param(forcecrt1, int, 0);
+module_param(forcecrt2type, charp, 0);
+module_param(scalelcd, int, 0);
+module_param(pdc, int, 0);
+module_param(pdc1, int, 0);
+module_param(specialtiming, charp, 0);
+module_param(lvdshl, int, 0);
+module_param(tvstandard, charp, 0);
+module_param(tvxposoffset, int, 0);
+module_param(tvyposoffset, int, 0);
+module_param(filter, int, 0);
+module_param(nocrt2rate, int, 0);
+#if !defined(__i386__) && !defined(__x86_64__)
+module_param(resetcard, int, 0);
+module_param(videoram, int, 0);
+#endif
 #endif
 
+MODULE_PARM_DESC(mem,
+	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
+	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
+	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
+	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
+	  "otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
+	  "The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
+	  "for XFree86 4.x/X.org 6.7 and later.\n");
+
+MODULE_PARM_DESC(noaccel,
+        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
+	  "(default: 0)\n");
+
+MODULE_PARM_DESC(noypan,
+        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
+ 	  "will be performed by redrawing the screen. (default: 0)\n");
+
+MODULE_PARM_DESC(nomax,
+        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
+	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
+	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
+	  "enable the user to positively specify a virtual Y size of the screen using\n"
+	  "fbset. (default: 0)\n");	  
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(mode,
+        "\nSelects the desired display mode in the format [X]x[Y]x[Depth], eg.\n"
+          "1024x768x16. Other formats supported include XxY-Depth and\n"
+ 	  "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n" 
+	  "number, it will be interpreted as a VESA mode number. (default: none if\n"
+	  "sisfb is a module; this leaves the console untouched and the driver will\n"
+	  "only do the video memory management for eg. DRM/DRI; 800x600x8 if sisfb\n"
+	  "is in the kernel)\n");
 MODULE_PARM_DESC(vesa,
-       "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
-         "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
-	 "and the driver will only do the video memory management for eg. DRM/DRI;\n"
-	 "0x0103 if sisfb is in the kernel)");
-#endif
+        "\nSelects the desired display mode by VESA defined mode number, eg. 0x117\n"
+          "(default: 0x0000 if sisfb is a module; this leaves the console untouched\n"
+	  "and the driver will only do the video memory management for eg. DRM/DRI;\n"
+	  "0x0103 if sisfb is in the kernel)\n");	
+#endif	  
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-MODULE_PARM(vesa, "i");
+MODULE_PARM_DESC(mode,
+       "\nSelects the desired default display mode in the format XxYxDepth,\n"
+         "eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
+	 "XxY-Depth@Rate. If the parameter is only one (decimal or hexadecimal)\n"
+	 "number, it will be interpreted as a VESA mode number. (default: 800x600x8)\n");
+
 MODULE_PARM_DESC(vesa,
        "\nSelects the desired default display mode by VESA defined mode number, eg.\n"
-         "0x117 (default: 0x0103)");
+         "0x117 (default: 0x0103)\n");
 #endif
-
-MODULE_PARM(rate, "i");
+	  
 MODULE_PARM_DESC(rate,
 	"\nSelects the desired vertical refresh rate for CRT1 (external VGA) in Hz.\n"
 	  "If the mode is specified in the format XxY-Depth@Rate, this parameter\n"
-	  "will be ignored (default: 60)");
-
-MODULE_PARM(crt1off,   "i");
-MODULE_PARM_DESC(crt1off,
-	"(Deprecated, please use forcecrt1)");
-
-MODULE_PARM(filter, "i");
-MODULE_PARM_DESC(filter,
-	"\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
-	  "(Possible values 0-7, default: [no filter])");
-
-MODULE_PARM(queuemode,   "s");
-MODULE_PARM_DESC(queuemode,
-	"\nSelects the queue mode on 315/550/65x/74x/330/760. Possible choices are AGP,\n"
-  	  "VRAM and MMIO. AGP is only available if the kernel has AGP support. The queue\n"
-	  "mode is important to programs using the 2D/3D accelerator of the SiS chip.\n"
-	  "The modes require a totally different way of programming the engines. If any\n"
-	  "mode than MMIO is selected, sisfb will disable its own 2D acceleration. On\n"
-	  "300/540/630/730, this option is ignored. (default: MMIO)");
-
-/* TW: "Import" the options from the X driver */
-MODULE_PARM(mem,    "i");
-MODULE_PARM_DESC(mem,
-	"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
-	  "for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
-	  "on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
-	  "the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
-	  "otherwise at 12288KB. On 315 and Xabre series, the heap is 1MB by default. The\n"
-	  "value is to be specified without 'KB' and should match the MaxXFBMem setting\n"
-	  "for XFree 4.x (x>=2).");
+	  "will be ignored (default: 60)\n");
 
-MODULE_PARM(forcecrt2type, "s");
+MODULE_PARM_DESC(forcecrt1,
+	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
+	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
+	  "0=CRT1 OFF) (default: [autodetected])\n");	  
+	  
 MODULE_PARM_DESC(forcecrt2type,
 	"\nIf this option is omitted, the driver autodetects CRT2 output devices, such as\n"
 	  "LCD, TV or secondary VGA. With this option, this autodetection can be\n"
 	  "overridden. Possible parameters are LCD, TV, VGA or NONE. NONE disables CRT2.\n"
 	  "On systems with a SiS video bridge, parameters SVIDEO, COMPOSITE or SCART can\n"
-	  "be used instead of TV to override the TV detection. (default: [autodetected])");
-
-MODULE_PARM(forcecrt1, "i");
-MODULE_PARM_DESC(forcecrt1,
-	"\nNormally, the driver autodetects whether or not CRT1 (external VGA) is \n"
-	  "connected. With this option, the detection can be overridden (1=CRT1 ON,\n"
-	  " 0=CRT1 off) (default: [autodetected])");
-
-MODULE_PARM(pdc, "i");
+	  "be used instead of TV to override the TV detection. Furthermore, on systems\n"
+	  "with a SiS video bridge, SVIDEO+COMPOSITE, HIVISION, YPBPR480I, YPBPR480P,\n"
+	  "YPBPR720P and YPBPR1080I are understood. However, whether or not these work\n"
+	  "depends on the very hardware in use. (default: [autodetected])\n");
+	  
+MODULE_PARM_DESC(scalelcd,
+	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
+	  "native resolution. Setting it to 0 will disable scaling; LVDS panels will\n"
+	  "show black bars around the image, TMDS panels will probably do the scaling\n"
+	  "themselves. Default: 1 on LVDS panels, 0 on TMDS panels\n");	
+	  
 MODULE_PARM_DESC(pdc,
         "\nThis is for manually selecting the LCD panel delay compensation. The driver\n"
 	  "should detect this correctly in most cases; however, sometimes this is not\n"
 	  "possible. If you see 'small waves' on the LCD, try setting this to 4, 32 or 24\n"
 	  "on a 300 series chipset; 6 on a 315 series chipset. If the problem persists,\n"
 	  "try other values (on 300 series: between 4 and 60 in steps of 4; on 315 series:\n"
-	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)");
+	  "any value from 0 to 31). (default: autodetected, if LCD is active during start)\n");
 
-MODULE_PARM(pdc1, "i");
+#ifdef CONFIG_FB_SIS_315	  
 MODULE_PARM_DESC(pdc1,
-        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315 series\n"
-	  "only. (default: autodetected if LCD is in LCD-via-CRT1 mode during startup)");
-
-MODULE_PARM(noaccel, "i");
-MODULE_PARM_DESC(noaccel,
-        "\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
-	  "(default: 0)");
-
-MODULE_PARM(noypan, "i");
-MODULE_PARM_DESC(noypan,
-        "\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
- 	  "will be performed by redrawing the screen. (default: 0)");
-
-MODULE_PARM(nomax, "i");
-MODULE_PARM_DESC(nomax,
-        "\nIf y-panning is enabled, sisfb will by default use the entire available video\n"
-	  "memory for the virtual screen in order to optimize scrolling performance. If\n"
-	  "this is set to anything other than 0, sisfb will not do this and thereby \n"
-	  "enable the user to positively specify a virtual Y size of the screen using\n"
-	  "fbset. (default: 0)\n");
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	
-MODULE_PARM(inverse, "i");
-MODULE_PARM_DESC(inverse,
-        "\nSetting this to anything but 0 should invert the display colors, but this\n"
-	  "does not seem to work. (default: 0)");
-#endif	
-
-MODULE_PARM(userom, "i");
-MODULE_PARM_DESC(userom,
-        "\nSetting this to 0 keeps sisfb from using the video BIOS data which is needed\n"
-	  "for some LCD and TV setup. (default: 1)");
-
-MODULE_PARM(useoem, "i");
-MODULE_PARM_DESC(useoem,
-        "\nSetting this to 0 keeps sisfb from using its internel OEM data for some LCD\n"
-	  "panels and TV connector types. (default: [auto])");
+        "\nThis is same as pdc, but for LCD-via CRT1. Hence, this is for the 315/330\n"
+	  "series only. (default: autodetected if LCD is in LCD-via-CRT1 mode during\n"
+	  "startup) - Note: currently, this has no effect because LCD-via-CRT1 is not\n"
+	  "implemented yet.\n");
+#endif
 
-MODULE_PARM(tvstandard, "s");
+MODULE_PARM_DESC(specialtiming,
+	"\nPlease refer to documentation for more information on this option.\n");
+
+MODULE_PARM_DESC(lvdshl,
+	"\nPlease refer to documentation for more information on this option.\n");	
+		  
 MODULE_PARM_DESC(tvstandard,
 	"\nThis allows overriding the BIOS default for the TV standard. Valid choices are\n"
-	  "pal and ntsc. (default: [auto])");
+	  "pal, ntsc, palm and paln. (default: [auto; pal or ntsc only])\n");	  
+
+MODULE_PARM_DESC(tvxposoffset,	  
+	"\nRelocate TV output horizontally. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");
+	
+MODULE_PARM_DESC(tvyposoffset,	  
+	"\nRelocate TV output vertically. Possible parameters: -32 through 32.\n"
+	  "Default: 0\n");	
+	  	  
+MODULE_PARM_DESC(filter,
+	"\nSelects TV flicker filter type (only for systems with a SiS301 video bridge).\n"
+	  "(Possible values 0-7, default: [no filter])\n");
 
-MODULE_PARM(nocrt2rate, "i");
 MODULE_PARM_DESC(nocrt2rate,
 	"\nSetting this to 1 will force the driver to use the default refresh rate for\n"
-	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)");
-
-MODULE_PARM(scalelcd, "i");
-MODULE_PARM_DESC(scalelcd,
-	"\nSetting this to 1 will force the driver to scale the LCD image to the panel's\n"
-	  "native resolution. Setting it to 0 will disable scaling; if the panel can\n"
-	  "scale by itself, it will probably do this, otherwise you will see a black bar\n"
-	  "around the screen image. Default: [autodetect if panel can scale]");
-
-MODULE_PARM(specialtiming, "s");
-
-MODULE_PARM(lvdshl, "i");
+	  "CRT2 if CRT2 type is VGA. (default: 0, use same rate as CRT1)\n");
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	 
+MODULE_PARM_DESC(inverse,
+        "\nSetting this to anything but 0 should invert the display colors, but this\n"
+	  "does not seem to work. (default: 0)\n");
+#endif
+	  
 #if !defined(__i386__) && !defined(__x86_64__)
-MODULE_PARM(resetcard, "i");
+#ifdef CONFIG_FB_SIS_300
 MODULE_PARM_DESC(resetcard,
 	"\nSet this to 1 in order to reset (POST) the card on non-x86 machines where\n"
 	  "the BIOS did not POST the card (only supported for SiS 300/305 currently).\n"
-	  "Default: 0");
-MODULE_PARM(videoram, "i");
+	  "Default: 0\n");
+
 MODULE_PARM_DESC(videoram,
 	"\nSet this to the amount of video RAM (in kilobyte) the card has. Required on\n"
 	  "some non-x86 architectures where the memory auto detection fails. Only\n"
-	  "relevant if resetcard is set, too. Default: [auto-detect]");
+	  "relevant if resetcard is set, too. Default: [auto-detect]\n");
+#endif	  
 #endif
 
 int __init sisfb_init_module(void)
 {
-	SiS_Pr.UsePanelScaler = -1;
-	SiS_Pr.CenterScreen = -1;
-	SiS_Pr.SiS_CustomT = CUT_NONE;
-	SiS_Pr.LVDSHL = -1;
+	sisfb_setdefaultparms();
 
-	ivideo.refresh_rate = sisfb_parm_rate = rate;
+	if(rate) sisfb_parm_rate = rate;
 
 	if((scalelcd == 0) || (scalelcd == 1)) {
-	   SiS_Pr.UsePanelScaler = scalelcd ^ 1;
+	   sisfb_scalelcd = scalelcd ^ 1;   
 	}
-
-	if(mode)
-		sisfb_search_mode(mode, FALSE);
-	else if(vesa != -1)
-		sisfb_search_vesamode(vesa, FALSE);
-	else
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		/* For 2.4, set mode=none if no mode is given  */
-		sisfb_mode_idx = MODE_INDEX_NONE;
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-		/* For 2.5, we don't need this "mode=none" stuff anymore */
-		sisfb_mode_idx = DEFAULT_MODE;
-#endif
-
+	
+	/* Need to check crt2 type first for fstn/dstn */
+	
 	if(forcecrt2type)
 		sisfb_search_crt2type(forcecrt2type);
 
 	if(tvstandard)
 		sisfb_search_tvstd(tvstandard);
 
-	if(crt1off == 0)
-		sisfb_crt1off = 1;
-	else
-		sisfb_crt1off = 0;
+	if(mode)
+		sisfb_search_mode(mode, FALSE);
+	else if(vesa != -1)
+		sisfb_search_vesamode(vesa, FALSE);
+
+	sisfb_crt1off = (crt1off == 0) ? 1 : 0;
 
 	sisfb_forcecrt1 = forcecrt1;
-	if(forcecrt1 == 1)
-		sisfb_crt1off = 0;
-	else if(forcecrt1 == 0)
-		sisfb_crt1off = 1;
+	if(forcecrt1 == 1)      sisfb_crt1off = 0;
+	else if(forcecrt1 == 0) sisfb_crt1off = 1;
 
 	if(noaccel == 1)      sisfb_accel = 0;
 	else if(noaccel == 0) sisfb_accel = 1;
@@ -5507,21 +5521,12 @@ int __init sisfb_init_module(void)
 	
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 	if(inverse)           sisfb_inverse = 1;
-	sisfb_fontname[0] = '\0';
 #endif
 
-	if(mem)		      sisfb_mem = mem;
-
-	sisfb_userom = userom;
-
-	sisfb_useoem = useoem;
-
-	if(queuemode)         sisfb_search_queuemode(queuemode);
+	if(mem)		      sisfb_parm_mem = mem;
 
-	/* If other queuemode than MMIO, disable 2D accel and ypan */
-	if((sisfb_queuemode != -1) && (sisfb_queuemode != MMIO_CMD)) {
-	        sisfb_accel = 0;
-	}
+	if(userom != -1)      sisfb_userom = userom;
+	if(useoem != -1)      sisfb_useoem = useoem;
 
         if(pdc != -1)  sisfb_pdc  = (pdc  & 0x7f);
 	if(pdc1 != -1) sisfb_pdca = (pdc1 & 0x1f);
@@ -5531,12 +5536,15 @@ int __init sisfb_init_module(void)
 	if(specialtiming)
 		sisfb_search_specialtiming(specialtiming);
 
-	if((lvdshl >= 0) && (lvdshl <= 3)) SiS_Pr.LVDSHL = lvdshl;
+	if((lvdshl >= 0) && (lvdshl <= 3))  sisfb_lvdshl = lvdshl;
+	
+	if(filter != -1) sisfb_filter = filter;
+	
+	sisfb_tvxposoffset = tvxposoffset;
+	sisfb_tvyposoffset = tvyposoffset;
 
 #if !defined(__i386__) && !defined(__x86_64__)
-        if(resetcard)   sisfb_resetcard = 1;
-	else		sisfb_resetcard = 0;
-
+ 	sisfb_resetcard = (resetcard) ? 1 : 0;
 	if(videoram)    sisfb_videoram = videoram;
 #endif
 
@@ -5556,7 +5564,5 @@ module_exit(sisfb_remove_module);
 
 EXPORT_SYMBOL(sis_malloc);
 EXPORT_SYMBOL(sis_free);
-EXPORT_SYMBOL(sis_dispinfo);
 
-EXPORT_SYMBOL(ivideo);
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/sis_main.h linux-2.4.27-rc4/drivers/video/sis/sis_main.h
--- linux-2.4.26/drivers/video/sis/sis_main.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/sis_main.h	2004-07-30 16:26:48.000000000 +0000
@@ -1,6 +1,7 @@
 /*
- * SiS 300/630/730/540/315/550/650/651/M650/661FX/M661FX/740/741/330/760
- * frame buffer driver for Linux kernels 2.4.x and 2.5.x
+ * SiS 300/305/540/630(S)/730(S)
+ * SiS 315(H/PRO)/55x/(M)65x/(M)661(F/M)X/740/741(GX)/330/(M)760
+ * frame buffer driver for Linux kernels >=2.4.14 and >=2.6.3
  *
  * Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
  *
@@ -22,335 +23,15 @@
 #ifndef _SISFB_MAIN
 #define _SISFB_MAIN
 
-#include "vstruct.h"
-
-/* ------------------- Constant Definitions ------------------------- */
-
-#define AGPOFF     /* default is turn off AGP */
-
-#define SISFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
-
-#define VER_MAJOR                 1
-#define VER_MINOR                 6
-#define VER_LEVEL                 32
+#include <linux/spinlock.h>
 
+#include "vstruct.h"
 #include "sis.h"
 
-/* To be included in pci_ids.h */
-#ifndef PCI_DEVICE_ID_SI_650_VGA
-#define PCI_DEVICE_ID_SI_650_VGA  0x6325
-#endif
-#ifndef PCI_DEVICE_ID_SI_650
-#define PCI_DEVICE_ID_SI_650      0x0650
-#endif
-#ifndef PCI_DEVICE_ID_SI_740
-#define PCI_DEVICE_ID_SI_740      0x0740
-#endif
-#ifndef PCI_DEVICE_ID_SI_330
-#define PCI_DEVICE_ID_SI_330      0x0330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660_VGA
-#define PCI_DEVICE_ID_SI_660_VGA  0x6330
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0661
-#endif
-#ifndef PCI_DEVICE_ID_SI_741
-#define PCI_DEVICE_ID_SI_741      0x0741
-#endif
-#ifndef PCI_DEVICE_ID_SI_660
-#define PCI_DEVICE_ID_SI_660      0x0660
-#endif
-#ifndef PCI_DEVICE_ID_SI_760
-#define PCI_DEVICE_ID_SI_760      0x0760
-#endif
-
-/* To be included in fb.h */
-#ifndef FB_ACCEL_SIS_GLAMOUR_2
-#define FB_ACCEL_SIS_GLAMOUR_2  40	/* SiS 315, 65x, 740, 661, 741  */
-#endif
-#ifndef FB_ACCEL_SIS_XABRE
-#define FB_ACCEL_SIS_XABRE      41	/* SiS 330 ("Xabre"), 760 	*/
-#endif
-
-#define MAX_ROM_SCAN              0x10000
-
-#define HW_CURSOR_CAP             0x80
-#define TURBO_QUEUE_CAP           0x40
-#define AGP_CMD_QUEUE_CAP         0x20
-#define VM_CMD_QUEUE_CAP          0x10
-#define MMIO_CMD_QUEUE_CAP        0x08
-
-/* For 300 series */
-#ifdef CONFIG_FB_SIS_300
-#define TURBO_QUEUE_AREA_SIZE     0x80000 /* 512K */
-#endif
-
-/* For 315/Xabre series */
-#ifdef CONFIG_FB_SIS_315
-#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD   0x1F
-#endif
-
-#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
-#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
-
-#define OH_ALLOC_SIZE             4000
-#define SENTINEL                  0x7fffffff
-
-#define SEQ_ADR                   0x14
-#define SEQ_DATA                  0x15
-#define DAC_ADR                   0x18
-#define DAC_DATA                  0x19
-#define CRTC_ADR                  0x24
-#define CRTC_DATA                 0x25
-#define DAC2_ADR                  (0x16-0x30)
-#define DAC2_DATA                 (0x17-0x30)
-#define VB_PART1_ADR              (0x04-0x30)
-#define VB_PART1_DATA             (0x05-0x30)
-#define VB_PART2_ADR              (0x10-0x30)
-#define VB_PART2_DATA             (0x11-0x30)
-#define VB_PART3_ADR              (0x12-0x30)
-#define VB_PART3_DATA             (0x13-0x30)
-#define VB_PART4_ADR              (0x14-0x30)
-#define VB_PART4_DATA             (0x15-0x30)
-
-#define SISSR			  SiS_Pr.SiS_P3c4
-#define SISCR                     SiS_Pr.SiS_P3d4
-#define SISDACA                   SiS_Pr.SiS_P3c8
-#define SISDACD                   SiS_Pr.SiS_P3c9
-#define SISPART1                  SiS_Pr.SiS_Part1Port
-#define SISPART2                  SiS_Pr.SiS_Part2Port
-#define SISPART3                  SiS_Pr.SiS_Part3Port
-#define SISPART4                  SiS_Pr.SiS_Part4Port
-#define SISPART5                  SiS_Pr.SiS_Part5Port
-#define SISDAC2A                  SISPART5
-#define SISDAC2D                  (SISPART5 + 1)
-#define SISMISCR                  (SiS_Pr.RelIO + 0x1c)
-#define SISMISCW                  SiS_Pr.SiS_P3c2
-#define SISINPSTAT		  (SiS_Pr.RelIO + 0x2a)
-#define SISPEL			  SiS_Pr.SiS_P3c6
-
-#define IND_SIS_PASSWORD          0x05  /* SRs */
-#define IND_SIS_COLOR_MODE        0x06
-#define IND_SIS_RAMDAC_CONTROL    0x07
-#define IND_SIS_DRAM_SIZE         0x14
-#define IND_SIS_SCRATCH_REG_16    0x16
-#define IND_SIS_SCRATCH_REG_17    0x17
-#define IND_SIS_SCRATCH_REG_1A    0x1A
-#define IND_SIS_MODULE_ENABLE     0x1E
-#define IND_SIS_PCI_ADDRESS_SET   0x20
-#define IND_SIS_TURBOQUEUE_ADR    0x26
-#define IND_SIS_TURBOQUEUE_SET    0x27
-#define IND_SIS_POWER_ON_TRAP     0x38
-#define IND_SIS_POWER_ON_TRAP2    0x39
-#define IND_SIS_CMDQUEUE_SET      0x26
-#define IND_SIS_CMDQUEUE_THRESHOLD  0x27
-
-#define IND_SIS_SCRATCH_REG_CR30  0x30  /* CRs */
-#define IND_SIS_SCRATCH_REG_CR31  0x31
-#define IND_SIS_SCRATCH_REG_CR32  0x32
-#define IND_SIS_SCRATCH_REG_CR33  0x33
-#define IND_SIS_LCD_PANEL         0x36
-#define IND_SIS_SCRATCH_REG_CR37  0x37
-#define IND_SIS_AGP_IO_PAD        0x48
-
-#define IND_BRI_DRAM_STATUS       0x63 /* PCI config memory size offset */
-
-#define MMIO_QUEUE_PHYBASE        0x85C0
-#define MMIO_QUEUE_WRITEPORT      0x85C4
-#define MMIO_QUEUE_READPORT       0x85C8
-
-#define SIS_CRT2_WENABLE_300 0x24
-#define SIS_CRT2_WENABLE_315 0x2F
-
-#define SIS_PASSWORD              0x86  /* SR05 */
-#define SIS_INTERLACED_MODE       0x20  /* SR06 */
-#define SIS_8BPP_COLOR_MODE       0x0
-#define SIS_15BPP_COLOR_MODE      0x1 
-#define SIS_16BPP_COLOR_MODE      0x2 
-#define SIS_32BPP_COLOR_MODE      0x4 
-#define SIS_DRAM_SIZE_MASK        0x3F  /* 300/630/730 SR14 */
-#define SIS_DRAM_SIZE_1MB         0x00
-#define SIS_DRAM_SIZE_2MB         0x01
-#define SIS_DRAM_SIZE_4MB         0x03
-#define SIS_DRAM_SIZE_8MB         0x07
-#define SIS_DRAM_SIZE_16MB        0x0F
-#define SIS_DRAM_SIZE_32MB        0x1F
-#define SIS_DRAM_SIZE_64MB        0x3F
-#define SIS_DATA_BUS_MASK         0xC0
-#define SIS_DATA_BUS_32           0x00
-#define SIS_DATA_BUS_64           0x01
-#define SIS_DATA_BUS_128          0x02
-
-#define SIS315_DATA_BUS_MASK      0x02
-#define SIS315_DATA_BUS_64        0x00
-#define SIS315_DATA_BUS_128       0x01
-#define SIS315_DUAL_CHANNEL_MASK  0x0C
-#define SIS315_SINGLE_CHANNEL_1_RANK  	0x00
-#define SIS315_SINGLE_CHANNEL_2_RANK  	0x01
-#define SIS315_ASYM_DDR		  	0x02
-#define SIS315_DUAL_CHANNEL_1_RANK    	0x03
-
-#define SIS_SCRATCH_REG_1A_MASK   0x10
-
-#define SIS_ENABLE_2D             0x40  /* SR1E */
-
-#define SIS_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
-#define SIS_PCI_ADDR_ENABLE       0x80
-
-#define SIS_AGP_CMDQUEUE_ENABLE   0x80  /* 315/650/740 SR26 */
-#define SIS_VRAM_CMDQUEUE_ENABLE  0x40
-#define SIS_MMIO_CMD_ENABLE       0x20
-#define SIS_CMD_QUEUE_SIZE_512k   0x00
-#define SIS_CMD_QUEUE_SIZE_1M     0x04
-#define SIS_CMD_QUEUE_SIZE_2M     0x08
-#define SIS_CMD_QUEUE_SIZE_4M     0x0C
-#define SIS_CMD_QUEUE_RESET       0x01
-#define SIS_CMD_AUTO_CORR	  0x02
-
-#define SIS_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
-#define SIS_MODE_SELECT_CRT2      0x02
-#define SIS_VB_OUTPUT_COMPOSITE   0x04
-#define SIS_VB_OUTPUT_SVIDEO      0x08
-#define SIS_VB_OUTPUT_SCART       0x10
-#define SIS_VB_OUTPUT_LCD         0x20
-#define SIS_VB_OUTPUT_CRT2        0x40
-#define SIS_VB_OUTPUT_HIVISION    0x80
-
-#define SIS_VB_OUTPUT_DISABLE     0x20  /* CR31 */
-#define SIS_DRIVER_MODE           0x40
-
-#define SIS_VB_COMPOSITE          0x01  /* CR32 */
-#define SIS_VB_SVIDEO             0x02
-#define SIS_VB_SCART              0x04
-#define SIS_VB_LCD                0x08
-#define SIS_VB_CRT2               0x10
-#define SIS_CRT1                  0x20
-#define SIS_VB_HIVISION           0x40
-#define SIS_VB_DVI                0x80
-#define SIS_VB_TV                 (SIS_VB_COMPOSITE | SIS_VB_SVIDEO | \
-                                   SIS_VB_SCART | SIS_VB_HIVISION)
-
-#define SIS_EXTERNAL_CHIP_MASK    	   0x0E  /* CR37 (< SiS 660) */
-#define SIS_EXTERNAL_CHIP_SIS301           0x01  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS             0x02  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_TRUMPION         0x03  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_LVDS_CHRONTEL    0x04  /* in CR37 << 1 ! */
-#define SIS_EXTERNAL_CHIP_CHRONTEL         0x05  /* in CR37 << 1 ! */
-#define SIS310_EXTERNAL_CHIP_LVDS          0x02  /* in CR37 << 1 ! */
-#define SIS310_EXTERNAL_CHIP_LVDS_CHRONTEL 0x03  /* in CR37 << 1 ! */
-
-#define SIS_AGP_2X                0x20  /* CR48 */
-
-#define BRI_DRAM_SIZE_MASK        0x70  /* PCI bridge config data */
-#define BRI_DRAM_SIZE_2MB         0x00
-#define BRI_DRAM_SIZE_4MB         0x01
-#define BRI_DRAM_SIZE_8MB         0x02
-#define BRI_DRAM_SIZE_16MB        0x03
-#define BRI_DRAM_SIZE_32MB        0x04
-#define BRI_DRAM_SIZE_64MB        0x05
-
-#define HW_DEVICE_EXTENSION	  SIS_HW_INFO
-#define PHW_DEVICE_EXTENSION      PSIS_HW_INFO
-
-#define SR_BUFFER_SIZE            5
-#define CR_BUFFER_SIZE            5
-
-/* entries for disp_state - deprecated as of 1.6.02 */
-#define DISPTYPE_CRT1       0x00000008L
-#define DISPTYPE_CRT2       0x00000004L
-#define DISPTYPE_LCD        0x00000002L
-#define DISPTYPE_TV         0x00000001L
-#define DISPTYPE_DISP1      DISPTYPE_CRT1
-#define DISPTYPE_DISP2      (DISPTYPE_CRT2 | DISPTYPE_LCD | DISPTYPE_TV)
-#define DISPMODE_SINGLE	    0x00000020L
-#define DISPMODE_MIRROR	    0x00000010L
-#define DISPMODE_DUALVIEW   0x00000040L
-
-/* Deprecated as of 1.6.02 - use vbflags instead */
-#define HASVB_NONE      	0x00
-#define HASVB_301       	0x01
-#define HASVB_LVDS      	0x02
-#define HASVB_TRUMPION  	0x04
-#define HASVB_LVDS_CHRONTEL	0x10
-#define HASVB_302       	0x20
-#define HASVB_303       	0x40
-#define HASVB_CHRONTEL  	0x80
-
-/* Useful macros */
-#define inSISREG(base)          inb(base)
-#define outSISREG(base,val)     outb(val,base)
-#define orSISREG(base,val)      do { \
-                                  unsigned char __Temp = inb(base); \
-                                  outSISREG(base, __Temp | (val)); \
-                                } while (0)
-#define andSISREG(base,val)     do { \
-                                  unsigned char __Temp = inb(base); \
-                                  outSISREG(base, __Temp & (val)); \
-                                } while (0)
-#define inSISIDXREG(base,idx,var)   do { \
-                                      outb(idx,base); var=inb((base)+1); \
-                                    } while (0)
-#define outSISIDXREG(base,idx,val)  do { \
-                                      outb(idx,base); outb((val),(base)+1); \
-                                    } while (0)
-#define orSISIDXREG(base,idx,val)   do { \
-                                      unsigned char __Temp; \
-                                      outb(idx,base);   \
-                                      __Temp = inb((base)+1)|(val); \
-                                      outSISIDXREG(base,idx,__Temp); \
-                                    } while (0)
-#define andSISIDXREG(base,idx,and)  do { \
-                                      unsigned char __Temp; \
-                                      outb(idx,base);   \
-                                      __Temp = inb((base)+1)&(and); \
-                                      outSISIDXREG(base,idx,__Temp); \
-                                    } while (0)
-#define setSISIDXREG(base,idx,and,or)   do { \
-                                          unsigned char __Temp; \
-                                          outb(idx,base);   \
-                                          __Temp = (inb((base)+1)&(and))|(or); \
-                                          outSISIDXREG(base,idx,__Temp); \
-                                        } while (0)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* Offscreen layout */
-typedef struct _SIS_GLYINFO {
-	unsigned char ch;
-	int fontwidth;
-	int fontheight;
-	u8 gmask[72];
-	int ngmask;
-} SIS_GLYINFO;
-
-static char sisfb_fontname[40];
-#endif
-
-typedef struct _SIS_OH {
-	struct _SIS_OH *poh_next;
-	struct _SIS_OH *poh_prev;
-	unsigned long offset;
-	unsigned long size;
-} SIS_OH;
-
-typedef struct _SIS_OHALLOC {
-	struct _SIS_OHALLOC *poha_next;
-	SIS_OH aoh[1];
-} SIS_OHALLOC;
-
-typedef struct _SIS_HEAP {
-	SIS_OH oh_free;
-	SIS_OH oh_used;
-	SIS_OH *poh_freelist;
-	SIS_OHALLOC *poha_chain;
-	unsigned long max_freesize;
-} SIS_HEAP;
+#define MODE_INDEX_NONE           0  /* index for mode=none */
 
 /* Fbcon stuff */
-static struct fb_info *sis_fb_info;
-
-static struct fb_var_screeninfo default_var = {
+static struct fb_var_screeninfo my_default_var = {
 	.xres            = 0,
 	.yres            = 0,
 	.xres_virtual    = 0,
@@ -377,103 +58,71 @@ static struct fb_var_screeninfo default_
 	.vsync_len       = 0,
 	.sync            = 0,
 	.vmode           = FB_VMODE_NONINTERLACED,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	.reserved        = {0, 0, 0, 0, 0, 0}
-#endif
 };
 
+/* Boot-time parameters */
+static int sisfb_off = 0;
+static int sisfb_parm_mem = 0;
+static int sisfb_accel = -1;
+static int sisfb_ypan = -1;
+static int sisfb_max = -1;
+static int sisfb_userom = 1;
+static int sisfb_useoem = -1;
+#ifdef MODULE
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static struct fb_fix_screeninfo sisfb_fix = {
-	.id		= "SiS",
-	.type		= FB_TYPE_PACKED_PIXELS,
-	.xpanstep	= 0,
-	.ypanstep	= 1,
-};
-static char myid[40];
-static u32 pseudo_palette[17];
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-static struct display sis_disp;
-
-static struct display_switch sisfb_sw;	
-
-static struct {
-	u16 blue, green, red, pad;
-} sis_palette[256];
-
-static union {
-#ifdef FBCON_HAS_CFB16
-	u16 cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-	u32 cfb32[16];
+static int sisfb_mode_idx = -1;
+#else
+static int sisfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
 #endif
-} sis_fbcon_cmap;
-
-static int sisfb_inverse = 0;
-static int currcon = 0;
+#else
+static int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
 #endif
-
-static int sisfb_off = 0;
+static int sisfb_parm_rate = -1;
 static int sisfb_crt1off = 0;
 static int sisfb_forcecrt1 = -1;
 static int sisfb_crt2type  = -1;	/* CRT2 type (for overriding autodetection) */
-static int sisfb_tvplug    = -1;	/* Tv plug type (for overriding autodetection) */
-static int sisfb_userom = 1;
-static int sisfb_useoem = -1;
-static int sisfb_parm_rate = -1;
-static int sisfb_mem = 0;
+static int sisfb_crt2flags = 0;
 static int sisfb_pdc = 0xff;
 static int sisfb_pdca = 0xff;
-static int sisfb_ypan = -1;
-static int sisfb_max = -1;
-static int sisfb_nocrt2rate = 0;
+static int sisfb_scalelcd = -1;
+static int sisfb_specialtiming = CUT_NONE;
+static int sisfb_lvdshl = -1;
 static int sisfb_dstn = 0;
 static int sisfb_fstn = 0;
-int 	   sisfb_accel = -1;
-int 	   sisfb_queuemode = -1; 	/* Use MMIO queue mode by default (315 series only) */
+static int sisfb_tvplug = -1;		/* Tv plug type (for overriding autodetection) */
+static int sisfb_tvstd  = -1;
+static int sisfb_tvxposoffset = 0;
+static int sisfb_tvyposoffset = 0;
+static int sisfb_filter = -1;
+static int sisfb_nocrt2rate = 0;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+static int  sisfb_inverse = 0;
+static char sisfb_fontname[40];
+#endif
 #if !defined(__i386__) && !defined(__x86_64__)
 static int sisfb_resetcard = 0;
 static int sisfb_videoram = 0;
 #endif
 
-/* data for sis hardware ("par") */
-struct video_info ivideo;
-
-/* For ioctl SISFB_GET_INFO */
-sisfb_info sisfbinfo;
-
-/* Hardware info; contains data on hardware */
-SIS_HW_INFO sishw_ext;
-
-/* SiS private structure */
-SiS_Private  SiS_Pr;
-
-typedef enum _SIS_CMDTYPE {
-	MMIO_CMD = 0,
-	AGP_CMD_QUEUE,
-	VM_CMD_QUEUE,
-} SIS_CMDTYPE;
-
 /* List of supported chips */
 static struct sisfb_chip_info {
         int 		chip;
-	VGA_ENGINE 	vgaengine;
+	int 		vgaengine;
+	int		mni;
 	int 		hwcursor_size;
 	int		CRT2_write_enable;
 	const char 	*chip_name;
 } sisfb_chip_info[] __devinitdata = {
-	{ SIS_300,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
-	{ SIS_540,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
-	{ SIS_630,    SIS_300_VGA, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
-	{ SIS_315H,   SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
-	{ SIS_315,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
-	{ SIS_315PRO, SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
-	{ SIS_550,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
-	{ SIS_650,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 65x" },
-	{ SIS_330,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
-	{ SIS_660,    SIS_315_VGA, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
+	{ SIS_300,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 300/305" },
+	{ SIS_540,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 540" },
+	{ SIS_630,    SIS_300_VGA, 0, HW_CURSOR_AREA_SIZE_300 * 2, SIS_CRT2_WENABLE_300, "SiS 630" },
+	{ SIS_315H,   SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315H" },
+	{ SIS_315,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315" },
+	{ SIS_315PRO, SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 315PRO" },
+	{ SIS_550,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 55x" },
+	{ SIS_650,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 650" },
+	{ SIS_330,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 330" },
+	{ SIS_660,    SIS_315_VGA, 1, HW_CURSOR_AREA_SIZE_315 * 4, SIS_CRT2_WENABLE_315, "SiS 660" },
 };
 
 static struct pci_device_id __devinitdata sisfb_pci_table[] = {
@@ -493,16 +142,26 @@ static struct pci_device_id __devinitdat
 #endif
 	{ 0 }
 };
+
 MODULE_DEVICE_TABLE(pci, sisfb_pci_table);
 
+static struct sis_video_info *card_list = NULL;
+
+/* TODO: This is not handled card-wise because the DRM
+   does not refer to a unique fb when calling sis_alloc
+   or sis_free. Therefore, this is handled globally for
+   now (hoping that nobody is crazy enough to run two
+   SiS cards at the same time).
+ */
+SIS_HEAP       	sisfb_heap;
+
 #define MD_SIS300 1
 #define MD_SIS315 2
 
 /* Mode table */
-/* NOT const - will be patched for 1280x768 mode number chaos reasons */
-struct _sisbios_mode {
+static const struct _sisbios_mode {
 	char name[15];
-	u8 mode_no;
+	u8 mode_no[2];
 	u16 vesa_mode_no_1;  /* "SiS defined" VESA mode number */
 	u16 vesa_mode_no_2;  /* Real VESA mode numbers */
 	u16 xres;
@@ -513,202 +172,223 @@ struct _sisbios_mode {
 	u16 rows;
 	u8  chipset;
 } sisbios_mode[] = {
-#define MODE_INDEX_NONE           0  /* index for mode=none */
-	{"none",         0xff, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
-	{"320x200x8",    0x59, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x200x16",   0x41, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x200x24",   0x4f, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* TW: That's for people who mix up color- and fb depth */
-	{"320x200x32",   0x4f, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
-	{"320x240x8",    0x50, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x16",   0x56, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x24",   0x53, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x32",   0x53, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
-	{"320x240x8",    0x5a, 0x0132, 0x0000,  320,  480,  8, 1,  40, 30,           MD_SIS315},  /* TW: FSTN */
-	{"320x240x16",   0x5b, 0x0135, 0x0000,  320,  480, 16, 1,  40, 30,           MD_SIS315},  /* TW: FSTN */
-	{"400x300x8",    0x51, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x16",   0x57, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x24",   0x54, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"400x300x32",   0x54, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
-	{"512x384x8",    0x52, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x16",   0x58, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x24",   0x5c, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"512x384x32",   0x5c, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
-	{"640x400x8",    0x2f, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x16",   0x5d, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x24",   0x5e, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x400x32",   0x5e, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
-	{"640x480x8",    0x2e, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x16",   0x44, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x24",   0x62, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"640x480x32",   0x62, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
-	{"720x480x8",    0x31, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x16",   0x33, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x24",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x480x32",   0x35, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
-	{"720x576x8",    0x32, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x16",   0x34, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x24",   0x36, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"720x576x32",   0x36, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
-	{"768x576x8",    0x5f, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x16",   0x60, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x24",   0x61, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"768x576x32",   0x61, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
-	{"800x480x8",    0x70, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x16",   0x7a, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x24",   0x76, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
-	{"800x480x32",   0x76, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+/*0*/	{"none",         {0xff,0xff}, 0x0000, 0x0000,    0,    0,  0, 0,   0,  0, MD_SIS300|MD_SIS315},
+	{"320x200x8",    {0x59,0x59}, 0x0138, 0x0000,  320,  200,  8, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x16",   {0x41,0x41}, 0x010e, 0x0000,  320,  200, 16, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x200x24",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},  /* That's for people who mix up color- and fb depth */
+	{"320x200x32",   {0x4f,0x4f}, 0x0000, 0x0000,  320,  200, 32, 1,  40, 12, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x50,0x50}, 0x0132, 0x0000,  320,  240,  8, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x16",   {0x56,0x56}, 0x0135, 0x0000,  320,  240, 16, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x24",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x32",   {0x53,0x53}, 0x0000, 0x0000,  320,  240, 32, 1,  40, 15, MD_SIS300|MD_SIS315},
+	{"320x240x8",    {0x5a,0x5a}, 0x0132, 0x0000,  320,  480,  8, 1,  40, 30,           MD_SIS315},  /* FSTN */
+/*10*/	{"320x240x16",   {0x5b,0x5b}, 0x0135, 0x0000,  320,  480, 16, 1,  40, 30,           MD_SIS315},  /* FSTN */
+	{"400x300x8",    {0x51,0x51}, 0x0133, 0x0000,  400,  300,  8, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x16",   {0x57,0x57}, 0x0136, 0x0000,  400,  300, 16, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x24",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"400x300x32",   {0x54,0x54}, 0x0000, 0x0000,  400,  300, 32, 1,  50, 18, MD_SIS300|MD_SIS315},
+	{"512x384x8",    {0x52,0x52}, 0x0000, 0x0000,  512,  384,  8, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x16",   {0x58,0x58}, 0x0000, 0x0000,  512,  384, 16, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x24",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"512x384x32",   {0x5c,0x5c}, 0x0000, 0x0000,  512,  384, 32, 1,  64, 24, MD_SIS300|MD_SIS315},
+	{"640x400x8",    {0x2f,0x2f}, 0x0000, 0x0000,  640,  400,  8, 1,  80, 25, MD_SIS300|MD_SIS315},
+/*20*/	{"640x400x16",   {0x5d,0x5d}, 0x0000, 0x0000,  640,  400, 16, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x24",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x400x32",   {0x5e,0x5e}, 0x0000, 0x0000,  640,  400, 32, 1,  80, 25, MD_SIS300|MD_SIS315},
+	{"640x480x8",    {0x2e,0x2e}, 0x0101, 0x0101,  640,  480,  8, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x16",   {0x44,0x44}, 0x0111, 0x0111,  640,  480, 16, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x24",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"640x480x32",   {0x62,0x62}, 0x013a, 0x0112,  640,  480, 32, 1,  80, 30, MD_SIS300|MD_SIS315},
+	{"720x480x8",    {0x31,0x31}, 0x0000, 0x0000,  720,  480,  8, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x16",   {0x33,0x33}, 0x0000, 0x0000,  720,  480, 16, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x480x24",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+/*30*/	{"720x480x32",   {0x35,0x35}, 0x0000, 0x0000,  720,  480, 32, 1,  90, 30, MD_SIS300|MD_SIS315},
+	{"720x576x8",    {0x32,0x32}, 0x0000, 0x0000,  720,  576,  8, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x16",   {0x34,0x34}, 0x0000, 0x0000,  720,  576, 16, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x24",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"720x576x32",   {0x36,0x36}, 0x0000, 0x0000,  720,  576, 32, 1,  90, 36, MD_SIS300|MD_SIS315},
+	{"768x576x8",    {0x5f,0x5f}, 0x0000, 0x0000,  768,  576,  8, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x16",   {0x60,0x60}, 0x0000, 0x0000,  768,  576, 16, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x24",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"768x576x32",   {0x61,0x61}, 0x0000, 0x0000,  768,  576, 32, 1,  96, 36, MD_SIS300|MD_SIS315},
+	{"800x480x8",    {0x70,0x70}, 0x0000, 0x0000,  800,  480,  8, 1, 100, 30, MD_SIS300|MD_SIS315},
+/*40*/	{"800x480x16",   {0x7a,0x7a}, 0x0000, 0x0000,  800,  480, 16, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x24",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
+	{"800x480x32",   {0x76,0x76}, 0x0000, 0x0000,  800,  480, 32, 1, 100, 30, MD_SIS300|MD_SIS315},
 #define DEFAULT_MODE              43 /* index for 800x600x8 */
 #define DEFAULT_LCDMODE           43 /* index for 800x600x8 */
 #define DEFAULT_TVMODE            43 /* index for 800x600x8 */
-	{"800x600x8",    0x30, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x16",   0x47, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x24",   0x63, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"800x600x32",   0x63, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
-	{"848x480x8",    0x39, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x16",   0x3b, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x24",   0x3e, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"848x480x32",   0x3e, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
-	{"856x480x8",    0x3f, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x16",   0x42, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x24",   0x45, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"856x480x32",   0x45, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
-	{"1024x576x8",   0x71, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x16",  0x74, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x24",  0x77, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x576x32",  0x77, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
-	{"1024x600x8",   0x20, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
-	{"1024x600x16",  0x21, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
-	{"1024x600x24",  0x22, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
-	{"1024x600x32",  0x22, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
-	{"1024x768x8",   0x38, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x16",  0x4a, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x24",  0x64, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1024x768x32",  0x64, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
-	{"1152x768x8",   0x23, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
-	{"1152x768x16",  0x24, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
-	{"1152x768x24",  0x25, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
-	{"1152x768x32",  0x25, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
-	{"1152x864x8",   0x29, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x16",  0x2a, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x24",  0x2b, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1152x864x32",  0x2b, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
-	{"1280x720x8",   0x79, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x16",  0x75, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x24",  0x78, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
-	{"1280x720x32",  0x78, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
-#define MODEINDEX_1280x768 79
-	{"1280x768x8",   0x23, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x16",  0x24, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x24",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x768x32",  0x25, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
-	{"1280x800x8",   0x14, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
-	{"1280x800x16",  0x15, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
-	{"1280x800x24",  0x16, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
-	{"1280x800x32",  0x16, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
-	{"1280x960x8",   0x7c, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x16",  0x7d, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x24",  0x7e, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x960x32",  0x7e, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
-	{"1280x1024x8",  0x3a, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x16", 0x4d, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x24", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1280x1024x32", 0x65, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
-	{"1360x768x8",   0x48, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x16",  0x4b, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x24",  0x4e, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x768x32",  0x4e, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
-	{"1360x1024x8",  0x67, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x16", 0x6f, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x24", 0x72, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-	{"1360x1024x32", 0x72, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
-	{"1400x1050x8",  0x26, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x16", 0x27, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x24", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
-	{"1400x1050x32", 0x28, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
-	{"1600x1200x8",  0x3c, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x16", 0x3d, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x24", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1600x1200x32", 0x66, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
-	{"1680x1050x8",  0x17, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x16", 0x18, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x24", 0x19, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
-	{"1680x1050x32", 0x19, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
-	{"1920x1440x8",  0x68, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x16", 0x69, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x24", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"1920x1440x32", 0x6b, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
-	{"2048x1536x8",  0x6c, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x16", 0x6d, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x24", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
-	{"2048x1536x32", 0x6e, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
-	{"\0", 0x00, 0, 0, 0, 0, 0, 0, 0}
+	{"800x600x8",    {0x30,0x30}, 0x0103, 0x0103,  800,  600,  8, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x16",   {0x47,0x47}, 0x0114, 0x0114,  800,  600, 16, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x24",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"800x600x32",   {0x63,0x63}, 0x013b, 0x0115,  800,  600, 32, 2, 100, 37, MD_SIS300|MD_SIS315},
+	{"848x480x8",    {0x39,0x39}, 0x0000, 0x0000,  848,  480,  8, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x16",   {0x3b,0x3b}, 0x0000, 0x0000,  848,  480, 16, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"848x480x24",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+/*50*/	{"848x480x32",   {0x3e,0x3e}, 0x0000, 0x0000,  848,  480, 32, 2, 106, 30, MD_SIS300|MD_SIS315},
+	{"856x480x8",    {0x3f,0x3f}, 0x0000, 0x0000,  856,  480,  8, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x16",   {0x42,0x42}, 0x0000, 0x0000,  856,  480, 16, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x24",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"856x480x32",   {0x45,0x45}, 0x0000, 0x0000,  856,  480, 32, 2, 107, 30, MD_SIS300|MD_SIS315},
+	{"1024x576x8",   {0x71,0x71}, 0x0000, 0x0000, 1024,  576,  8, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x16",  {0x74,0x74}, 0x0000, 0x0000, 1024,  576, 16, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x24",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x576x32",  {0x77,0x77}, 0x0000, 0x0000, 1024,  576, 32, 1, 128, 36, MD_SIS300|MD_SIS315},
+	{"1024x600x8",   {0x20,0x20}, 0x0000, 0x0000, 1024,  600,  8, 1, 128, 37, MD_SIS300          },
+/*60*/	{"1024x600x16",  {0x21,0x21}, 0x0000, 0x0000, 1024,  600, 16, 1, 128, 37, MD_SIS300          },
+	{"1024x600x24",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x600x32",  {0x22,0x22}, 0x0000, 0x0000, 1024,  600, 32, 1, 128, 37, MD_SIS300          },
+	{"1024x768x8",   {0x38,0x38}, 0x0105, 0x0105, 1024,  768,  8, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x16",  {0x4a,0x4a}, 0x0117, 0x0117, 1024,  768, 16, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x24",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1024x768x32",  {0x64,0x64}, 0x013c, 0x0118, 1024,  768, 32, 2, 128, 48, MD_SIS300|MD_SIS315},
+	{"1152x768x8",   {0x23,0x23}, 0x0000, 0x0000, 1152,  768,  8, 1, 144, 48, MD_SIS300          },
+	{"1152x768x16",  {0x24,0x24}, 0x0000, 0x0000, 1152,  768, 16, 1, 144, 48, MD_SIS300          },
+	{"1152x768x24",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+/*70*/	{"1152x768x32",  {0x25,0x25}, 0x0000, 0x0000, 1152,  768, 32, 1, 144, 48, MD_SIS300          },
+	{"1152x864x8",   {0x29,0x29}, 0x0000, 0x0000, 1152,  864,  8, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x16",  {0x2a,0x2a}, 0x0000, 0x0000, 1152,  864, 16, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x24",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1152x864x32",  {0x2b,0x2b}, 0x0000, 0x0000, 1152,  864, 32, 1, 144, 54, MD_SIS300|MD_SIS315},
+	{"1280x720x8",   {0x79,0x79}, 0x0000, 0x0000, 1280,  720,  8, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x16",  {0x75,0x75}, 0x0000, 0x0000, 1280,  720, 16, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x24",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x720x32",  {0x78,0x78}, 0x0000, 0x0000, 1280,  720, 32, 1, 160, 45, MD_SIS300|MD_SIS315},
+	{"1280x768x8",   {0x55,0x23}, 0x0000, 0x0000, 1280,  768,  8, 1, 160, 48, MD_SIS300|MD_SIS315},
+/*80*/	{"1280x768x16",  {0x5a,0x24}, 0x0000, 0x0000, 1280,  768, 16, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x24",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x768x32",  {0x5b,0x25}, 0x0000, 0x0000, 1280,  768, 32, 1, 160, 48, MD_SIS300|MD_SIS315},
+	{"1280x800x8",   {0x14,0x14}, 0x0000, 0x0000, 1280,  800,  8, 1, 160, 50,           MD_SIS315},
+	{"1280x800x16",  {0x15,0x15}, 0x0000, 0x0000, 1280,  800, 16, 1, 160, 50,           MD_SIS315},
+	{"1280x800x24",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x800x32",  {0x16,0x16}, 0x0000, 0x0000, 1280,  800, 32, 1, 160, 50,           MD_SIS315},
+	{"1280x960x8",   {0x7c,0x7c}, 0x0000, 0x0000, 1280,  960,  8, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x16",  {0x7d,0x7d}, 0x0000, 0x0000, 1280,  960, 16, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x960x24",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+/*90*/	{"1280x960x32",  {0x7e,0x7e}, 0x0000, 0x0000, 1280,  960, 32, 1, 160, 60, MD_SIS300|MD_SIS315},
+	{"1280x1024x8",  {0x3a,0x3a}, 0x0107, 0x0107, 1280, 1024,  8, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x16", {0x4d,0x4d}, 0x011a, 0x011a, 1280, 1024, 16, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x24", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1280x1024x32", {0x65,0x65}, 0x013d, 0x011b, 1280, 1024, 32, 2, 160, 64, MD_SIS300|MD_SIS315},
+	{"1360x768x8",   {0x48,0x48}, 0x0000, 0x0000, 1360,  768,  8, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x16",  {0x4b,0x4b}, 0x0000, 0x0000, 1360,  768, 16, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x24",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x768x32",  {0x4e,0x4e}, 0x0000, 0x0000, 1360,  768, 32, 1, 170, 48, MD_SIS300|MD_SIS315},
+	{"1360x1024x8",  {0x67,0x67}, 0x0000, 0x0000, 1360, 1024,  8, 1, 170, 64, MD_SIS300          },
+/*100*/	{"1360x1024x16", {0x6f,0x6f}, 0x0000, 0x0000, 1360, 1024, 16, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x24", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1360x1024x32", {0x72,0x72}, 0x0000, 0x0000, 1360, 1024, 32, 1, 170, 64, MD_SIS300          },
+	{"1400x1050x8",  {0x26,0x26}, 0x0000, 0x0000, 1400, 1050,  8, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x16", {0x27,0x27}, 0x0000, 0x0000, 1400, 1050, 16, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x24", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1400x1050x32", {0x28,0x28}, 0x0000, 0x0000, 1400, 1050, 32, 1, 175, 65,           MD_SIS315},
+	{"1600x1200x8",  {0x3c,0x3c}, 0x0130, 0x011c, 1600, 1200,  8, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x16", {0x3d,0x3d}, 0x0131, 0x011e, 1600, 1200, 16, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1600x1200x24", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+/*110*/	{"1600x1200x32", {0x66,0x66}, 0x013e, 0x011f, 1600, 1200, 32, 1, 200, 75, MD_SIS300|MD_SIS315},
+	{"1680x1050x8",  {0x17,0x17}, 0x0000, 0x0000, 1680, 1050,  8, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x16", {0x18,0x18}, 0x0000, 0x0000, 1680, 1050, 16, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x24", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1680x1050x32", {0x19,0x19}, 0x0000, 0x0000, 1680, 1050, 32, 1, 210, 65,           MD_SIS315},
+	{"1920x1440x8",  {0x68,0x68}, 0x013f, 0x0000, 1920, 1440,  8, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x16", {0x69,0x69}, 0x0140, 0x0000, 1920, 1440, 16, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x24", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"1920x1440x32", {0x6b,0x6b}, 0x0141, 0x0000, 1920, 1440, 32, 1, 240, 75, MD_SIS300|MD_SIS315},
+	{"2048x1536x8",  {0x6c,0x6c}, 0x0000, 0x0000, 2048, 1536,  8, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x16", {0x6d,0x6d}, 0x0000, 0x0000, 2048, 1536, 16, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x24", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"2048x1536x32", {0x6e,0x6e}, 0x0000, 0x0000, 2048, 1536, 32, 1, 256, 96,           MD_SIS315},
+	{"\0", {0x00,0x00}, 0, 0, 0, 0, 0, 0, 0}
+};
+
+#define SIS_LCD_NUMBER 17
+static const struct _sis_lcd_data {
+	u32 lcdtype;
+	u16 xres; 
+	u16 yres; 
+	u8  default_mode_idx;
+} sis_lcd_data[] = {
+	{ LCD_640x480,    640,  480,  23 },
+	{ LCD_800x600,    800,  600,  43 },
+	{ LCD_1024x600,  1024,  600,  59 },
+	{ LCD_1024x768,  1024,  768,  63 },
+	{ LCD_1152x768,  1152,  768,  67 },
+	{ LCD_1152x864,  1152,  864,  71 },
+	{ LCD_1280x720,  1280,  720,  75 },
+	{ LCD_1280x768,  1280,  768,  79 },
+	{ LCD_1280x800,  1280,  800,  83 },
+	{ LCD_1280x960,  1280,  960,  87 },
+	{ LCD_1280x1024, 1280, 1024,  91 },
+	{ LCD_1400x1050, 1400, 1050, 103 },
+	{ LCD_1680x1050, 1680, 1050, 111 },
+	{ LCD_1600x1200, 1600, 1200, 107 },
+	{ LCD_640x480_2,  640,  480,  23 },
+	{ LCD_640x480_3,  640,  480,  23 },
+	{ LCD_320x480,    320,  480,   9 },
 };
 
-/* mode-related variables */
-#ifdef MODULE
-int sisfb_mode_idx = MODE_INDEX_NONE;  /* Don't use a mode by default if we are a module */
-#else
-int sisfb_mode_idx = -1;               /* Use a default mode if we are inside the kernel */
-#endif
-
 /* CR36 evaluation */
 const USHORT sis300paneltype[] =
     { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
       LCD_1280x960,  LCD_640x480,   LCD_1024x600,  LCD_1152x768,
-      LCD_1024x768,  LCD_1024x768,  LCD_1024x768,  LCD_1024x768,
-      LCD_1024x768,  LCD_1024x768,  LCD_320x480,   LCD_1024x768 };
+      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,
+      LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN,   LCD_UNKNOWN };
 
 const USHORT sis310paneltype[] =
     { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
       LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
       LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-      LCD_640x480_2, LCD_640x480_3, LCD_320x480,   LCD_1024x768 };
+      LCD_640x480_2, LCD_640x480_3, LCD_UNKNOWN,   LCD_UNKNOWN };
 
 const USHORT sis661paneltype[] =
     { LCD_UNKNOWN,   LCD_800x600,   LCD_1024x768,  LCD_1280x1024,
       LCD_640x480,   LCD_1024x600,  LCD_1152x864,  LCD_1280x960,
       LCD_1152x768,  LCD_1400x1050, LCD_1280x768,  LCD_1600x1200,
-      LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_1024x768 };
+      LCD_1280x800,  LCD_1680x1050, LCD_1280x720,  LCD_UNKNOWN };
 
 #define FL_550_DSTN 0x01
 #define FL_550_FSTN 0x02
+#define FL_300      0x04
+#define FL_315      0x08
 
 static struct _sis_crt2type {
-	char name[10];
-	int type_no;
-	int tvplug_no;
-	unsigned short flags;
+	char name[32];
+	u32 type_no;
+	u32 tvplug_no;
+	u16 flags;
 } sis_crt2type[] __initdata = {
-	{"NONE", 	0, 		-1,        0},
-	{"LCD",  	CRT2_LCD, 	-1,        0},
-	{"TV",   	CRT2_TV, 	-1,        0},
-	{"VGA",  	CRT2_VGA, 	-1,        0},
-	{"SVIDEO", 	CRT2_TV, 	TV_SVIDEO, 0},
-	{"COMPOSITE", 	CRT2_TV, 	TV_AVIDEO, 0},
-	{"SCART", 	CRT2_TV, 	TV_SCART,  0},
-	{"DSTN",        CRT2_LCD,       -1,        FL_550_DSTN},
-	{"FSTN",        CRT2_LCD,       -1,        FL_550_FSTN},
-	{"\0",  	-1, 		-1,        0}
-};
-
-/* Queue mode selection for 310 series */
-static struct _sis_queuemode {
-	char name[6];
-	int type_no;
-} sis_queuemode[] __initdata = {
-	{"AGP",  	AGP_CMD_QUEUE},
-	{"VRAM", 	VM_CMD_QUEUE},
-	{"MMIO", 	MMIO_CMD},
-	{"\0",   	-1}
+	{"NONE", 	     0, 	-1,                     FL_300|FL_315},
+	{"LCD",  	     CRT2_LCD, 	-1,                     FL_300|FL_315},
+	{"TV",   	     CRT2_TV, 	-1,                     FL_300|FL_315},
+	{"VGA",  	     CRT2_VGA, 	-1,                     FL_300|FL_315},
+	{"SVIDEO", 	     CRT2_TV, 	TV_SVIDEO,              FL_300|FL_315},
+	{"COMPOSITE", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"CVBS", 	     CRT2_TV, 	TV_AVIDEO,              FL_300|FL_315},
+	{"SVIDEO+COMPOSITE", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"COMPOSITE+SVIDEO", CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SVIDEO+CVBS",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"CVBS+SVIDEO",      CRT2_TV,   TV_AVIDEO|TV_SVIDEO,    FL_300|FL_315},
+	{"SCART", 	     CRT2_TV, 	TV_SCART,               FL_300|FL_315},
+	{"HIVISION",	     CRT2_TV,   TV_HIVISION,            FL_315},
+	{"YPBPR480I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525I,  FL_315},
+	{"YPBPR480P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR525P,  FL_315},
+	{"YPBPR720P",	     CRT2_TV,   TV_YPBPR|TV_YPBPR750P,  FL_315},
+	{"YPBPR1080I",	     CRT2_TV,   TV_YPBPR|TV_YPBPR1080I, FL_315},
+	{"DSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_DSTN},
+	{"FSTN",             CRT2_LCD,  -1,                     FL_315|FL_550_FSTN},
+	{"\0",  	     -1, 	-1,                     0}
 };
 
 /* TV standard */
 static struct _sis_tvtype {
 	char name[6];
-	int type_no;
+	u32 type_no;
 } sis_tvtype[] __initdata = {
 	{"PAL",  	TV_PAL},
 	{"NTSC", 	TV_NTSC},
+	{"PALM",  	TV_PAL|TV_PALM},
+	{"PALN",  	TV_PAL|TV_PALN},
+	{"NTSCJ",  	TV_NTSC|TV_NTSCJ},
 	{"\0",   	-1}
 };
 
@@ -764,16 +444,6 @@ static const struct _sis_vrate {
 	{0,    0,    0,   0, FALSE}
 };
 
-static struct sisfb_monitor {
-	u16 hmin;
-	u16 hmax;
-	u16 vmin;
-	u16 vmax;
-	u32 dclockmax;
-	u8  feature;
-	BOOLEAN datavalid;
-} sisfb_thismonitor;
-
 static const struct _sisfbddcsmodes {
 	u32 mask;
 	u16 h;
@@ -812,14 +482,10 @@ static const struct _sisfbddcfmodes {
        { 1920, 1440, 75, 113,297000}
 };
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static u8 sisfb_lastrates[128];
-#endif
-
 #ifdef CONFIG_FB_SIS_300
 static struct _chswtable {
-    int subsysVendor;
-    int subsysCard;
+    u16  subsysVendor;
+    u16  subsysCard;
     char *vendorName;
     char *cardName;
 } mychswtable[] __devinitdata = {
@@ -830,18 +496,18 @@ static struct _chswtable {
 #endif
 
 static struct _customttable {
-    unsigned short chipID;
-    char *biosversion;
-    char *biosdate;
-    unsigned long bioschksum;
-    unsigned short biosFootprintAddr[5];
-    unsigned char biosFootprintData[5];
-    unsigned short pcisubsysvendor;
-    unsigned short pcisubsyscard;
-    char *vendorName;
-    char *cardName;
-    unsigned long SpecialID;
-    char *optionName;
+    u16   chipID;
+    char  *biosversion;
+    char  *biosdate;
+    u32   bioschksum;
+    u16   biosFootprintAddr[5];
+    u8    biosFootprintData[5];
+    u16   pcisubsysvendor;
+    u16   pcisubsyscard;
+    char  *vendorName;
+    char  *cardName;
+    u32   SpecialID;
+    char  *optionName;
 } mycustomttable[] __devinitdata = {
 	{ SIS_630, "2.00.07", "09/27/2002-13:38:25",
 	  0x3240A8,
@@ -971,13 +637,6 @@ static struct _customttable {
 	}
 };
 
-
-
-static unsigned long sisfb_heap_start;
-static unsigned long sisfb_heap_end;
-static unsigned long sisfb_heap_size;
-static SIS_HEAP      sisfb_heap;
-
 static const struct _sis_TV_filter {
 	u8 filter[9][4];
 } sis_TV_filter[] = {
@@ -1127,9 +786,6 @@ static const struct _sis_TV_filter {
 	   {0xFF,0xFF,0xFF,0xFF} }}
 };
 
-static int           filter = -1;
-static unsigned char filter_tb;
-
 /* ---------------------- Prototypes ------------------------- */
 
 /* Interface used by the world */
@@ -1140,7 +796,11 @@ int             sisfb_setup(char *option
 /* Interface to the low level console driver */
 int             sisfb_init(void);
 
+
 /* fbdev routines */
+static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			      struct fb_info *info);
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
 static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, 
 			      int con,
@@ -1151,7 +811,8 @@ static int      sisfb_get_var(struct fb_
 static int      sisfb_set_var(struct fb_var_screeninfo *var, 
 			      int con,
 			      struct fb_info *info);
-static void     sisfb_crtc_to_var(struct fb_var_screeninfo *var);			      
+static void     sisfb_crtc_to_var(struct sis_video_info *ivideo, 
+			          struct fb_var_screeninfo *var);			      
 static int      sisfb_get_cmap(struct fb_cmap *cmap, 
 			       int kspc, 
 			       int con,
@@ -1174,104 +835,67 @@ static int      sis_getcolreg(unsigned r
 			      struct fb_info *fb_info);
 static void     sisfb_do_install_cmap(int con, 
                                       struct fb_info *info);
-static void     sis_get_glyph(struct fb_info *info, 
-                              SIS_GLYINFO *gly);
-static int 	sisfb_mmap(struct fb_info *info, struct file *file,
-		           struct vm_area_struct *vma);	
 static int      sisfb_ioctl(struct inode *inode, struct file *file,
 		       	    unsigned int cmd, unsigned long arg, int con,
 		       	    struct fb_info *info);		      
 #endif			
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+static int      sisfb_ioctl(struct inode *inode, struct file *file,
+		       	    unsigned int cmd, unsigned long arg, 
+		       	    struct fb_info *info);
 static int      sisfb_set_par(struct fb_info *info);
 static int      sisfb_blank(int blank, 
                             struct fb_info *info);			
-static int 	sisfb_mmap(struct fb_info *info, struct file *file,
-		           struct vm_area_struct *vma);			    
 extern void     fbcon_sis_fillrect(struct fb_info *info, 
                                    const struct fb_fillrect *rect);
 extern void     fbcon_sis_copyarea(struct fb_info *info, 
                                    const struct fb_copyarea *area);
 extern int      fbcon_sis_sync(struct fb_info *info);
-static int      sisfb_ioctl(struct inode *inode, 
-	 		    struct file *file,
-		       	    unsigned int cmd, 
-			    unsigned long arg, 
-		       	    struct fb_info *info);
-extern int	sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, 
-			      PSIS_HW_INFO HwDeviceExtension,
-			      unsigned char modeno, unsigned char rateindex);	
-extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
-			 unsigned char modeno, unsigned char rateindex,
-			 unsigned int *left_margin, unsigned int *right_margin, 
-			 unsigned int *upper_margin, unsigned int *lower_margin,
-			 unsigned int *hsync_len, unsigned int *vsync_len,
-			 unsigned int *sync, unsigned int *vmode);
 #endif
 			
-static int      sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			      struct fb_info *info);
-
 /* Internal 2D accelerator functions */
-extern int      sisfb_initaccel(void);
-extern void     sisfb_syncaccel(void);
+extern int      sisfb_initaccel(struct sis_video_info *ivideo);
+extern void     sisfb_syncaccel(struct sis_video_info *ivideo);
 
 /* Internal general routines */
 static void     sisfb_search_mode(char *name, BOOLEAN quiet);
-static int      sisfb_validate_mode(int modeindex, unsigned long vbflags);
-static u8       sisfb_search_refresh_rate(unsigned int rate, int index);
+static int      sisfb_validate_mode(struct sis_video_info *ivideo, int modeindex, u32 vbflags);
+static u8       sisfb_search_refresh_rate(struct sis_video_info *ivideo, unsigned int rate, 
+			int index);
 static int      sisfb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			unsigned blue, unsigned transp,
 			struct fb_info *fb_info);
 static int      sisfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		      	struct fb_info *info);
-static void     sisfb_pre_setmode(void);
-static void     sisfb_post_setmode(void);
-
+static void     sisfb_pre_setmode(struct sis_video_info *ivideo);
+static void     sisfb_post_setmode(struct sis_video_info *ivideo);
 static char *   sis_find_rom(struct pci_dev *pdev);
-static BOOLEAN  sisfb_CheckVBRetrace(void);
-static BOOLEAN  sisfbcheckvretracecrt2(void);
-static BOOLEAN  sisfbcheckvretracecrt1(void);
-static BOOLEAN  sisfb_bridgeisslave(void);
-static void     sisfb_detect_VB_connect(void);
-static void     sisfb_get_VB_type(void);
+static BOOLEAN  sisfb_CheckVBRetrace(struct sis_video_info *ivideo);
+static BOOLEAN  sisfbcheckvretracecrt2(struct sis_video_info *ivideo);
+static BOOLEAN  sisfbcheckvretracecrt1(struct sis_video_info *ivideo);
+static BOOLEAN  sisfb_bridgeisslave(struct sis_video_info *ivideo);
+static void     sisfb_detect_VB_connect(struct sis_video_info *ivideo);
+static void     sisfb_get_VB_type(struct sis_video_info *ivideo);
+static void     sisfb_set_TVxposoffset(struct sis_video_info *ivideo, int val);
+static void     sisfb_set_TVyposoffset(struct sis_video_info *ivideo, int val);
 
-static void     sisfb_handle_ddc(struct sisfb_monitor *monitor, int crtno);
-static BOOLEAN  sisfb_interpret_edid(struct sisfb_monitor *monitor, unsigned char *buffer);
-
-/* SiS-specific Export functions */
-void            sis_dispinfo(struct ap_data *rec);
+/* SiS-specific exported functions */
 void            sis_malloc(struct sis_memreq *req);
-void            sis_free(unsigned long base);
-
-/* Chipset-dependent internal routines */
-#ifdef CONFIG_FB_SIS_300
-static int      sisfb_get_dram_size_300(void);
-#endif
-#ifdef CONFIG_FB_SIS_315
-static int      sisfb_get_dram_size_315(void);
-#endif
+void            sis_free(u32 base);
 
 /* Internal heap routines */
-static int      sisfb_heap_init(void);
+static int      sisfb_heap_init(struct sis_video_info *ivideo);
 static SIS_OH   *sisfb_poh_new_node(void);
-static SIS_OH   *sisfb_poh_allocate(unsigned long size);
+static SIS_OH   *sisfb_poh_allocate(u32 size);
 static void     sisfb_delete_node(SIS_OH *poh);
 static void     sisfb_insert_node(SIS_OH *pohList, SIS_OH *poh);
-static SIS_OH   *sisfb_poh_free(unsigned long base);
+static SIS_OH   *sisfb_poh_free(u32 base);
 static void     sisfb_free_node(SIS_OH *poh);
 
-/* Internal routines to access PCI configuration space */
-BOOLEAN         sisfb_query_VGA_config_space(PSIS_HW_INFO psishw_ext,
-	          	unsigned long offset, unsigned long set, unsigned long *value);
-BOOLEAN         sisfb_query_north_bridge_space(PSIS_HW_INFO psishw_ext,
-	         	unsigned long offset, unsigned long set, unsigned long *value);
-
 /* Sensing routines */
-static void     SiS_Sense30x(void);
-static int      SISDoSense(int tempbl, int tempbh, int tempcl, int tempch);
-static void     SiS_SenseCh(void);
+static void     SiS_Sense30x(struct sis_video_info *ivideo);
+static void     SiS_SenseCh(struct sis_video_info *ivideo);
 
 /* Routines from init.c/init301.c */
 extern USHORT   SiS_GetModeID(int VGAEngine, ULONG VBFlags, int HDisplay, int VDisplay, int Depth, BOOLEAN FSTN);
@@ -1289,8 +913,16 @@ extern BOOLEAN  SiSDetermineROMLayout661
 
 extern BOOLEAN  sisfb_gettotalfrommode(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
 		       unsigned char modeno, int *htotal, int *vtotal, unsigned char rateindex);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)		       
+extern int	sisfb_mode_rate_to_dclock(SiS_Private *SiS_Pr, 
+		    	PSIS_HW_INFO HwDeviceExtension,
+			unsigned char modeno, unsigned char rateindex);	
+extern int      sisfb_mode_rate_to_ddata(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceExtension,
+			unsigned char modeno, unsigned char rateindex,
+			struct fb_var_screeninfo *var);		       
+#endif
 
-/* Chrontel TV functions */
+/* Chrontel TV, DDC and DPMS functions */
 extern USHORT 	SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
 extern void 	SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempbx);
 extern USHORT 	SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx);
@@ -1298,7 +930,7 @@ extern void 	SiS_SetCH701x(SiS_Private *
 extern void     SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh);
 extern void     SiS_DDC2Delay(SiS_Private *SiS_Pr, USHORT delaytime);
 extern void     SiS_SetChrontelGPIO(SiS_Private *SiS_Pr, USHORT myvbinfo);
-extern USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, unsigned long VBFlags, int VGAEngine,
+extern USHORT   SiS_HandleDDC(SiS_Private *SiS_Pr, ULONG VBFlags, int VGAEngine,
 		              USHORT adaptnum, USHORT DDCdatatype, unsigned char *buffer);
 extern USHORT   SiS_ReadDDC1Bit(SiS_Private *SiS_Pr);			      
 extern void 	SiS_Chrontel701xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwDeviceInfo);
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/vgatypes.h linux-2.4.27-rc4/drivers/video/sis/vgatypes.h
--- linux-2.4.26/drivers/video/sis/vgatypes.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/vgatypes.h	2004-07-30 16:24:21.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * General type definitions for universal mode switching modules
  *
@@ -118,21 +119,17 @@ typedef IOADDRESS SISIOADDRESS;
 #endif
 #endif
 
-#ifndef LINUX_KERNEL   /* For the linux kernel, this is defined in sisfb.h */
-#ifndef SIS_CHIP_TYPE
-typedef enum _SIS_CHIP_TYPE {
+enum _SIS_CHIP_TYPE {
     SIS_VGALegacy = 0,
-#ifdef LINUX_XF86
     SIS_530,
     SIS_OLD,
-#endif
     SIS_300,
     SIS_630,
     SIS_730,
     SIS_540,
     SIS_315H,   /* SiS 310 */
     SIS_315,
-    SIS_315PRO, /* SiS 325 */
+    SIS_315PRO,
     SIS_550,
     SIS_650,
     SIS_740,
@@ -141,29 +138,13 @@ typedef enum _SIS_CHIP_TYPE {
     SIS_741,
     SIS_660,
     SIS_760,
+    SIS_761,
+    SIS_340,
     MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-#endif
-#endif
-
-#ifndef SIS_VB_CHIP_TYPE
-typedef enum _SIS_VB_CHIP_TYPE {
-    VB_CHIP_Legacy = 0,
-    VB_CHIP_301,
-    VB_CHIP_301B,
-    VB_CHIP_301LV,
-    VB_CHIP_302,
-    VB_CHIP_302B,
-    VB_CHIP_302LV,
-    VB_CHIP_301C,
-    VB_CHIP_302ELV,
-    VB_CHIP_UNKNOWN, /* other video bridge or no video bridge */
-    MAX_VB_CHIP
-} SIS_VB_CHIP_TYPE;
-#endif
+};
 
-#ifndef SIS_LCD_TYPE
-typedef enum _SIS_LCD_TYPE {
+#ifdef LINUX_KERNEL
+enum _SIS_LCD_TYPE {
     LCD_INVALID = 0,
     LCD_800x600,
     LCD_1024x768,
@@ -173,29 +154,22 @@ typedef enum _SIS_LCD_TYPE {
     LCD_1600x1200,
     LCD_1920x1440,
     LCD_2048x1536,
-    LCD_320x480,       /* FSTN, DSTN */
+    LCD_320x480,       /* FSTN */
     LCD_1400x1050,
     LCD_1152x864,
     LCD_1152x768,
     LCD_1280x768,
     LCD_1024x600,
-    LCD_640x480_2,     /* FSTN, DSTN */
-    LCD_640x480_3,     /* FSTN, DSTN */
+    LCD_640x480_2,     /* DSTN */
+    LCD_640x480_3,     /* DSTN */
     LCD_848x480,
     LCD_1280x800,
     LCD_1680x1050,
     LCD_1280x720,
     LCD_CUSTOM,
     LCD_UNKNOWN
-} SIS_LCD_TYPE;
-#endif
-
-#ifndef PSIS_DSReg
-typedef struct _SIS_DSReg
-{
-  UCHAR  jIdx;
-  UCHAR  jVal;
-} SIS_DSReg, *PSIS_DSReg;
+};
+typedef unsigned int SIS_LCD_TYPE;
 #endif
 
 #ifndef SIS_HW_INFO
@@ -219,51 +193,38 @@ struct _SIS_HW_INFO
 
     ULONG  ulVideoMemorySize;    /* size, in bytes, of the memory on the board */
 
-    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0) */
+    SISIOADDRESS ulIOAddress;    /* base I/O address of VGA ports (0x3B0; relocated) */
 
     UCHAR  jChipType;            /* Used to Identify SiS Graphics Chip */
-                                 /* defined in the data structure type  */
-                                 /* "SIS_CHIP_TYPE" */
+                                 /* defined in the enum "SIS_CHIP_TYPE" (above or sisfb.h) */
 
     UCHAR  jChipRevision;        /* Used to Identify SiS Graphics Chip Revision */
 
-    UCHAR  ujVBChipID;           /* the ID of video bridge */
-                                 /* defined in the data structure type */
-                                 /* "SIS_VB_CHIP_TYPE" */
-#ifdef LINUX_KERNEL
-    BOOLEAN Is301BDH;
-    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
-                                 /* "SIS_LCD_TYPE" */
-#endif
-
-    USHORT usExternalChip;       /* NO VB or other video bridge (other than  */
-                                 /* SiS video bridge) */
-
     BOOLEAN bIntegratedMMEnabled;/* supporting integration MM enable */
-                                      
-    BOOLEAN bSkipDramSizing;     /* True: Skip video memory sizing. */
 
 #ifdef LINUX_KERNEL
-    PSIS_DSReg  pSR;             /* restore SR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF). */
-                                 /* Note : restore SR registers if  */
-                                 /* bSkipDramSizing = TRUE */
-
-    PSIS_DSReg  pCR;             /* restore CR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF) */
-                                 /* Note : restore cR registers if  */
-                                 /* bSkipDramSizing = TRUE */
+    ULONG  ulCRT2LCDType;        /* defined in the data structure type */
+                                 /* "SIS_LCD_TYPE" */
 #endif
 };
 #endif
 
-/* Addtional IOCTL for communication sisfb <> X driver        */
+/* Addtional IOCTLs for communication sisfb <> X driver        */
 /* If changing this, sisfb.h must also be changed (for sisfb) */
 
 #ifdef LINUX_XF86  /* We don't want the X driver to depend on the kernel source */
 
 /* ioctl for identifying and giving some info (esp. memory heap start) */
-#define SISFB_GET_INFO    0x80046ef8  /* Wow, what a terrible hack... */
+#define SISFB_GET_INFO_SIZE	0x8004f300
+#define SISFB_GET_INFO		0x8000f301  /* Must be patched with result from ..._SIZE at D[29:16] */
+/* deprecated ioctl number (for older versions of sisfb) */
+#define SISFB_GET_INFO_OLD    	0x80046ef8  
+
+/* ioctls for tv parameters (position) */
+#define SISFB_SET_TVPOSOFFSET   0x4004f304
+
+/* lock sisfb from register access */
+#define SISFB_SET_LOCK		0x4004f306
 
 /* Structure argument for SISFB_GET_INFO ioctl  */
 typedef struct _SISFB_INFO sisfb_info, *psisfb_info;
@@ -305,8 +266,10 @@ struct _SISFB_INFO {
 	CARD8 	sisfb_haveemilcd;
 
 	CARD8 	sisfb_lcdpdca;
+	
+	CARD16  sisfb_tvxpos, sisfb_tvypos;  	/* Warning: Values + 32 ! */
 
-	CARD8 reserved[212]; 		/* for future use */
+	CARD8 reserved[208]; 			/* for future use */
 };
 #endif
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/drivers/video/sis/vstruct.h linux-2.4.27-rc4/drivers/video/sis/vstruct.h
--- linux-2.4.26/drivers/video/sis/vstruct.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/drivers/video/sis/vstruct.h	2004-07-30 16:25:47.000000000 +0000
@@ -1,4 +1,5 @@
 /* $XFree86$ */
+/* $XdotOrg$ */
 /*
  * General structure definitions for universal mode switching modules
  *
@@ -168,6 +169,7 @@ typedef struct _SiS_ExtStruct
 	UCHAR  VB_ExtTVYFilterIndex;
 	UCHAR  VB_ExtTVYFilterIndexROM661;
 	UCHAR  REFindex;
+	CHAR   ROMMODEIDX661;
 } SiS_ExtStruct;
 
 typedef struct _SiS_Ext2Struct
@@ -289,6 +291,7 @@ typedef struct _SiS_Private
 #endif
 	BOOLEAN SiS_UseROM;
 	BOOLEAN SiS_ROMNew;
+	BOOLEAN SiS_NeedRomModeData;
 	BOOLEAN PanelSelfDetected;
 	int     SiS_CHOverScan;
 	BOOLEAN SiS_CHSOverScan;
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/fs/affs/amigaffs.c linux-2.4.27-rc4/fs/affs/amigaffs.c
--- linux-2.4.26/fs/affs/amigaffs.c	2001-09-11 15:19:35.000000000 +0000
+++ linux-2.4.27-rc4/fs/affs/amigaffs.c	2004-07-30 16:26:40.000000000 +0000
@@ -458,7 +458,6 @@ affs_error(struct super_block *sb, const
 	if (!(sb->s_flags & MS_RDONLY))
 		printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
 	sb->s_flags |= MS_RDONLY;
-	AFFS_SB->s_flags |= SF_READONLY;	/* Don't allow to remount rw */
 }
 
 void
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/fs/affs/bitmap.c linux-2.4.27-rc4/fs/affs/bitmap.c
--- linux-2.4.26/fs/affs/bitmap.c	2002-02-25 19:38:07.000000000 +0000
+++ linux-2.4.27-rc4/fs/affs/bitmap.c	2004-07-30 16:31:44.000000000 +0000
@@ -268,8 +268,7 @@ err_full:
 	return 0;
 }
 
-int
-affs_init_bitmap(struct super_block *sb)
+int affs_init_bitmap(struct super_block *sb, int *flags)
 {
 	struct affs_bm_info *bm;
 	struct buffer_head *bmap_bh = NULL, *bh = NULL;
@@ -277,13 +276,13 @@ affs_init_bitmap(struct super_block *sb)
 	u32 size, blk, end, offset, mask;
 	int i, res = 0;
 
-	if (sb->s_flags & MS_RDONLY)
+	if (*flags & MS_RDONLY)
 		return 0;
 
 	if (!AFFS_ROOT_TAIL(sb, AFFS_SB->s_root_bh)->bm_flag) {
 		printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
 			kdevname(sb->s_dev));
-		sb->s_flags |= MS_RDONLY;
+		*flags |= MS_RDONLY;
 		return 0;
 	}
 
@@ -296,7 +295,7 @@ affs_init_bitmap(struct super_block *sb)
 	bm = AFFS_SB->s_bitmap = kmalloc(size, GFP_KERNEL);
 	if (!AFFS_SB->s_bitmap) {
 		printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
-		return 1;
+		return -ENOMEM;
 	}
 	memset(AFFS_SB->s_bitmap, 0, size);
 
@@ -311,13 +310,13 @@ affs_init_bitmap(struct super_block *sb)
 		bh = affs_bread(sb, bm->bm_key);
 		if (!bh) {
 			printk(KERN_ERR "AFFS: Cannot read bitmap\n");
-			res = 1;
+			res = -EIO;
 			goto out;
 		}
 		if (affs_checksum_block(sb, bh)) {
 			printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n",
 			       bm->bm_key, kdevname(sb->s_dev));
-			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
 			goto out;
 		}
 		pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key);
@@ -333,7 +332,7 @@ affs_init_bitmap(struct super_block *sb)
 		bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
 		if (!bmap_bh) {
 			printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
-			res = 1;
+			res = -EIO;
 			goto out;
 		}
 		bmap_blk = (u32 *)bmap_bh->b_data;
@@ -378,3 +377,15 @@ out:
 	affs_brelse(bmap_bh);
 	return res;
 }
+
+void affs_free_bitmap(struct super_block *sb)
+{
+	if (!AFFS_SB->s_bitmap)
+		return;
+
+	affs_brelse(AFFS_SB->s_bmap_bh);
+	AFFS_SB->s_bmap_bh = NULL;
+	AFFS_SB->s_last_bmap = ~0;
+	kfree(AFFS_SB->s_bitmap);
+	AFFS_SB->s_bitmap = NULL;
+}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/fs/affs/super.c linux-2.4.27-rc4/fs/affs/super.c
--- linux-2.4.26/fs/affs/super.c	2002-02-25 19:38:07.000000000 +0000
+++ linux-2.4.27-rc4/fs/affs/super.c	2004-07-30 16:29:47.000000000 +0000
@@ -48,10 +48,9 @@ affs_put_super(struct super_block *sb)
 		mark_buffer_dirty(AFFS_SB->s_root_bh);
 	}
 
-	affs_brelse(AFFS_SB->s_bmap_bh);
 	if (AFFS_SB->s_prefix)
 		kfree(AFFS_SB->s_prefix);
-	kfree(AFFS_SB->s_bitmap);
+	affs_free_bitmap(sb);
 	affs_brelse(AFFS_SB->s_root_bh);
 
 	return;
@@ -235,6 +234,7 @@ affs_read_super(struct super_block *sb, 
 	gid_t			 gid;
 	int			 reserved;
 	unsigned long		 mount_flags;
+	int			 tmp_flags;	/* fix remount prototype... */
 
 	pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
 
@@ -349,7 +349,6 @@ got_root:
 		printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
 			kdevname(dev));
 		sb->s_flags |= MS_RDONLY;
-		AFFS_SB->s_flags |= SF_READONLY;
 	}
 	switch (chksum) {
 		case MUFS_FS:
@@ -405,8 +404,10 @@ got_root:
 	AFFS_SB->s_root_bh = root_bh;
 	/* N.B. after this point s_root_bh must be released */
 
-	if (affs_init_bitmap(sb))
+	tmp_flags = sb->s_flags;
+	if (affs_init_bitmap(sb, &tmp_flags))
 		goto out_error;
+	sb->s_flags = tmp_flags;
 
 	/* set up enough so that it can read an inode */
 
@@ -445,14 +446,14 @@ affs_remount(struct super_block *sb, int
 	int			 reserved;
 	int			 root_block;
 	unsigned long		 mount_flags;
-	unsigned long		 read_only = AFFS_SB->s_flags & SF_READONLY;
+	int			 res = 0;
 
 	pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
 
 	if (!parse_options(data,&uid,&gid,&mode,&reserved,&root_block,
 	    &blocksize,&AFFS_SB->s_prefix,AFFS_SB->s_volume,&mount_flags))
 		return -EINVAL;
-	AFFS_SB->s_flags = mount_flags | read_only;
+	AFFS_SB->s_flags = mount_flags;
 	AFFS_SB->s_mode  = mode;
 	AFFS_SB->s_uid   = uid;
 	AFFS_SB->s_gid   = gid;
@@ -463,14 +464,11 @@ affs_remount(struct super_block *sb, int
 		sb->s_dirt = 1;
 		while (sb->s_dirt)
 			affs_write_super(sb);
-		sb->s_flags |= MS_RDONLY;
-	} else if (!(AFFS_SB->s_flags & SF_READONLY)) {
-		sb->s_flags &= ~MS_RDONLY;
-	} else {
-		affs_warning(sb,"remount","Cannot remount fs read/write because of errors");
-		return -EINVAL;
-	}
-	return 0;
+		affs_free_bitmap(sb);
+	} else
+		res = affs_init_bitmap(sb, flags);
+
+	return res;
 }
 
 static int
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/fs/attr.c linux-2.4.27-rc4/fs/attr.c
--- linux-2.4.26/fs/attr.c	2002-02-25 19:38:07.000000000 +0000
+++ linux-2.4.27-rc4/fs/attr.c	2004-07-30 16:25:50.000000000 +0000
@@ -33,7 +33,8 @@ int inode_change_ok(struct inode *inode,
 
 	/* Make sure caller can chgrp. */
 	if ((ia_valid & ATTR_GID) &&
-	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
+	    (current->fsuid != inode->i_uid ||
+	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)) &&
 	    !capable(CAP_CHOWN))
 		goto error;
 
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/fs/buffer.c linux-2.4.27-rc4/fs/buffer.c
--- linux-2.4.26/fs/buffer.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/buffer.c	2004-07-30 16:29:14.000000000 +0000
@@ -2836,7 +2836,7 @@ void show_buffers(void)
 				       buf_types[nlist], found, tmp);
 		}
 		printk("%9s: %d buffers, %lu kbyte, %d used (last=%d), "
-		       "%d locked, %d dirty %d delay\n",
+		       "%d locked, %d dirty, %d delay\n",
 		       buf_types[nlist], found, size_buffers_type[nlist]>>10,
 		       used, lastused, locked, dirty, delalloc);
 	}
diff -Naur -p -X /home/marcelo/lib/dontdiff linux-2.4.26/fs/cramfs/inode.c linux-2.4.27-rc4/fs/cramfs/inode.c
--- linux-2.4.26/fs/cramfs/inode.c	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.27-rc4/fs/cramfs/inode.c	2004-07-30 16:25:04.000000000 +0000
@@ -111,8 +111,8 @@ static int next_buffer;
  */
 static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
 {
-	struct buffer_head * bh_array[BLKS_PER_BUF];
-	struct buffer_head * read_array[BLKS_PER_BUF];
+	struct address_space *mapping = sb->s_bdev->bd_inode->i_mapping;
+	struct page *pages[BLKS_PER_BUF];
 	unsigned i, blocknr, buffer, unread;
 	unsigned long devsize;
 	int major, minor;
@@ -139,7 +139,7 @@ static void *cramfs_read(struct super_bl
 		return read_buffers[i] + blk_offset;
 	}
 
-	devsize = ~0UL;
+	devsize = mapping->host->i_size >> PAGE_CACHE_SHIFT;
 	major = MAJOR(sb->s_dev);
 	minor = MINOR(sb->s_dev);
 
@@ -149,26 +149,31 @@ static void *cramfs_read(struct super_bl
 	/* Ok, read in BLKS_PER_BUF pages completely first. */
 	unread = 0;
 	for (i = 0; i < BLKS_PER_BUF; i++) {
-		struct buffer_head *bh;
+		struct page *page = NULL;
 
-		bh = NULL;
 		if (blocknr + i < devsize) {
-			bh = sb_getblk(sb, blocknr + i);
-			if (!buffer_uptodate(bh))
-				read_array[unread++] = bh;
+			page = read_cache_page(mapping, blocknr + i,
+				(filler_t *)mapping->a_ops->readpage,
+				NULL);
+			/* synchronous error? */
+			if (IS_ERR(page))
+				page = NULL;
 		}
-		bh_array[i] = bh;
+		pages[i] = page;
 	}
 
-	if (unread) {
-		ll_rw_block(READ, unread, read_array);
-		do {
-			unread--;
-			wait_on_buffer(read_array[unread]);
-		} while (unread);
+	for (i = 0; i < BLKS_PER_BUF; i++) {
+		struct page *page = pages[i];
+		if (page) {
+			wait_on_page(page);
+			if (!Page_Uptodate(page)) {
+				/* asynchronous error */
+				page_cache_release(page);
+				pages[i] = NULL;
+			}
+		}
 	}
-
-	/* Ok, copy them to the staging area without sleeping. */
+		
 	buffer = next_buffer;
 	next_buffer = NEW
+			0 next_buffer;
 	next_buffer = Ngs & MS_R next_buffer;
 	next_buffer = Ngs & MS_R next_bufCHIP_302      	 unuffeNtotype... */
5:04.000000000 +0000
@@ -1.000000000 +0000{
+	    (!in_group_p(attr->ia_gid) &&;
-static SIS_OH   *sisfb_pon0 +0ilid) &!  	    struct fb_info *info);
 static int  a__bloc ExtTVYFilterIndexRY
 static int  a__b ExtTV8+UL;
+	devsif (page) rn BOgid;struct supe000000buffer(v			if >
+++ linux-2.4.e *>3/fs/att    2.4.e6)(63N  sinux-2.4.e(++ linux-2.4.e *>3/fs/att    2.4.e6)(63N  sinux-2.4.e(++ linux-2.4.e *ffs_remount(struct super_block *s
 	/* N.B. after this AR   ROMMODEIsupeging are data st4_p_flags))
 		gi2>3/fs/att  te(pagb*s
 	/* N.B. after0   0x4vockedterInI ExtTAFFSbuffer2/5_t    2d+ags)
 {
 	struct affs(page) rn BOgid;s07-       0},
-	{"VGA"_rate_t(stpegin8(stratt  te(pagb*s
 	/*n
 	struct affs(page) ULL;
+			}
+		p_p(attrm4-07-30 16:25:04.000000000 +0000
@@ -111,000000	AFFS_SB->s_gid   = gid;
@@ -463,                  eid != inod:tpegin8(stratt = Ngs      E      sis_fr_PEo:ic -2.4.26/Rper_	_oid);
-#endif
-#ifdef CON_oidpstraLEo:i        gs   ue	6eRb_info *info);
ndexRY
 stafr_PEnext_buffEBUF pa,    {
-			umloc Ex = gm,opts=\"%s\1->s_gid nDatt = Ngs   t_b       to the sedL  E   SF_READONLY)ct fNV*s
 	/* N.c
--- linu] :_	e(psuper_b	if (rucb600000 +0(psup_-2.4.26/fs/cramfs/inode.c	ng s/inode.c	ng s/inodeedL  E   SF_t(st.ode+#define SISFB_SET_TVPOSOFFSET   0x4004f304
+
+/* lock sisfb froine cachetruct sups>SIS_OH PER_BUF];
 	unsigned i, bloccHetruct page *page =Bgned char modeno, uns5fs/crachar def CON_ohi];
 ] :_	e'SISF, uns5fs/cr= b* l Hetruct  (page) rn BOgid;struct supe00005_t   
 ] :EW
+			0 apping->hostb.h) = bnr + i,
+				(filler_t *)mapp4ostb.h) = d(str5att  r + i,
))
+	tmp_flags = sb->[] =tr5att page)3er_	_oid);
-#endif
-#ifdef CON_oidpstraLEo:i        gs   ue	6eR sinux-2.4.e(++ linux-0O		0 apping->hostb.h) o:i       r + i,
 S9>3/.h) o:i       #endif
-#ifdef CON_oidpstr5_t  s
 	/* N.c
--- linu]egister ac1ct fNV*linu] mi2Pfupeging are data sck sisf (
 	/stb.hPfupeg_	e'SISF, uns5fsinu] mi2P00
@@ -4 N.c
--- linu]egist{
-			s/inode.c	ng s/inode.c	ng s/int+0000
@@e.c		s/inode. lck sis2tic inI:04.000000000 +0000
@@ -111,0locketb.ust be patched with resullt		vge);
+			if (%	vge);
ohi				page = NUL:   nPe dataf (%	vge (*flagi]
 
-int
-affs_init_bitmap(struct s, uns5b* Cu] mi2Pfu+%	vge (*fl5ehd cop7U      +0000
@@ -458,7 +458,t+0i2Pfu+%p(stS_Pri)_bitmap) {
 -458,7 ++.TV8+UL;
+	
-#endif
	umloc Ex = gm,opts= locke4-ins_m				pagm				pagm				pic unsignedchet   B--1302ELV_bh->b_data1302ELV_bh->b_data1302ELV_bh->b_data1302ELV_.c		s/ sis_mem604f304
+
+/* lock si 			affs_write_super(sfb froine cachetruct sups>SIS_OH PER_BUF];
 	unsigned i, bloccHetruct page *pagP definiti	ps>SIS_OH PER_BUF];SET_TV>SIS_OH ps>SIS_OH PER_R_BUF]lock %d: %d\n"ilatched w:e *pame_to_dclock(SiS_Private 0SiS_Privat2UF]lock %r  *biate 0SiS_S_Private9_ */
+			if (IS_ERR(page	Alinux-2. 	0x80046ef8  
+
+			if letely first. */
 	unrock a|HORT tempbh);
 exter7cuct super_block *sb)
+{
+	if (!AFFS_SB->s_bitmap)
+		return;
+
+	affsta1302ELVP gs   ue);
-te 0SiS_Privat2UF]lock %r  *b				pagm				pic unsignedchet   B--1302ELV_b4itmap)
+		return;
_to_dclock(SiS_P->b_dagghar rateindex);
+#if LINUX_VERSION_CODE >= KERNELad s/att    2.4.e6)(63N  sinux-2.4.e(++ linux-2.4.edad s/a)(63N  sinux-2.4.e(++ linux-2/att    2.4.e6)(63N  1inux-2.4.e(++ r rateindex);
e|
+/vde. l	afore cR reH     sisfb_insert_node(SIS_OH *pock *sb)
nAefine o(;
e     8
+		returneG "AFFS: Remounting fnAe4o/lib/dontdiff linux-2.4.26/fs/B(SiSl-- ULONG  ulCRT2LCDType;        /* defined ingm,opts= lo,iounting fnAe4o/lib/donf{
-		ll_rw_block(READ, unread, read_array);
-	 P bloc	ng s_R_BUF]lock %d: %d\n"i       ne/fs/B(SiSl-- ULONG  ulCRT2LCDType;    5m,opts=}
 		if (affs_cn  1inuIbPr, -37ing fnAe4  		ifng %s re 		iulCRtPr, - LV_.cxRY
</* synchronous error? */
+			>-P, uns5fs/crachar def CON_ohi];
 ] :_	ntking fnAe4  		i "no optinux-2. 	 affsmnr + i);
-			if (!b;
-		pTb->s_bd. 	 affsmAe4 _to_uf (!b @@ afREAD, unread, ead_array);
-	 P bleDType;    i);
-			if (!b;
* s+affs_init_bitmap(sb))
+	tmp_flags = sb->s_B	if (!b;
* s+f0		ifnm	umlofL+	tmp_flags = 
-		a]
-			if (!b;
*umlofL+	_SET_TVPO     SISDoSense(int tempblng el7ISFB_GET_INFO	b)
nAefin1,dex, u32 vbflags)_t temler_t *)mapping-zing. *I-
-	/* Ok, copy them to the staging arTb->s_bd. 	 affsmAe4 _to_uf (!b @@ afREAD, s = ml++ lin i < deGao {
-0SiS_Privat2UF]lock %r  *bi vbflat>f (!b @@sb, flags);
 exter7nr +pic unsignedLsfb_post_s;
 	unsign
 	unsign
 	unsign
 	unsign
 	unsign
 	unEAD, ign
 	unsign
e to tnsigned(isfb_initaccel(void);
-extern void     sisfw_node(void);
-sta#endh->s_bdfferid     siss_bd--- linr +y);
-	 P bleDType;    i);
-			if (!b;
* s+affs_init_bitmap(sb))
+	tmp_flags =0		if	_PAL|TV_Pstruc21+affs_init_b 4t_b 4ffs_init_ 1a)
+	tmp_flags =0		if	_PAL|TV_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAe4 _to_uf (!b sis_video_info *ivideo);le (dbx6s4		goS(_init_b ffPst3	_PAL|TV_Pstruc21+affs_M;
* s+affs_init_bitmap(sb))
+	s_iniuper.|TV_Pstruc21+affs_init_b 4t_O_m2_TV,  fb_ins_M;
* s+affs_itruc21+affs_M;
* s+u     0},
-	{ Bitmap invd_arra;strp_fs/amigaffs.c	2001-09-11 15:19:35.000000000 +0000
+++ linux-2.4.27-rc4/fs/affs/amigaffs.c	20_R next_bufCHIP_302    b->s_flags |= MS_RDONLY;
s =ch->saA3*r(PSIS_HW_4/fs/affs/amA|= MS_RDONLY;
s =ch->saA3*r(PSIS_HW_4/fs/affs/amA|ELVP dCaffs/ SIS Mhr(Pe3oupera *rec);
+/_HW_4/fsAFFS_SB-.rage = pages[iaA3*r(PSIS_HW_4/fs/af2UF]lock %r  *biate 0SiS_S4		g-M l /* Intec21+   0},
-	{ Bitmap inv2;
 ed i, bloccIS_HW	/* N.B. after0(S-iitmap & SF_READlPDetermineROMLayout661
 
 extervideo_i	 1>s_bd.voccIS_HW	/neROMLayou12B,
-  -	{ Bitmap inv2;
 ed i, blocaffrmine
-static 0SiS_Privat2UF]lock %r sisf (
 	/stb.hPf_dagntihv u32 vbflags)_t temloid);
-sta#endh->s_bdf_PEo:d exterv	2001egin8(strattr0(S-i sb_getblkl_rw_block(x0pisfb_get_var(dt_b 4t_b=i sb_getbPf_dag.e(+yt_b 45g83A3*r(PSIS_HW_4/fs/af2UF]lock %r  *biate 0SiS_S3 +111,8 @@ stati kl_rw_) SI0MMivideo_4/      tS3 +1_4/  isf (
 	/stb 45g83_PEo:d MivideIS_HW	/neROMLayou12B,
-  -	{ Bi,+yt_b f (
 A 	/st_PEo:d MivideIS_HW	/neROMLayou12B,g83_PEo:d MivideIS_HW	/nideIS_ %r  *B,g A 	/st_PEo:d D, unre:, unr(PDetamA|= MSdif
	umloc Ex umloc Elock %d:-dh->s_bdf_PE_rror? */
+			>-P, uns5fs/crachar def COiSl-- ULONG  6f C&roo;n;
 	}
 	memset(AFFS_SB->s_b3S_HW	/neROMLayou12B,g83_PEo:dn != iaA3*r(PSIS_HW_4/fs/affs/amA|ELV83_PEomamA|= MSdcW	/* N.B. after0+ter7nr afFnux-2_HW_4/fs/affs/amA|ELV83_PEoma_A|ELVm2_S3 +S0
 	}
 	me_S3 +S0
 	}
 	me_S3 +S0
 	}
 	me_S3 +SIS_HW_4/fs/affs/amA|ELVges[iaA3*r(PSIS_HW_4/fs/af2U{
-ign
 	uPEo:0
 	}
 	me_S3 +S0
 	}(!b;
* s+f0		ifnm	uml"tS)	0		Y;
s =ch->saA3*r(PSIS_HW_4/fs/affs/amA|= MS_RDONLY;
s =ch->saA3*r(PSIS_HW_4/fs/afMivi"tS)	aL)aeMLayou12B,
-  -	{ Bitmap inv2;
 edlk[blk])u;
 	}
 	memset(AFFS_SBu12B,
ount(2I-
-	//stb.hPf_dagOMLaA|ELVm2_S3 +S0
 95P bleDType;   ffer4+*r(PSIS_HW-rl_4/fs	}
= roine cachetruB,g A 	/s2_HW_4/funting fnAHdagOv+S0
 95P bleDType;  12_S3inI= roine cachetruB,g A 	/shr(Pe3oupera *rec)-
-	/d88g fn Af (rucb6tmp_flags =0		truB,g A 	/shr(Pe3ounux-2.4.26/fs/cramfs/inode.c linux-2.4.27-rc4/fs/cr000->saA3*e3ounux-fs	,B,
ount(2Ii);
 exter7nr +pic unsir000->saA3*e3ounux-fs	,B,
ounttmp_e cachetruB,g A 	/shB,
ount(m 	}-	2004-07memsk %d<<52.4.e(++ i >gaft_root:n
 	unsigf	_P	/shB-1]HIP_TYPEr_blo125t			 rhetruB,g A 	/s2_HW_4/funting fnAHdagOv+S0
 9+S0
 95P bleqev));
 		sbrs_flags - gm,op004-:fs	,B3ounux-fs	,B,
s_initSB->s_g00->saAS_FS:
    0},
-S0
)_4/fs/af2Us_ %r	uPEochkg A (-S0
uffe14)0->s(P bffe14)0|| -
-	[-S0
u&truB,,
ouffe5] | ~(((1 << n)rat(m << -S0
u&tru1fb;
*!fs	,ffffffffVm2_SP_TYP52,45efin6,57		 rhetruB,g A 	/s2_HW_4/funting fnAHdagOv+S0
g A 	/	uPEos2_HW_g At
 		printk(KERN_ERR "AFF,
g A 	/nea8,13 @@ typenk, bm-mp_e cak, bm-it_b );
@@ - A 	/- Ab, flags);
 ei_gid) &ei_gign
 	unsig/funt&&
-	d(isf ffs_ %r	uPEocme_S3 +igned(isf_p01-09-id) &enea8funtunr(PDetmp_e cac<gaft_rootmp_e cacuntmp_e ca_flagf_p01-1Type;  1PDetit_b /	uPEog83_PcS_Sf304(ou12B,PDetamarg A amarg<fs_ %r	uPEoPEoe(++ -id/funt&PAL|T_ %r	uPEoPEoe(++blediff 0rat(m ffe144.27-rc4amarg A amarg<fs_ %r	uPEoPEoe(++ _4/fs/af2U(- Ax-2.2_HW_4/funtin,/nea8,1nk,f_p0?tmp_e cac:tmp_e ca/4b;
* s+f0rex-fs	,nea8funtps>SIar ffe144.27SIS_HW_nea8funtps>Sfunt&P/ 2linux-s_bd--- 
ount(m 4/fs/af2U(- Ax-2.2_HW_4/funtin,/b<<14,1nk,f_p0?tmp_e cac:tmp_e ca/2)AFFS_SB->bx-fs	,0fffffffev));
 		sbrep_bh);
 	if (AFb >gax1 	me_S3) af2U(- Ax-2.2_HW_4/funtin,/(b&	,fffffff)<<14,1nk,f_p0?tmp_e cac:t0b;
* s+f0rex-f- g	f- /funt&PAL|T_ %r	uPEoPEoe(++blediff 0rat(m ffe144.-	s/inode. lck sisSfunt&P/ 2lER_BUF];
 	af2U(- Ax-2.2_HW_4/funtin,/(Sfunt&/2+im << 14,1nk,fLaA|ELVmmodeno, s_ %r	uPEocme_S3 +ps>Sfunt&/2+i4.27S.27t(2Ii)nsirf_p) af2Ump_e cachfs_ %r	uPEomax_fwdos2_HW) mp_e cacuns_ %r	uPEomax_fwdos2_HW4.27ck(x_fwd:id;
@@ -463,       /funt&&d != inod:t-rc4amarfunt+ sisSfunt&P A (-- Ax-2.2_HW_4/funtin,/(Smarfunt+ m << 14,1nk,fLaA|ELVmm  
 ] :Es_ %r	uPEocme_S3 +ps>Smarfunt+ ev));
 		sbrep_bh);
	;
 	af2U(- Ax-2.2_HW_4/funtin,/(Sfunt&/2-i-1m << 14,1nk,fLaA|ELVmmodeno, s_ %r	uPEocme_S3 +ps>Sfunt&/2-i-1-fs	,B,
o!fLaA|ELV 
 ] :E-rc4amarfunt-i-1chetrP A (-- Ax-2.2_HW_4/funtin,/(Smarfunt-i-1m << 14,1nk,fLaA|ELVmmo:i      s_ %r	uPEocme_S3 +ps>Smarfunt-i-1-fs	,;
 		sbrep_bx = gm,optt_ 1a)
+	tmt-rc4amarfunt+ s>=sSfunt&P A (-- Ax-2.2_HW_4/funtin,/(Smarfunt+ -Sfunt&m << 14,1nk,fLaA|ELVmmo:i      s_ %r	uPEocme_S3 +ps>Smarfunt+ -Sfunt&-fs	,;
 		sbrep_bx = gm,optfs	,B,
oiBitm1P A s_ %r	uPEocme_S3 +pount(P A (-- Ax-2.2_HW_4/funtin,/(s_ %r	uPEocme_S3 +m << 14,1nk,fLaA|ELVmmo:i ));
 		sbrep_bh);
 	i-	{ Bitm(- Ax-2.2_HW_4/funtin,/(Sfunt&-1m << 14,1nk,fLaA|ELVmmodeno,s_ %r	uPEocme_S3 +ps>Sfunt&fo, 
;
 		sbrep_b-e;  1PDetrf_p) deno,
@@ -463,       /funt&&d != sinux-2.4(- Ax-2.2_HW_4/funtin,/i << 14,1nk,0Vmmodeno, ,s_ %r	uPEocme_S3 +ps>ax1 	me_S3re d, uns5
 		sbrep_b-eoptfs	,B,
ofLaA|ELV 
 ] :Es_ %r	uPEomax_fwdos2_HWps>mp_e cac* 3P/ 4_bx = mp_e cac/= 2linu5
 		sbck(x_fwd;m,opts=\"%@ - A01-09-11rep:e(sb->s  sin28k *sb, st.od	uPEoP/homg At
 s		printk(KERN_ERR fer;
 	nexType;  1g83_PEo:d Miex);
s_ %r	uPEomax_fwdos2_HWp+s>S >gaxffff0?taxffff0:e;  +/af2Us_ %r	uPEomax_fwdos2_HWp>s	,ffffff)ns_ %r	uPEomax_fwdos2_HW fs	,ffffffnu] :_wo:0
   0},
-{
-ign
 	uPEo:0
 e_S3 +S0
 - A0ffe14
 	}(!, "P/ho"mmo:i ));ou12B,
-  -	{ 	/* fix 1RDONLY3. *I-
-) &e	uPEocheB,
P/hom	}
 	s		printk(KERN_ype;  1	uPEofs/cr=4(	}(!bunr(P01-09--/af2Us_ %r	uPEocme_S3 +pount(Ps/amA|= MSs_ %r	uPEocme_S3 +pount(o:i ));-ign
 	uPEo:0
 e_S3 +S0
 b
 	}(!, "chkdn1"ounting fnAchkfuntunr(f{
-		ll_rw_block(READ, unread, read_array);
-	 P bloc	ng s_R_amA|ELuf (!b sis_video_info *ividamA|ELuf (!baA3*r(PSIS_HW_4/fs/affs/amA Cu] mi2Pfu+06YPE 02:15:2000
@@ -111,8 +111,8 @@ static int next_bufs/amA Cu] mi2Pf synchronous e3b_ins_M;
* s+affs_itru112_blo11prototyg A 	/	uPEosddmg At
 : "nbtf (!Aprintk(K_SB->bs/cr= b* l 
 9+S0
irty,1ffs(page) sups>Si	ps>+) sups>!fSi	0?tt sup:/(S sups/c6384)0& ~c6383unr(f	  0},
-{
sups>	uPEos2_HW_g At
 		
 - , 1k,fg A 	*ALLOC_M>ALLOC_FWD_MAX0?tALLOC_FWD_MAX0:,fg A 	*ALLOC_M<ALLOC_FWD_MIN0?tALLOC_FWD_MIN0:,fg A 	*ALLOC_M, 1mmo:i ));bs/cr= b* l i     1_blo19ue	6eR s A 	/	uPEosddmg At
 : "nbtf (!Aprintk(K_SB-
 	ifugn
 u+pounS sup? ack(SiSu+p:y,1ffs(pbtf (iSu.iS_Sense[btf (iSn_ptod+extesrat(].B->s_s A 	/= /*fs*/fo, 
;
n8(stpBitma(o:ack(SiSu+p= r
 
 	=0x%x,opts=\"%s\")\b* l 
 9bs/cr= b* l 
 94004nauns5fs/crachar def COiSl-- ULONG  6f C&roo;n;
 	}
 	memset(AFFS_SB-n read_buffers[i] + blk_offseS_SB-n read_baA3*r(PSIS_HW_4/fs/affs/amsb->s_dev);
04.000000000 +0800
@@ -111,8 +111,8 @@ static int next_bufs/amsb->s_dev);
 	minor = MI8:12 0SiS_S4		g-M l /* Inte2UF]lo24 *sb, st.od*	uPEo:0
 g At
 		printk(KERN_ERR ");
@@ -333,7 struct supe000000ffs.cose);es1;
 (nux-2 	000pt pag ffs_init_Pst,
g A 	BUF];
 	uag !oidpst/buffer.c lis_flags |= SF_RE141+aff142 *sb, st.od*	uPEones g At
 		printk(KERN_ERR "); -333,7 struct supe000000fux-er.c li	uPEo:0
 g At
 		,
g A 	har 0000);0000 s.cose);es1;
 (nux-2 	-2.4(000pt pag ffs_i/fs/att ,
g A 	B) !oidpst/_4/fs/af2U{e(++ linux-2.4.e *ff 5:04.000000000 b* l 
 90x%x,opts=\"nux-2.4.e *, 1m SF_RE15ock *sb2 *sb, st.od*	uPEo:0
 4g At
 s		printk(KERN_ERR); -333,7 struct supe000000furite_ss |= S0 s.cose);es1;
 (nux-2 	-2.4s A 	/& 31302ELV_bh->b_dHPode-	uPEo:0
 4g At
 s: unseVyposoffaly first.	}
diff -Na(sb->032 siz15 *sb, st.od*	uPEo:0
 4g At
 s		printk(KERN_ERR);st.od*	uPEones 4g At
 s		printk(KERN_ERR "AFF,
 lin i < d A 	h
 };
 #endif
 
diff -Naur -p	printkqu04
+
+/*  supe00}(!b
/amA|cose);es1;
 (nux-2 	-2.4s A 	/& 31302ELV_bh->b_dHPode-	uPEones 4g At
 s: unseVyposoffaly first.	}
diff -Nas5fs/crachar def COiSl-- ULONG  6f C&roo;n;
 	}
 	memset(AFFS_SB-ea_buffers[i] + blk_offseS_SB-ea_baA3*r(PSIS_HW_4/fs/affs/amea_b		if (IS_ERR(page))
+				page = NULL;
 		}
-		bh_array[i] = bfs/amea_b		if
 static void *b_ins_M;
* s+affs_itru	AFF149,35@@ static v	uPEos
 	ea, unsigned int len)
  fter0ages coosp+s>eaiSnameleuntteaiSS_Prileuntt5
-  -	{ Bitmafck(SiSea init.ss/amA|= MS_fck(SiSea 		if1302ELVBu12B,fck(SiSea init.ss/am
 9+	uPEo) {
 		, "Pd int%08x: ea init.sBitm%03x, ea 		ifBitm0} else IS_OH PER_BUFk,fck(SiSea init.ssNa(sb->43}
 	+>43}
3 static v	uPEos
 	ea, unsigned int len)
  fter0agst_PE	fck(SiSea 		if fs	,c4
-  -	{ Bitmfck(SiSea 		if <s	,c40|| fck(SiSea 		if +,fck(SiSea init.sp>s	,200s/amA|= MSfck(SiSea 		if <s	,c40|| fck(SiSea 		if +,fck(SiSacl init.sp+,fck(SiSea init.sp>s	,200s/am 9+	uPEo) {
 		, "Pd int%08x: ea 		ifBitm%03x, ea init.sBitm%03x} else S_OH PER_BUFk,fck(SiSea 		ifk,fck(SiSea init.ssNaer;
 	nexType;  1-2.4(fck(SiSea init.sp|| afck(SiSea init.lhead * read fck(SiSea 		if +,fck(SiSea init.sp+p	prleu(gs;	p+p	(++ble5 <=s	,200s/am-
e|
+I'm _typffer_sb, maybet_va_rro	     ACLBitma. I igafR  j@ af_PER_BUon4-07rightt_b 4:-((SiSl-read fck(SiSea 		if +,fck(SiSacl init.sp+,fck(SiSea init.sp+p	prleu(gs;	p+p	(++ble5 <=s	,200s/amer;e4004fck(S_ese)ea,funrock er;*(rite_sue400409-11	eaiSnameleun=p	prleu(gs;	Nas5fs/crachar def COiSl-- ULONG  6f C&roo;n;
 	}
 	memset(AFFS_SB-S_SB
 }
 
 void
diff -NaAFFS_SB-S_SB
 aA3*r(PSIS_HW_4/fs/affs/amS_SB
 		if0(IS_
3 17:22S_SB->s_flags & SF_R
 		}
-		bh_array[i] = bfs/amS_SB
 		if
 static voi7:5.TV8+UL;
+	
-#endif
	u40(!AFFS08 *I-
-	/* Ok,funro
 }; lin i < B->s_s4ffsfilesys->s_leugiS_Po mem* definn
 	unsig/famA|easfilesy91,7 @@of EA'sp inv2NEEDEA4.27- definrite_ptor_id[16]sfilesyunu -X /ho-inn
 	unsigea 		ifsfilesy		if	_POverSrneG "of funro
+inn
 	unsigdeGao ea 		ifsfiesy		if	_POverSrneG "of funro
lse I-reagP dtTVY,fck(Si;eseral  ea- definrite_dasd_lim04.tf shhola_flinrite_dasd_lim04.deltauns5fs/crachar def COiSl-- ULONG  6f C&roo;n;
 	}
 	memset(AFFS_SB-	uPEoPn
 }
 
 void
diff -NaAFFS_SB-S_SBoPn
 aA3*r(PSIS_HW_4/fs/affs/amS_SBoPn
 		if (IS_ERR(page))
+				page = NULL;
 		}
-		bh_array[i] = bfs/amS_SBoPn
 		if 	minor = MINOR800
@@ -111,8 +111_bread	}
=27e	6eRuct.h	ncluint"S_SB
 "      /home/W
+			: "if W
+			    /home/W
+			:Overif W
+			  t.h /home/EIOERROR /EIOt.h /home/EFSERROR /EPERMt.h /home/EMEMERROR affs/s/* Inte1c Ex =18m,opts=/vgatypeslome/	/* Ok,S_SBo%s\al  *(S_nexrivate *SiSeslome/	/* Ok,- moudod+lockibuVB_Cfck(S_ea, unsignPd intCfck(S BLKS_P}
diff (	/* Ok,- moudod+lockibuVB_C)((rite_sufS sups/fck(SiSea 		if1;2.4.27-rc4(	/* Ok,- moudod+lockibuVB_C)((rite_sufS sups/fck(SiSea 		if +,fck(SiSacl init.s)/cramfs/te *SiSeslome/	/* Ok,- moudod+lockibuVB_Cfck(S_ese)ea, unsignPd intCfck(S BLKS_P}
diff (	/* Ok,- moudod+lockibuVB_C)((rite_sufS sups/fck(SiSea 		ifp+,fck(SiSea init.s1;2.4.27-rc4(	/* Ok,- moudod+lockibuVB_C)((rite_sufS sups/fck(SiSea 		if +,fck(SiSacl init.sp+,fck(SiSea init.s1;2ramfs/te *SiSeslome/	/* Ok,- moudod+lockibuVB_C:_	e(ea, unsign- moudod+lockibuVB_Cea)ns5fs/crachar def COiSl-- ULONG  6f C&roo;n;
 	}
 	memset(AFFS_SB-_uf (!b sis_video_info *ividS_SB-_uf (!baA3*r(PSIS_HW_4/fs/affs/am* Cu] mi2Pfu+,7 +r =4*bia2
+				page = NULL;
 		}
-		bh_array[i] = bfs/amaffs_init_b 4t_O_m2_TV,7:1ror? */
+			>-P, uns5f192_S3 +192_S3 static v	uPEoeROMLOH PER_unsigned int l)
 		if (v	uPEodag.e(ick(S_ea, unsigned int l,  unsignPd intCfck(S BLKS_P= MSfck(SiSacl init.l0|| fck(SiSacl init.s)/am-
e|
+Sns funk_b n7 @@ err_fs	}
k  ACLBmay -Nain fck(S,_PER_BUwe'd -Nto/li_typ_rro	      = NgSiSl-Bu12B,fck(SiSacl init.l0|| fck(SiSacl init.s)/am		struSns funk_b n7 @@ err_fs	}
k  ACLBmay -Nain fck(S,_+ER_BUwe'd -Nto/li_typ_rro	      = Nm 9+	uPEo) {
 	i    	b, "Pd int%08x igsions funk_b n7HPod3867 @ err_fs", iPER_BUF)"%d locked, %d i    	b_ %r	uPEoegsi>= 2)/am		locked*/, %d i    	b_ %r	uPEoegsi>= 2)/am + linux-2.4.27-rea[4]2.4.e(++  i    apping;
    	b_ %r	uPEoued i|| 
    	uPEoegoued iam
 9+ea[0ockei    appi&s	,ffNa(sb->59VGAE+>59VG*sb, st.od	uPEodag.e(ick(S_no)
 		kunsigned i); -333,7 S_SBo%s\al  *(SUF];
 	uiPER_BUF];g;
    	b_ %r	uPEo8  
45g8	nexType},
-{
ft sups>	uPEo:0
 ft su	i    	b, iPER_BUFk,&(!b;
*g8	nexTy-;
 	uiPER_BUF]ng;
    	b_ %r	uPEo8  
45amA|= MSiPER_BUF]ng;
    	b_ %r	uPEo8  
P A 
    slomk/_4/fs/af2U{(dext_buf ft suo%s\al 	i    	b, iPER_BUFk,fck(S, 	}(!b;
*{_SB->bs/cr= b* l 
 9+S0
irt_bh);
 	i-ocked,dstruct affs(af2US_ISREG	i    c4/fmmodeno,fck(SiSB->s_s4fftru(SiSB->s_s4fftrui    	 uns>+) fck(SiSB->s_s4fftrui    	 uns>+) (++ le)u(SiSB->s_s4fftrui    	 uns>  locked, %d S_ISDIR	i    c4/fmmodeno,fck(SiSB->s_s4fftru(SiSB->s_s4fftru0s>+) fck(SiSB->s_s4fftru0s>+) (++ le)u(SiSB->s_s4fftrus_bmap_b		uPEodag.e(ick(S_ea,ik,fck(SBUF];
 	udefs_init_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAefs/am;
+			res = -EIO;
 			gotofs/am;
+		aA3*r(PSIS_HW_4/fs/affs/am only.\n"0(IS_
3 17:22S_SB->s_flags & SF_R
 		}
-		bh_array[i] = bfs/am only.\n",
 			     loc(2 0SiS_S4		g-M l /* Int42_blo142 *I-
-	/* Ok,funrod*	uPEo:0
 fH PER_unsign(KER
lse Iges cIges cI12B,fck(SiSea init.sP A (--r (i = 0;)fck(SiSea 		if <s	,c40||b-eopes[B-r (i = 0;)fck(SiSea 		if +,fck(SiSea init.sp>s	,200sV 
 ] :Ees[B-r (i = 0;)fck(SiSea 		if +,fck(SiSacl init.sp+,fck(SiSea init.sp>s	,200s
*{_SB->+	uPEo) {
 		, "bad EAfor unin fck(St%08x: ea 		ifBitm%04x ea init.sBitm%04x} else e S_Ok,fck(SiSea 		ifk,fck(SiSea init.ssNaer;ing fnAbailNa(sb->2@@ -33>2@@ 6I-
-	/* Ok,dunrod*	uPEo:0
 dH PER_unsign(KER
lse ges cI
@@ -pt p20; px-2.ck(SiSB-TVYuct pa px+ru([p& MS(([p+1] << 8s
*{_SB->+-333,7 S_SBo%s\al  *(SPAL|T333,7 S_SBo%s\al  *)((rite_sudS sups/pF, uns5;
 	ude->leugiSp>s2920|| -de->leugiSp< 32)0|| -de->leugiSp& 31o:i      
 	ude->leugiSp>s2920|| -de->leugiSp< 32)0|| -de->leugiSp& 310|| px+ de->leugiSp>s2048
*{_SB->++	uPEo) {
 		, "bad %s\al  s4fftin dck(St%08x, %s\al  %03x, er_um%03x} 
g A 	haphappsNaer;inng fnAbailNalse Iges cIe(++  (31x+ de->nameleunttde->db n*4 con)0& ~3) !oide->leugiSo:i      e(++  (31x+ de->nameleunttde->db n*4 con)0& ~3) < de->leugiSp A s_ %rt661
 
 extervideo* s+f0ok;_SB->++	uPEo) {
 		, "nameleundofs	_typm661; %s\al  s4fftin dck(St%08x, %s\al  %03x, er_um%03x} 
g A 	haphappsNaer;inng fnAbailNalse Ige     ok:es cIe(++ s_ %r	uPEochkg>= 2)/b Miv1 << de->db n;es cIe(++ de->db n) af2Usuo%b n_sisfb_iudefs<>ax1 
*{_SB->++	uPEo) {
 		, "bad %b n7sisfb_inin dck(St%08x, %s\al  %03x, er_um%03x} 
g A 	haphappsNanit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAefs/ams/amA|= MS_RDONLY;
s =ch->safs/ams/amA|=aA3*r(PSIS_HW_4/fs/affs/am	 reserved;
 	S_ERR(page))
+				page = NULL;
 		}
-		bh_array[i] = bfs/amFO	b)
nAefin1,dex, u32 vb1
+				page = NULL;ern vo1d     1 *I-
-	/* Ok, copy them to	uPEoeROMLflags;
 	A); -_ %r	uPEowaEo) {
 trus_bmas_ %r	uPEocp_t, wharuct affs(s_ %r	uPEocme_S3 +ps>-1-fs	s_ %r	uPEomax_fwdos2_HW fs	,ffffffnu] 0fux- Lorcache FS %s\aAt
 yLKS_PER_BU! s_ %r	uPEobmpo%s\ps>	uPEolo04
+he FS_%s\aAt
 yt ,
givideo_4/->+he FSsb;
anit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejbd/transa_SISFB= MS_RDONLY;
s =ch->sajbd/transa_SISFB=aA3*r(PSIS_HW_4/fs/afjbd/transa_SISFB=hr(Pe3oupera *rec);
+/_HW_4/fsAFFS_SB-.rage = pages[iaA3*r(PSjbd/transa_SISFB=hr(Pe3o_O_m2_TV,7:0lags)_t temler_t *)map1692UF]loc92U23* s+u     0 MS_RDONLY;
+		0 @@ guid !er_	_oruct  (page) r;
 	/*  BOgid;struct supe000000b/* ag ffp->+inode.00b/* 
 		printk(KERN_N%s:(page)bh = :ead cs/ino%de.c li:eax
+	in__FUNCTION__,_+ER_puct  = , atomicne SIS&puccs/in),_puc.c linux-2.4SB->s_gbSo:i    
 		printk(KERN_N%s:(ag b_nexno%pc	ng s/i:ead bDType:%urhetre:eax
+	ie    __FUNCTION__,is_flagnexn,is_flag}
 	}
-
-	_flagType;e     	_flaghetreex);
euct pagflagb/do__rate_		lomp_f+-2.4.2* -268,) &ejouense_tr	: "X /homeramfs_r)rat		ifgP d/ho(page)eramfs_.ode.c	n52UF]lo760
 	}
 	) &ejouense_tr	: "X /homeramfs_rjouense_  0nr +p  	unsigned i, bloccHet+ps>tntunr>+) (++ un}
k ly(!ER_Bo:i     uid !er_	_oapp4ostb.h)BUG();m,optfs	, 0fu.4.2ps>tntflagb/do__rate_	if (AFb i, bljbd(p4.e6)(6R_BU!__jouense_tr	: "X /homeramfs(pha&frmine_o\"%s\");
anit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAeB->sB= MS_RDONLY;
s =ch->sajmAeB->sB=aA3*r(PSIS_HW_4/fs/afjmAeB->sB=hr(P3-11-2ra 8 +S0
 	}
 	me_S3 +S0
 	-.rage = pages[iaA3*r(PSjmAeB->sB=hr(Pn1,dex, u32 vb0b_ins_M;
* s+affs_itru70_S3 +Src4/fs/ad, read_arrjmA_open, unsigned int len)
 {
(af2US_ISREG	i_OH PER_c4/fmp A B->suc.-2.4.2& FLL;
_WRITEgned long 	i_OH PER_s4fftr= 0s
*{_SB- unsignj.26/fk(S_@ affsjP01-JFS_IP 	unrock aB- pinog83_Pirq(&ji  agog83_-2.4.e(++ ji  acb_ge_agBitma(o:{_SB->ji  acb_ge_agBi ji  agno;es cIatomicninc(es cIor;
 Jy %d I	i_OH PER_sbffs_batfldb_acb_ge[ji  agno]BUF pageaB- pinoou12B,
irq(&ji  agog83_-2.4.}gs | read_o -Na(sb-8oine +85c4/fs/ad, read_arrjmA_t  r + i unsigned int len);
@@ -333,7 j.26/fk(S_@ affsjP01-JFS_IP 	unrock r>+) pinog83_Pirq(&ji  agog83_-2.4.(++ ji  acb_ge_agBount(o:i ));unsigned FS *_init_bJy %d I	i_OH PER_sbffs_batl 
 94tomicndec(&_batfldb_acb_ge[ji  acb_ge_ag]BUF paji  acb_ge_agBi -1Type; +- pinoou12B,
irq(&ji  agog83_-2.4  0 MS_RDONLY;
+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAe_uf (!b sis_video_info *ividjmAe_uf (!baA3*r(PSIS_HW_4/fs/afjmAeaffs_init_b3-11-2ra 8 +S0
 	}
 	me_S3 +S0
 	-.rage = pages[iaA3*r(PSjmAeaffs_init_b 4t_O_m2_TV,7:1 	}
 	me_S3 +S0
 	}
 	49Y;
+	i9}
3 static vj.26_HW	rLOH PER_unsigned int lunro
l  0j.26/ffo("j.26_HW	rLOH PEELV_.c		i+ps>ax%p", iunrock r>+) pinog83_Pirq(&ji  agog83_-2.4.(++ ji  acb_ge_agBount(o:i ));unsigned FS *_init_bJy %d I	i_OH PER_sbffs_batl 
 94tomicndec(&_batfldb_acb_ge[ji  acb_ge_ag]BUF+paji  acb_ge_agBi -1Type; +- pinoou12B,
irq(&ji  agog83_-2.4  0ASSERT( ULONempty(&ji  anon6/fk(S_ ULOrning+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26btf (
 }
 
 void
diff -NaAFFjmAej.26btf (
 aA3*r(PSIS_HW_4/fs/afjmAej.26btf (
 it_b3-11-2ra 8 +S0
 	}
 	me_S3 +S0
 	-.rage = pages[iaA3*r(PSjmAej.26btf (
 it_b 	minor = MI8:12 0SiS_S4		g-M l /* Int,5tmap.c	2004-
-68,  Copyrightt(c) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pfu
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu 68,  itWundIS_OH uct
miS_PrOH uGNU,8 +268,7PubleadLicense aontubles;
 }by-rl_4/f82.4.2/f82.opts= locke4btpage){u 68,_PE_rdrOH upanv2;ra 
-i
 }dur000 +0o(sW	rc000f68,topnd/ame,_PE_rdrOH uHW	f(page/+			ifs  rb, A.
-			u   /home	MAXTREEHEIGHT		8
= locke4btd/ame,{0   0tam td/ame,KS_PEs64 bnsfilesy8:,KS_PEs16)bh = sfiesy2:,KS_-Es16)er_ubh = sfiesy2:,KS_-Eslocke4metapage) ntuiesy4:,KS_-};      g(16EAN PaEs16)er_ubh = sfiesy2:,unu -X /ho+Eslocke4metapage) ntuiesy4/8:,KS_+};      g(16/24vstruct. locke4bt0tam t
@@ -333,7 std/ame,*topHIP_TYPE5c Ex =24}
 	swi locke4bt0tam t
@@h /home/BT_CLR(bt0tam )\@@ (bt0tam )->topn>s(Pt0tam )->0tam  r>+h /home/BT_STACK_FULL(bt0tam )\@+	( (bt0tam )->topn>= &((Pt0tam )->0tam [MAXTREEHEIGHT-1]+ags@@h /home/BT_PUSH(BTSTACK, BN, INDEX)\@@{\@+	assert(!BT_STACK_FULL(BTSTACKrni\@@ (BTSTACKr->topfs_un=pBNi\@@ (BTSTACKr->topfsbh = n=pINDEXi\@@ ++(BTSTACKr->topi\@-	assert((BTSTACKr->topBoun&((BTSTACKr->0tam [MAXTREEHEIGHT]rni\@@}gs |h /home/BT_POP(bt0tam )\@	
 	buffaff141@ 6I-
-	/* Ok,bt0tam t
@@h /home/BT_STACK(bt0tam )\@@ ( (bt0tam )->topn>= (Pt0tam )->0tam  ?uct ap:/(bt0tam )->topn)
 	+d, read_alome/tic vBT_STACK_DUMP(	/* Ok,bt0tam t*bt0tam )
 	/* N &ei_g* 
 		pri"bt0tam tdump:y firsd;
@@ -463,       MAXTREEHEIGHT&d != s   
 		printk(KERN_N_un=p%Lx, bh = n=ps;
+	i
		struct p(unsign
ng)bt0tam ->0tam [i].bni
		struct pbt0tam ->0tam [i].bh = );mp_f+-2/fdef rievo(sW	rc0to_ufltm* defh /home/BT_GETSEARCH(IP, LEAF, BN, MP, TYPE, P, INDEX, a;
@)\@@{\@nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26uid !!b sis_video_info *ividjmAej.26uid !!baA3*r(PSIS_HW_4/fs/afjmAej.26uid !!bit_b3-06YP3 =4*51:3SB->s_flags & SF_R
 		}
-		bh_array[i] = bjmAej.26uid !!bit_b]lock %r  *bia3ror? */
+			>-P, uns5f1faff1e	6eRuc4-
-68,  Copyrightt(c) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf2
-68,  PorreturnCopyrightt(c) ChrULOoph Hellwig, \n"1(2Pf2
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4c+68,  PorreturnCopyrightt(C) ChrULOoph Hellwig, \n"1(2Pf2
t su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu 68,  itWundIS_OH uct
miS_PrOH uGNU,8 +268,7PubleadLicense aontubles;
 }by-rl_4/47_blo147@@ static vj.26trocS_HW	/read(stru (AFb + ft_rootmp_ -463,       NPROCENT000000000 	e[nlge_trocS+			i(En rieruct.name, b + focked, nlge_trocS+			i("j.2", b + foc+ed, nlge_trocS+			i("j.2", trocS i,
 fs-2.4.}gs}ng+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26d;
+			res = -EIO;
 			gotojmAej.26d;
+		aA3*r(PSIS_HW_4/fs/afjmAej.26u only.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26u only.\n",
 			     loc5800
@@ -111,8 +111_bret,5tmap.c	2004-
-68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf3
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu 68,  itWundIS_OH uct
miS_PrOH uGNU,8 +268,7PubleadLicense aontubles;
 }by-rl_4382_blo382_bl
 	) &edbFf (!Aprintked int lp, s64 blk 	ha.4.I2tic 1+af(ipb&mount
-	struthem tfnAbend/hod -Nto/libap inviinux-2 FSsize.,KS_-E(++ un}
k ly(blk 	ype;rivate >P	/sfldb_ FSsizefs/amA|= MSun}
k ly((blk 	yr= 0s0|| -
lk 	ype;rivate >P	/sfldb_ FSsizefsft_rootI2tic UN1+af(ipb&mount
  
 		printk(KERN_N_lk 	yrp%Lx, ;rivate rp%LxLL;
 		if (bloc(ost_s;
 	unsign
ng) blk 	hIP_TYPE05UF]lo2052.opts= l read_arrdbA2_HWNexvoid)
 		d FS *P	/s@@ -8 *HW	f_gign32 read bimA|= MSdsfltf (
HW	fidxBouncpu: "Xle32(LEAFINDBo:i    jPEo) {
 		/sfldb_ipb&mo    	b, ] :Ees"dbA2_HWNexv:	Corruprrd FS page"foc+ed, dirty, dO4.27S.2-	strupim tup a sisfb_inserOH uHW	veiS_PrOH ud FS tf (
d loKS_PEHW	f(= dsfltf (
stf (ypelta : "no opdsfltf (
HW	fidxm SF_RE1328fer = 34}
 	swidbA2_HWNearoid)
 		d FS *P	/s error;
	/* Ok,d FS *Pdp, s64 blk 	ha) &enbivat2UF bm-i2nb, s64 *to_ufltm );
@@  bm-wocak,lwocak,rAb, f-8 *HW	f(= dsfltf (
stf (ypelta : "no opdsfltf (
HW	fidxm S+ -8 *HW	f_g+mA|= MSdsfltf (
HW	fidxBouncpu: "Xle32(LEAFINDBo:i    jPEo) {
 		/sfldb_ipb&mo    	b, ] :Ees"dbA2_HWNear:	Corruprrd FS page"foc+ed, dirty, dO4.27S.2-+EHW	f(= dsfltf (
stf (ypelta : "no opdsfltf (
HW	fidxm S
-	strudect
mome/OH uwocap inviinux-2d FS t 0Sihola *biaths[nlis *t(i.e.,blk 	).  also,udect
mome/OH uer_umwocapiinux-2d FSp(attr->1+aff15ap(s3	swidbA2_HWAGoid)
 		d FS *P	/s F bm-agno, s  0ncpPAL|T333,7 d FSctl *) /sfld |= S0	budmom(= dcp->+idmom bimA|= MSdcp->HW	fidxBouncpu: "Xle32(CTLLEAFINDBo:i    jPEo) {
 		/sfldb_ipb&mo    	b, ] :Ees"dbA2_HWAG:	Corruprrd FSctl page"foc+ed,  r + _metapage(mpfoc+ed, dirty, dO4.27S.2-	strusW	rc0t32 vbfbtf (!A)S_PrOH ud FS 004-rol page t 0Sidesckibeslis *tOH us2_HWs
--- PER_Buc21ok000 mp_ sufficial  d/ho(sge)). tfnAbegin,lis *tdect
mome/how renyus2_HWs
--- PER_Bsar(dtrep(CAPfb_apiina2d FSp(attr69ock *s719c4/fs/ad, read_arrdbFbh Ctloid)
 		d FS *P	/s F 		incpPAL|T333,7 d FSctl *) /sfld |= S0		budmom(= dcp->+idmom bimA||= MSdcp->HW	fidxBouncpu: "Xle32(CTLLEAFINDBo:i     jPEo) {
 		/sfldb_ipb&mo    	b, ] :EEes"dbFbh Ctl:	Corruprrd FSctl page"foc+edd,  r + _metapage(mpfoc+edd, dirty, dO4.277S.2-	sstrusW	rc0t32 vtf (y inviinux-2d FS 004-rol page mp_ 		if* suffical  d/ho(sge)). t= Msufficial  d/ho(sge)) dond{
-		 		if* dbFbh LW	f(
*g8	nexs. l	afo = n_PrOH uHW	f(  8
hicha(sb->461+aff2488(s3	swidbAdjCtloid)
 		d FS *P	/s Fs64 blk 	ha)st.	}
diff , dO4. 0ncpPAL|T333,7 d FSctl *) /sfld |= S0mA|= MSdcp->HW	fidxBouncpu: "Xle32(CTLLEAFINDBo:i    jPEo) {
 		/sfldb_ipb&mo    	b, ] :Ees"dbAdjCtl:	Corruprrd FSctl page"foc+ed,  r + _metapage(mpfoc+ed, dirty, dO4.27S.2-	strudect
mome/OH ueW	f(91,7 @@correspond000 +erOH uthem t_4/lis *tOH ufo = n inviinux-2d FS 004-rol tf (
d loKS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26dtf (
		res = -EIO;
 			gotojmAej.26dtf (
	aA3*r(PSIS_HW_4/fs/afjmAej.26utf (
	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26utf (
	.\n",
 ck %r  *b0e3b_ins_M;
* s+affs_itru1,5tmap.c	2004-
-68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf3
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu 68,  itWundIS_OH uct
miS_PrOH uGNU,8 +268,7PubleadLicense aontubles;
 }by-rl_4/77k(REA77 unread, read_arrciComparu|T333,7  */
onal _naunread--;
-			dtGetKey(dtpages))
 s F bm-l,  unsign */
onal _name,* key
 		if (bld(isflagm S
--read--;
-			ciGetLW	fP/marcKey(dtpages))
 ls F bm-ll, dtpages))
 rp,b-eopes[ (bld(isrl,  unsign */
onal _name,* key
ld(isflagm S+d, read_arrciGetLW	fP/marcKey(dtpages))
 ls F bm-ll, dtpages))
 rp,b+eopes[ (bd(isrl,  unsign */
onal _name,* key
ld(isflagm S unread--;
-			dtInsertE			i(dtpages))
 s F bm-l  = ,  unsign */
onal _name,* key
 		ipesdd |=s))
 r5att T333,7 dt_hem to*	/* fix 42_blo 42_	6eR sinux-2n32 sddml  = (tids))tidt T333,7 i@@ -333,7 metapage) ntu_PEs64 S9>3/.h) ou bm-pagesS9>3/.h)-	d(isrAb,@ -333,7 them totlPstrucs64 xtoda;p_p(att37@@ 6I+37p(s96eR sinux-2n32 sddml  = (tids))tidt T333,7 i@@ d, dirtybh = sype;  1-2.4bh = n=AL|MAX_INLINE_DIRTABLE_ENTRYps/cBo:i    T333,7 dir_t, wh_slo))temp_t, wh[12];.2-	sstr 		if* Ir  *btche+ermvde. l	afolome/t, whasb_gn/te *Sial 		if* page)_4/fbegintfnAbuildrOH uxtf ( 		if*/mA||= MSdbA2_HW(lp, 0ROMLi->nbperagb*s &xtoda+ags)
 g fnAcHW	/_utuiesyNo(sge)) truct.sstr 		if* Sade. l	at, wh,Uwe'(dtgo000 +er_rro	     itW inv2;
  		if* xtf (f8  
 		if*/m-  T333,7 dir_t, wh_slo))temp_t, wh[12];. :EW
+			0temp_t, whs &j.26/o    %s\", whs sizeof0temp_t, wh)m S
-	sstr 6)(63N5c Ex ux-2.26eR sinux-2n32 sddml  = (tids))tidt T333,7 i@@ dtr 		if* A2_HWs
e. l	adtTVY,them t& sdd itW+erOH uxtf ( 		if*/m-  xtoda01-09--/e(++  rc =_PER_BUF;xtInsert(tidt lp, 0RO0ROMLi->nbperagb*sb-eopes[ (b&xtodak,0VmmodeA||= MSxtInsert(tidt lp, 0RO0ROMLi->nbperagb*sb&xtodak,0Vm:i     /* T/donres2_ygdeGuldn'tB->s_oKS_PE  jPEowarn("sddml  = :;xtInsertf letel!+/* locd, dirty, PERMoc+eddW
+			0&j.26/o    %s\", whs temp_t, whsb+eopes[ (b sizeof 0temp_t, wh)m Ss)
 g fnAcHW	/_utubh);
 	i	/o     are dat;
-ext	i	/o    rivate += LBLK2PBLKROMLaMLi->nbperagb*	/* fix40(!AFFS10,96eR sinux-2n32 sddml  = (tids))tidt T333,7 i@@ d(++  .2ps>nes l  = er_	_olp, 0Vm:r= 0s0{_PE  jPEo) {("sddml  = :;nes metapage) letel!+/* PE  xtTrunWs
e(tidt lp, 0ROCOMMIT_PWMAP/* locd, dirty, PERMoc+eddW
+			0&j.26/o    %s\", whs temp_t, whsb+eopes[ (b sizeof 0temp_t, wh)m Ss)
 g fnAcHW	/_utubh);
 	i	tlPsps>txL
 		tidt lp, /s FtlPsDATA/* PE llb;
* s+333,7 lomehem to)0& tlPs->H_Pstr fix4382.op+442_96eR sinux-2n32 sddml  = (tids))tidt T333,7 i@@ d * T/donwillibapOH uteginnstatif( >SIS page 		if*/m   xtoda01-09--/e(++  rc =_PER_BUF;xtInsert(tidt lp, 0ROblk 	haMLi->nbperagb*sb-eopes[ (b&xtodak,0VmmodeA||= MSxtInsert(tidt lp, 0ROblk 	haMLi->nbperagb*sb&xtodak,0Vm:i PE  jPEowarn("sddml  = :;xtInsertf letel!+/* locdj.26/o  :_	e(l  = -30 16:2, dirty, PERMoc+eddg fnAcHW	/_utubh);
 	i	/o     are +dat;
-ext	i	/o    rivate += LBLK2PBLKROMLaMLi->nbperagb*	/* fix45ng-zin58ext_buffer;
 n32 sddml  = (tids))tidt T333,7 i@@  1-2.4mp:r= 0s0{_PE jPEo) {("sddml  = :;nes/eROMLmetapage) letel!+/* -:2, dirty, PERMoc+edg fnAcHW	/_utubh)}gs | 12B,
i  = (tidt lp, /s Fbh = );m fix472UF]l4732.26eR sinux-2n32 sddml  = (tids))tidt T333,7 i@@ ,  r + _metapage(mpfoc4  0 MS_RDObh = sy+
+innnnncHW	/_ut:.2-+Ej.26/o  :_	e(l  = -30 +2.4.27-rc4NLY;
+		 tr 6)(6760_S3 +S6-2.26eR _arrdtSW	rc0!Aprintked int lp, sunsign * 		if*/m  innnnnnesChild:-	sstruupu]egimax.y91,7 @@of ic intto(sglitf*/m-   (AFbt0tam ->nsglitf>= 8modeA||= MSBT_STACK_FULL(bt0tam )m:i PE  |
+Sns nviig's@corrupredt 0x%x B->ssytem %s\")(so 		ipe*Achkdsknwilliarc it. 		ipe*/_PE  jPEo) {
 		b, "0tam t_rrorunnin dtSW	rc0!"foc+eddBT_STACK_DUMP(bt0tam )l 
 9+SW fs, dO4. 0edg fnAoup_bh);
 6)(6971k(RE9792.4.e(+d, read_arrdtSglitUp(tids))tidtbh);ty,= DTa;
@MAXSLOT -(sg->occHer.d/hocnt;2/fdoccHerntten riere*/_PE B,
oun<=(sglit->nslo)0000 	xlen++9--/e(++  rc = dbA2_HW(lp, 0RO(s64) xlens &xtoda+a)eA||= MS rc = dbA2_HW(lp, 0RO(s64) xlens &xtoda+a):i     DT_PUTfsin(smpsNaer;ipagP d/hoKeyName;m,opts=t
  
xd ULO.maxn
xd01-1Type 
xd ULO.n
xd01--Na(sb-982_blo992_96eR sinux-2_arrdtSglitUp(tids))tidtbh);sglit->
xd ULO01-&
xd ULONaer;
c = dtSglitR  
(tidt lp, sglits &rmpfoc4 -  DT_PUTfsin(rmpfoc+edR_BU!rc)     DT_PUTfsin(rmpfoc+aer;DT_PUTfsin(smpsNaeaer;pagP d/hoKeyName;mitru1150	}
= sb2 166eR sinux-2_arrdtSglitUp(tids))tidtbh);x-2.4(-g->occHer.dlag0& BT_a;
@p A skip >t(m ||es cIor;
-g->occHer.prev*!fs	0|| skip >t(m {_SB->+/fd */
uVB_upperc + f8 ub_inp/marc keyf*/m-  		ciGetLW	fP/marcKey(lp,b-eop cIor;lg->occHer.:_	ebh = n- 1,b-eop cIor;rp, 0RO&key
lMLi->mntflagm S+	 9+SW fsciGetLW	fP/marcKey(lp,b     eE lg->occHer.:_	ebh = -1,b     eE rp, 0RO&key
b     eE MLi->mntflagm S+	 9+},
-Sco:i      eDT_PUTfsin(lmpfoc+edd  DT_PUTfsin(rmpfoc+ed   DT_PUTfsin(smpsNa+r;inng fnAsglitOup_bx = Iges cIgIS_HW_4/fs/ilesy94.26	sbckftmoLO0+			ifof/fs/ilor;lowestked *Sialbckve_oKS_itru1876ck *s895_96eR sinux-2_arrdtSglitR  
(tids))tidtbh)xleun=pleugiSPXD(
xdsNaerx are daxleun<<bJy %d I	sbffsl2b	 uns>  r.2ps>nes metapage(lp, rbns x are, 1m SA|= MS_rmpfc+ed, dirty, dO4.2>  r+p= r/sfld |= S0m dBT_MARK_DIRTY(rmpt lp	/* fix 326ck *33482.opts= l read_arrdtRccHFtTVY!Aprintked int lp,@@ dtr 		if* descend %b n7	sbckftmoLO0child page 		if*/mA||= MSBT_STACK_FULL(bt0tam )m:i     DT_PUTfsin(mpsNa+r;ijPEo) {
 	io    	b, "dtRccHFtTVY:,bt0tam t_rrorun"foc+eddBT_STACK_DUMP(bt0tam )l +edd, dirty, dO4.277S.	sstrupushAFbn Fbh = )S_PrOH uparubm-page/+			if*/_PE BT_PUSH(bt0tam RObnk,0V;p_p(att37f82.8I+3736,2unread, read_arrciComparu|T333,7  */
onal _naun *-read fverStwo sdjacal  eW	f(en rierun *-read across(page)e{
-	aryu 68
-68,, dirt:
-68	N1,7 @@of i/marc o mem*amA|ed7	sbdULOiiguishAb fverSa.
+68,, dirt: non-zeroUon4) {
 
+68	
-			u read--;
-			ciGetLW	fP/marcKey(dtpages))
 ls F bm-ll, dtpages))
 rp,b+d, read_arrciGetLW	fP/marcKey(dtpages))
 ls F bm-ll, dtpages))
 rp,bs cIor;
 (bd(isrl,  unsign */
onal _name,* key
ld(isflagm);
@@  bm-klens namlens>  writes))
pl,)
pak,*kname;m- writes))lname[Jy %NAME_MAX0+ 1]HI-Eslocke4 */
onal _name,lkeyf= { 0ROlname };m- writes))rname[Jy %NAME_MAX0+ 1]HI-Eslocke4 */
onal _name,rkeyf= { 0ROrname };m+Eslocke4 */
onal _name,lkey;m+Eslocke4 */
onal _name,rkey;m+-+EHkey.name
* swrites))
) kms2_HW((Jy %NAME_MAX0+ 1)f* sizeof0writes))
b     eGFP_ntk(ELm SA|= MSHkey.name
*oidpst/b+ed, dirty, NOSPC0 +2.4.key.name
* swrites))
) kms2_HW((Jy %NAME_MAX0+ 1)f* sizeof0writes))
b     eGFP_ntk(ELm SA|= MSrkey.name
*oidpst/:i    	if (!Hkey.namefoc+ed, dirty, NOSPC0 +pts=t
 tru46efckft)_4/frighttkeyf*/m 	dtGetKey(ls Fll, &lkey
lflagm S(att3744_blo 782ext_buffer;
 
-			ciGetLW	fP/marcKey(dtpages))bs c*kname
* 
pa2.4.e(++ 
pl*!fs
pam {_SB->key->namleun=pkleuntt10 16:2, dirtoc+eddg fnA /homnames_bh);
 	i-p_p(att37@5_blo 7932.4.e(+d, read
-			ciGetLW	fP/marcKey(dtpages))bs gIS_HW/ilesyliSnameleun== riSnameleun*/_PE key->namleun=pkleuoc4 - , dirtoc+ /homnames:id;	if (!Hkey.namefoc+e	if (!rkey.namefoc+e.27-rc4NLY;
+		 _nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26- mout
		res = -EIO;
 			gotojmAej.26- mout
	aA3*r(PSIS_HW_4/fs/afjmAej.26- mout
	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26- mout
	.\n",
 inor = MINOR800
@@ -111,8 +111_bre55cracha5 def CO- mBs2_HW(Aprintked int lp, s64 hs[n, s6@@  1-2.4S_ISREG	ipPER_c4/fmp A  ji  B->ss0
 9= FILESYSTEM_I)m:i PE agBi BLKTOAG(dtodak,MLick aB- pinog83_Pirq(&ji  agog83_-2.4.e(++ ji  acb_ge_agBitma(o:{_SB->atomicninc(&	/sfldb_acb_ge[ag]BUF paaji  acb_ge_agBi ag S(att562UF]l563def CO- mBs2_HW(Aprintked int lp, s64 hs[n, s6@@B->atomicninc(&	/sfldb_acb_ge[ag]BUF paaji  acb_ge_agBi ag S pageaB- pinoou12B,
irq(&ji  agog83_-2.4.}gs | read_o (0sNanit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26i;
+			res = -EIO;
 			gotojmAej.26i;
+		aA3*r(PSIS_HW_4/fs/afjmAej.26i only.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26i only.\n",
 inor = MI8:2
+				page = NULL;P_TYPE86ck *sE86cbl
 	) &ediFf (!Aprintked int lp)lis *tOnAbend/hod -yt32 vtfansa_SISF;  d loKS_PEtidps>txBegin	ipi&mo    	b,OCOMMIT_FORCEck aB%b n(&JFS_IP 	pi&mo)uccsmm04.semm S
-	struacquire them t_PrOH uiagBpage)_PrOH ud/hod ixad lis *tOnAfoffsrOH upage)NOHOMEOK (kveinuxoughR  jd |= isSF_RE131ock *s 1RDON
 	) &ediFf (!Aprintked int lp)lisSW fstxCsmm04(tidt 1, &ip ULO[0],OCOMMIT_FORCEck  listxEnd(tidck aBup(&JFS_IP 	pi&mo)uccsmm04.semm S
-	struou12B,rOH uAGked int FS /fforms
--- KS_PEAG UN1+af(i FS,-agnosNa(sb->630Y;
+	>632(s3	swidiNewIAGoid)
 		ed  FS *Pi FS,-) &e*iagn 		if*/m #endifs/ilesy _STILL_TO_PORTn*/_PE tidps>txBegin		b,OCOMMIT_FORCEck aBB%b n(&JFS_IP 	pi&mo)uccsmm04.semm S
-	sstruupu]egi l	afo int FS todaessstat @@ err_ftOnAsisfbtOnAitf*/m /e(++  rc =_ ER_BUF;xtInsert(tidt lpi FS,-0ROblk 	haxlens &xtodak,0VmmodeA||stxEnd(tidck aB	Bup(&JFS_IP 	pi&mo)uccsmm04.semm S
/ilesyFf (rOH uthem sus2_HWs
 < BorrOH uiagBsstc  itW as 		ipe*A_typffccessfu2_ygtoded7	sb l	afo int FS 		ipe*/_(sb->65ock *2663def COdiNewIAGoid)
 		ed  FS *Pi FS,-) &e*iagn 		iSW fstxCsmm04(tidt 1, &ip ULO[0],OCOMMIT_FORCEck  lisstxEnd(tidck aB	up(&JFS_IP 	pi&mo)uccsmm04.semm S
-	s	dup UWs
 IXtf (!AbROblk 	haxlens &xtodaning+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26stcor(
 }
 
 void
diff -NaAFFjmAej.26stcor(
 aA3*r(PSIS_HW_4/fs/afjmAej.26itcor(
 it_b3-11-2ra 8 +S0
 	}
 	me_S3 +S0
 	-.rage = pages[iaA3*r(PSjmAej.26itcor(
 it_b,
 ck %r  *b0e2ror? */
+			>-P, uns5f5cracha4 *I-
-	/* Ok,j.26/fk(S_@ aff{_SBlids)	blidsfiesylid@of iseudoed i, b?	KS_PEHids)	atloccH,+yt_bnonymous them t ULO0occH	KS_PEHids)	atltailN+yt_bnonymous them t ULO0tail7t(2Ii pin12B,
m-agog83_N+yt_protectsuscb_ge_ag		KS_PE+333,7 lostloccHeanon6/fk(S_ ULO;2/fd/fk(Ss igastatbnonymous txnre*/_PEtr 		)
 rdwrhem tserializes xtf (fbetweenoffal
 
 	    s)_4/fsynchronizes+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26logmgA|= MS_RDONLY;
s =ch->sajmAej.26logmgA|=aA3*r(PSIS_HW_4/fs/afjmAej.26logmgA|=.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26logmgA|=.\n",
 ck %r  *bia5SB->s_flags & SF_R	
 	buf1+aff1uf1+ON
 	) &elmLogClosER_unsign(KERN_ERR "AFFb, s  0blkdev_put(log->bdev, BDEV_FSm S
-							u    d;	if (!Hogm S 0j.26/ffo("lmLogClosE:O- 04(%d)"k,rAm S 0read_o rAb,@
+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26metapage|= MS_RDONLY;
s =ch->sajmAej.26metapage|=aA3*r(PSIS_HW_4/fs/afjmAej.26metapage|=.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26metapage|=.\n",
 inor = MINO56_ins_M;
* s+affs_itru1,5tmap.c	2004-
-68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf3
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct s,  PorreturnCopyrightt(C) ChrULOoph Hellwig, \n"1(2Pf2
t su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu(sb->81,3sin281,48I-
-	/* Ok,metapage) __nes metapage(T333,7 i@@  1-2.4absoluVB0000 &mopstat= i_OH PER_sb_ %rbdev->bd_i_OH PER_cmopsta0 16S_HW d;_ 1a)
+	tm4-
+	if* If_gn/nfs clial   riere	sbrecHeanafo intt 0Sidonlarger
+	if* t 0n enyu- 0LOiigd/fk(Ss,UweBmay 		ifgP recHepr_um;
  +	if* end _PrOH uio int FS +	if*/mA||= MS(lERR "A<< i_OH PER_blkbits)f>= i_OH PER_s4ff) +edd, dirtyct affs( &mopstat= i_OH PER_cmopsta0 1I-Espinog83_(&metaog83_-2.+pts=t
 hash_pta01-metaohash(cmopsta, lERR "/* -
+again:>+) pinog83_(&metaog83_-2. 	.2ps>sW	rc0ohash(hash_ptat 0xopsta, lERR "/*  1-2.4mpo:{_SB						pagesd{
-	:>+)	mpuccs/in++9-+)	12B,
metapage(mpfoc+ed pinoou12B,(&metaog83_-2.+p1-2.4  st
+he(METAghetwhs &mpuc.c lmmodeA||s,  r + _metapage(mpfoc+eddyiel (nuux- Let oOH r 5:04eronre r +  its toof*/mA||dg fnAagain4.277S.	ss-2.4  st
+he(METAgdULcacak,&mpuc.c lmmode6)(6R_BU!newmodeno, ,spinoou12B,(&metaog83_-2.fs/iljPEo) {
 	i_OH PER_sb else e   "__nes metapage: usstata "else e   "dULcacaed7metapage"foc+edd ,  r + _metapage(mpfoc4	edd, dirtyct affs( Iges cI_HW	rL+he(METAgdULcacak,&mpuc.c lm S page-)	mpuccs/in++9-PE jPEo/ffo("__nes metapage: d{
-	>ax%p,-)  igsh", /s-2.4.e(++ mpucHogUWsl init*!fss4ff)odeno, spinoou12B,(&metaog83_-2.fs/ijPEo) {
 	i_OH PER_sb else e  "__nes metapage: mpucHogUWsl init*!fss4ff"foc+edd,  r + _metapage(mpfoc edd, dirtyct affs( ge-)	12B,
metapage(mpfoc-, spinoou12B,(&metaog83_-2.fsgIS_HW_4/fs/l2b	 unt= i_OH PER_blkbits* PE l2Bhem sPerPage)= fsin_CACHE_SHIFT -(l2b	 uns> fix 3  sin3492.4.e(+d,* Ok,metapage) __nes metapage(T333,7 i@@eddno_5:04trus_bmfs( &px-2.2_HW_metapage(&droppedog83_, no_5:04foc+edR_BU!mpo:{_+o, spinoou12B,(&metaog83_-2.+edd, dirtyct aff277S.	ss-2.4droppedog83_m:i PE  |
+.2_HW_metapageuthem edt weBamA|tto(sW	rc0t32 vigsh 		ipe*Aagain.	}
 	498,4acha14,5@ static v,  r + _metapage(d,* Ok,metapage) @  1-2.4--mpuccs/in0|| atomicne SIS&mpucnoinito )m:i PE ou12B,
metapage(mpfoc edspinoou12B,(&metaog83_-2.-sgIS_HW_4/ked, nlge_fverohash(cp, /etaohash(cpuc0xopsta, mpfsbh = )foc-, spinoou12B,(&metaog83_-2.---/e(++ mpfsagb*	odeno, kun3 +Smpfsagb*	0 16:2/sfld |=01-09--/es-2.4  st
+he(METAgdUrtyk,&mpuc.c lmmeno, ,_odag.e(metapage(mpfoc-, 1-2.4  st
+he(METAghynck,&mpuc.c lmmodeno, ,sync(metapage(mpfoc-, 1I_HW	rL+he(METAghynck,&mpuc.c lm_b-eoptf---/es-2.4  st
+he(METAgdULcacak,&mpuc.c lmmode-, 1I12B,
page(mpfsagb*	0 16:2	them _flushpage(mpfsagb*k,0V;p16:2	Uu12B,Page(mpfsagb*	0 16:2}c+ed, dirt2.+pts=t16:2pagescat_e_t  r + impfsagb*	0 16:2INCREMENTimpStat.agb*d/hom SA|= MSmpfsagb*	ode	tm4- R  r +stat pin12B,t weBigafRfnAche "Ampuccs/in0lab_in*/mA||s
 	+he(METAghetwhs &mpuc.c lmoc+ed pinoou12B,(&metaog83_-2.+p1kun3 +Smpfsagb*	0 +:2/sfld |=01-09-+p1-2.4  st
+he(METAgdUrtyk,&mpuc.c lmme+, ,_odag.e(metapage(mpfoc+p1-2.4  st
+he(METAghynck,&mpuc.c lmmode+, ,sync(metapage(mpfoc+ 1I_HW	rL+he(METAghynck,&mpuc.c lm_bh);
 	--/e(++ mpfslsnmode-, 14-
-	ipe*AR nlge,metapage)fverSHoghync ULO.
-	ipe*/m-  	Hog01-mpucHog0 16:2LOGSYNC 1+af(Hogm S16:2/sflHog01-0 S16:2/sflHsn01-0 S16:2/sflcHsn01-0 S16:2log->cs/in-30 16:2lostldelS&mpuchync ULO)0 16:2LOGSYNC UN1+af(Hogm S+p1-2.4  st
+he(METAgdULcacak,&mpuc.c lmmode+ 1I12B,
page(mpfsagb*	0 +:2	them _flushpage(mpfsagb*k,0V;p+:2	Uu12B,Page(mpfsagb*	0 h);
 	--/e /hommetapage(mpfoc+ 1pagescat_e_t  r + impfsagb*	0 +:2/sflpage)= ct aff277INCREMENTimpStat.agb*d/hom SA|) pinog83_(&metaog83_-2. 	}g+mA|= MSmpfslsnmode	tm4-
+	if* R nlge,metapage)fverSHoghync ULO.
+	if*/mA||Hog01-mpucHog0 +:2LOGSYNC 1+af(Hogm S+:2/sflHog01-0 S+:2/sflHsn01-0 S+:2/sflcHsn01-0 S+:2log->cs/in-30 +:2lostldelS&mpuchync ULO)0 +:2LOGSYNC UN1+af(Hogm S+p}mA|= MSmpfscs/in)ode	tm4- Sns oneocked, s 		i000 +er46efb/do,metpage) /mA||ou12B,
metapage(mpfoc+ed pinoou12B,(&metaog83_-2.+p1, dirt2.+pts+d, nlge_fverohash(cp, /etaohash(cpuc0xopsta, mpfsbh = )foc+d pinoou12B,(&metaog83_-2.+c+d /hommetapage(mpfoc;
+		 tic v_o/fvaliu]egmmetapages(Aprintked int lp, s64 todak,) &elen)1_bre55d	}
=584,20 static v_o/fvaliu]egmmetapages(Aprintked in. 	mp_ -lERR "A= toda; lERR "A< todaypeltns>  					lERR "A+iv1 << l2Bhem sPerPages/am 9+	ash_pta01-metaohash(cmopsta, lERR "/* +again:> |) pinog83_(&metaog83_-2. 		.2ps>sW	rc0ohash(hash_ptat 0xopsta, lERR "/*  11-2.4mpo:{_+, 1-2.4  st
+he(METAghetwhs &mpuc.c lmmodeA||sm4- Rac000  inv2,  r + _metapagef*/mA||d	mpuccs/in++9-+)	)	12B,
metapage(mpfoc+ed, spinoou12B,(&metaog83_-2.+eddm4- rac000 ,  r + _metapagefdeGuldAbendoneo_b 4*/mA||d	,  r + _metapage(mpfoc+edddg fnAagain4.2777S.2-	ss|s
 	+he(METAgdULcacak,&mpuc.c lm S pa spinoou12B,(&metaog83_-2.fs/gIS_HW_4/nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26metapage| }
 
 void
diff -NaAFFjmAej.26metapage| aA3*r(PSIS_HW_4/fs/afjmAej.26metapage|hit_b3-06YP3 =4*51:3SB->s_flags & SF_R
 		}
-		bh_array[i] = bjmAej.26metapage|hit_b 4t_O_m2_TV,7:12 0SiS_S4		g-M l /* In6crach64 *I-
-	/* Ok,metapagef
@@h /home/METAghync	4@@h /home/METAgdULcaca	5@@h /home/METAgfoffsd	6>+h /home/METAghetwh	7gs |h /home/0x%x6metapagegdUrty4mpo:s
 	+he(METAgdUrtyk,&4mpouc.c lmng+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26txnmgA|= MS_RDONLY;
s =ch->sajmAej.26txnmgA|=aA3*r(PSIS_HW_4/fs/afjmAej.26txnmgA|=.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26txnmgA|=.\n",
 			     loc(b_ins_M;
* s+affs_itru1,5tmap.c	2004-
-68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf3
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct s,  PorreturnCopyrightt(C) ChrULOoph Hellwig, \n"1(2Pf2
t su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu(sb-175_blo175_6.e(+d, read
-			dtLog(	/* Ok,j.26Hog0*SHog F 		i-333,7 them to tlPs-2.fd, read
-			0xoLog(	/* Ok,j.26Hog0*SHog F-333,7 tbhem to tblk F-333,7 lrd0*SHrdtbh);s333,7 them to tlPs-2. read--;
-			txAborrCsmm04(slocke4 */mitf* cd-2.fd, read
-			txA2_HWPM +SAprintked int lp, sunsign0xohem to 0xohem tbh);s333,7 tbhem to tblk-2.fd, read
-			txFoffs(s333,7 tbhem to tblk-2.P_TYPE95_blo1294+ON
 	) &etxCsmm04(tids))tidtdm4- tfansa_SISF S
-							u     +},
-Sc*!fs	meno,txAborrCsmm04(&cdck aB	txAborr(tidt 1m S
-							TheEnd:-	sjPEo/ffo("txCsmm04: tidps>%ak,r dirt000 %d",)tidt rAm S(sb-1706_blo17052.4.e(+d, read
-			xtLog(	/* Ok,j.26Hog0*SHog F 	  11-2.4lwmBitm94.2)aer;ipagP oup_bno,assert(lwmB<m94.2) S+p1-2.4lwmB>m94.2):i     jPEo) {("xtLog: lwmB>m94.2\n"foc+eddpagP oup_b+);
 	i	tlPsuc.c l MivtlPsUPDATEMAP2.fs/xado_4/->.c l 1-mlPsAL1+aXADLIST2.fs/xado_4/->cs/in0tm94.2 -(lwm;_itru1872,25tma87p(s8.e(+d, read
-			xtLog(	/* Ok,j.26Hog0*SHog F 	 dtr 		if*      	     Hog0_PE_rds 		if*/m- 14-
-	i *us2_HWs
 ten riereXAD[lwm:94.2]:e	tm4- Hog0af_Se-image mp_ Hog16do():
+	if*
+	if* Hog16do()nwilliupu]egid FS mp_ s2_HW of>SIS/- moudod +	if* e mouts (XAD_NEW|XAD_EXTEND)S_PrXAD[lwm:94.2))fver +	if* af_Se-image _PrXAD ULONa+	if* Hog16do()n(CAPts (XAD_NEW|XAD_EXTEND)S.c l when +	if* apply000 +0o(af_Se-image 	sb l	ameta-d |=0page| 		if*/m- 1-2.4lwmB<m94.2):i -	tm4- Hog0af_Se-image mp_ Hog16do():
-	ipe*AHog16do()nwilliupu]egid FS mp_ s2_HW of>SIS/- moudod -	ipe*Ae mouts (XAD_NEW|XAD_EXTEND)S_PrXAD[lwm:94.2))fver -	ipe*Aaf_Se-image _PrXAD ULONa-	ipe*AHog16do()n(CAPts (XAD_NEW|XAD_EXTEND)S.c l when -	ipe*Aapply000 +0o(af_Se-image 	sb l	ameta-d |=0page| -	ipe*/m-  	Hrd->type)= cpu: "Xle16(LOG_REDOfsin)0 16:2PXDtodaess(
xd, mpfsbh = )0 16:2PXDleugiS(
xd,p16:2	  mpucHogUWsl init*>> tblkuchb->p16:2	  s rivatenit.bits);m-  	Hrd->backchaom(=b-eopes[ cpu: "Xle32(lmLog(Hog Ftblk FHrdt tlPs-);m-  }c+edHrd->type)= cpu: "Xle16(LOG_REDOfsin)0 +:2PXDtodaess(
xd, mpfsbh = )0 +:2PXDleugiS(
xd, mpucHogUWsl init*>> tblkuchb->s rivatenit.bits);m+ 	Hrd->backchaom(= cpu: "Xle32(lmLog(Hog Ftblk FHrdt tlPs-);mF 	 dtr 		if* trunWs
e0+			ifXAD[twmBitm94.2n- 1]:e(sb->58ffaff2584,@ static vtxAborr(tids))tidt ) &edi\");_PEHids)ylid,m94.2b,@ -333,7 metapage) ntu_PEs333,7 tbhem totblk fstids)o_tbhem (tidck aB-333,7 them totlPstru-	sjPEowarn("txAborr: tido%dedi\"):0x%x",)tidt di\");;p_p(att2596	}
=25922.4.e(+tic vtxAborr(tids))tidt ) &edi\");_PEf* d/ho(them su_PrOH utfansa_SISFd loKS_PEmp_ -lidps>tblkuc94.2bylidbylid0tm94.2):i -	t94.2n= lids)o_them (lid)uc94.2bf---/e.2ps>lids)o_them (lid)ucntu_+i	tlPsps>lids)o_them (lid)u_+i	94.2n= tlPsuc94.2bf+/e.2ps>tlPsucntu_+i	JFS_IP tlPsucipoucxtlid0tms_bmfs( -2.4mpo:{_SB:2/sflHid01--Na(sb-2633,64+	>630_6.e(+tic vtxAborr(tids))tidt ) &edi\");_PES0
irt_bh
 	--
-4-
-68,     txAborrCsmm04()
-68
-68,funWSISF: aborr4 */mit.
-68
-68,f/hos(them su_PrOfansa_SISF; lome-hem sus4/fsegmal  eem sump_ s2_
-68,segmal s-)   */d |=0 @@ err_f.,f/hos(ms2_HW0 @orage -68,se s-hetreu_PrB->susystem 	sbFM_MDIRTY-)  (KERN-bhem .
-68 Hog0age _Prpage-d/ames-)  mem
 yLmp_ 
hichELV_.crvigs
-68 r(dtres0
 	sb0 (fnAatic vHogwarap).
-68/. read--;
-			txAborrCsmm04(slocke4 */mitf* cd-
-{I-Eslocke4tbhem totblk;m- tids))tid;m- Hids)ylid,m94.2b,-Eslocke4metapage) ntuf---/jPEowarn("txAborrCsmm04: cd:ax%p", cdck ---/4-
-	f* d/ho(them su_PrOH utfansa_SISFd-pe*/m- tidps>cd->tid;m- tblk fstids)o_tbhem (tidck -Emp_ -lidps>tblkuc94.2bylidbylid0tm94.2):i -	t94.2n= lids)o_them (lid)uc94.2bf---/e.2ps>lids)o_them (lid)ucntu_-( -2.4mpo:{_-B:2/sflHid01--Na-e-, 14-
-	ipe*Ares0
 Hsn0_Prpage fnAatic vHogwarap; -	ipe*/m-  	= MSmpfsxdlag0& COMMIT_Psin)p16:2	LogSyncR  r + imp);m-  }c-m- 14--) sertfthem taO0occHu_PrB/ho ULO0*/m-  TXN 1+af();m-  txL
 	Ff (!lidck -E TXN UN1+af(-2.-sgc-m- tblkuc94.2ps>tblkucer_um1--Na-e-,/* d/ho(tH utfansa_SISF,them t*/m- txEnd(tidck ---/4-
-	f* 0x%x B->ssystem %s\")d-pe*/m- jPEo) {
 	cd->	b, "txAborrCsmm04+/* -gc-m-004-
 68,     txLazyCsmm04(ead(str68
nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26txnmgA| }
 
 void
diff -NaAFFjmAej.26txnmgA| aA3*r(PSIS_HW_4/fs/afjmAej.26txnmgA|hved;
 11-2ra23:53b1
+				page = NULL;
 		}
-		bh_array[i] = bjmAej.26txnmgA|hit_b 4t_O_m2_TV,5:1SB->s_flags & SF_R	
 	b,5tmap.c	2004-
-68,  Copyrightt(c) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf2
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu 68,  itWundIS_OH uct
miS_PrOH uGNU,8 +268,7PubleadLicense aontubles;
 }by-rl_48ff 6I+8ff 6I CO- mSenF-333,7 tbhem toTxBg83_N+yt_tfansaun *-tfansa_SISF,g83_
-			u -333,7 them t{m- Hids)y94.2b 14--)  = n94.2phem wocapSF,tc vHock ULO-+EHids)y94.2b 14--2:-)  = n94.2phem wocapSF,tc vHock ULO-lse e 8,         94.2phem wocapSF,B/ho ULO-lse e 8/m- tids))tid;dm4- tfansa_SISF c vholaisign
m t*/m+ tids))tid;dm4- 2:-tfansa_SISF c vholaisign
m t*/mmfs(u 6Idlag;dm4- 2:-n
m t004-rol KS_PEu 6Itype;dm4- 2:-n
gItypet*/mmf-Eslocke4metapage) ntuiesy4:,obje  (page)d i, b hem ed,KS_-Eslocke4ed int lpuiesy4:,obje  (/ho+Eslocke4metapage) ntuiesy4/8:,obje  (page)d i, b hem ed,KS_+Eslocke4ed int lpuiesy4/8:,obje  (*/_PEtrg(16EAN Pmfs(s16)eem [24];dm4- 48:,overlay r(daoKS_itru163def+163def CO-333,7 lvf
@@h /home	T1+afLONG	28uct. locke4lomehem t{m- u 6I94.2b 14--2:-94.2phomehem to/-+EHids)y94.2b 14--2:-94.2phomehem to/-mfs(s8imaxcnt; 14--1:,KS_PEs8)bh = sfiesy1:,KS_(sb-179_blo179def CO-333,7 lomehem t{m|h /home/dt_hem 	lomehem uct. locke4xthem t{m- u 6I94.2b 14--2:-o/-+EHids)y94.2b 14--2:-o/-mfs(s8imaxcnt; 14--1:,KS_PEs8)bh = sfiesy1:,KS_(sb-211+ON+211+ON CO-333,7 xthem t{m f* d/ho(0xohem t(i.e.,y91,7 @@of 0xohem )piinux-2them ; 
-			u -333,7 0xohem t{m- u 6I94.2b 14--2:-o/-+EHids)y94.2b 14--2:-o/-mfs(u8imaxcnt; 14--2:-o/-m(u8ibh = sfiesy2:,94.2pd/ho(0xohem t)  = nKS_(sb-23(!AFF23(!AF-
-	/* Ok,mxohem t{m@h /home	
xd_hem 	mxohem uct. locke4xd ULOhem t{m- u 6I94.2b 14--2:-o/-+EHids)y94.2b 14--2:-o/-mfs(u8imaxcnt; 14--2:-o/-m(u8ibh = sfiesy2:,KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26types| }
 
 void
diff -NaAFFjmAej.26types| aA3*r(PSIS_HW_4/fs/afjmAej.26types| ved;
 11-2ra23:53b1
+				page = NULL;
 		}
-		bh_array[i] = bjmAej.26types| ved; 4t_O_m2_TV,7:22 0SiS_S4		g-M l /* Int,5tmap.c	2004-
-68,  Copyrightt(c) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf2
+68,  Copyrightt(C) IS_Sens
--- liBusinaur Mat_bifs	Corp., \n"0(2Pf4ct su 68,  T/dontrogram dond/ho(softwarure you7-30 16dULOkibuVB_itW_4//
 t2.4ifyu 68,  itWundIS_OH uct
miS_PrOH uGNU,8 +268,7PubleadLicense aontubles;
 }by-rl_432_96+32(s2c	200004-
 68,tfansa_SISF s4/fhem t)d's
+68
+68,Don'tBchange t es0  invoutBcarufu2_yg004sidIS000 +0o(impa_SpSF,t
  +f* size s4/falignmal  if( lln_PrOH uHomehem tvarial s
-			u type /h u bm-tids);u type /h u bm-lids);u+type /h u 6Itids);u+type /h u 6Ilids);u0004-
 68,AlmoLO0idIntUWsl fnAL
-		  *btchspec,)d tA_typquite-rl_4/f82.1
= s12.opts=type /h  locke4{m@h /home	todaessPXD(
xds\@@ ( ((s64)((
xds->todacBo:<< 32 | __lta : "no op(
xds->toda2)) r>+h /home/MAXTREEHEIGHT 8-2/fd
xd0 ULO0*/m  locke4
xd ULO0{fs(s16)maxn
xd;fs(s16)n
xd;f-	
xd_e4
xd[8];.2	
xd_e4
xd[MAXTREEHEIGHT]_bh
;+		 _nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAej.26xtf (
		res = -EIO;
 			gotojmAej.26xtf (
	aA3*r(PSIS_HW_4/fs/afjmAej.26xtf (
	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAej.26xtf (
	.\n",
 ck %r  *b1:54 0SiS_S4		g-M l /* Int071k(REt071k.4.e(+xtSglitUp(tids))tidtbh);f*/m /etru46e/piinux-2parubm-page <sp>f*/m /eXT_GETfsin(lp, parubmfs_u, scp, t;
-e, sgt rAm S-9+},
-Scop16:2pagP ) {
ut2 S+p1-2.4Sco:i     XT_PUTfsin(rcmpfoc+edd, dirtyrAb,,opts=t
  tr 		if* The>SIS keyf+			ifgofs	ONE AFTER. l	afo = n_Prparubm-+			ihIP_TYP106k(REt/f82.4.e(+xtSglitUp(tids))tidtbh);iSW fs(-g->occHer.dlag0& BT_a;
@) ?
s cIor;
xtSglitR  
(tidt lp, sglits &rmpf :
s cIor;
xtSglitPage(tidt lp, sglits &rmps &rbnfoc-, 1-2.4Scop16:22pagP ) {
ut1;_+, 1-2.4Sco:i      XT_PUTfsin(smpsNa+r;in, dirtyrAb,,oppts=t
   XT_PUTfsin(smpsNaPE  |
+keep>SIS child page <rp>fpiined,KS_P_TYP1Src4}
= s74_6.e(+xtSglitUp(tids))tidtbh)XT_PUTfsin(rmpfoc4  0 MS_RDONLY---/4-
-	f* Ih  ns nviig) letspiinux-2ablge,loop weBwer us2e SIy walk000 back
-	f* upt32 vtf (ys4/f32 vtf (ydon_b 4itco4sismout

-	f* re r +   llnic intwe'(dtholaisi.d-pe*/m-      ) {
ut1:
-	XT_PUTfsin(smpsNa-m-      ) {
ut2:
-	XT_PUTfsin(rcmpfoc- - , dirt rAb,@
+ p_p(att35ap(blo 4N5c AF-
-	64 xtTrunWs
e(tids))tidt T333,7 id int _PEf* a page t 0Siwasump_merly 	sb l	aright, ler  *mak vbfre t 0Si;
  		 sy94.26sisfb_indonzero
d loKS_-	
->occHer.:_	e01-0 S+:-2.4
->occHer.:_	emodeA||= MSHogm,,opp4-
+	i	 syMak vbfre t donchange tsb l	aoccHerndonlogg A.
+	i	 syIh wenres2_ygtrunWs
e0t doneW	f,rOH udlag
+	i	 sywillibapchanged7	sb lckTRUNCATE
+	i	 s/mA||dtlPsps>txL
 		tidt lp, /s FtlPsXTREE|tlPsGROWsNa+r;BT_MARK_DIRTY(mpt lp	/*+ 1p->occHer.:_	e01-0 S+:ts=t
 d/hod tms_bmfnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAenamei
		res = -EIO;
 			gotojmAenamei
	aA3*r(PSIS_HW_4/fs/afjmAenamei
	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAenamei
	.\n",
 			     loc04 0SiS_S4		g-M l /* Int30fer = 0,66eR sinux-2_arrj.26crest(!Aprintked int dlp,@@  +} sert6/fk(S_hash(ipsNaPE0x%x6/fk(S_dUrty4ip);m- d_i_sinntUst(!d+			ih lp	/*@  +dipPER_cbtche= dipPER_mbtche= CURRENT_TIME;p_p(att145_blo144 unread, read_arrj.26crest(!Aprintked int dlp,@@1-2.4Sco:i 	i	/o    olomk tms_bmi	/out4ip);m- }c+egIS_HW*+ 1d_i_sinntUst(!d+			ih lp	/*@  						u  2:t
 d/ho_UCSname(&dnamefoc(att25p(blo254,66eR sinux-2_arrj.26mkdUr!Aprintked int dlp, @@  +} sert6/fk(S_hash(ipsNaPE0x%x6/fk(S_dUrty4ip);m- d_i_sinntUst(!d+			ih lp	/*@  +truupu]egiparubm-dUrect
 yLed int /  +dipPER_olomk++sfiesymp_ '..')fverSchild dUrect
 yLKS_(sb-271+ON+269 unread, read_arrj.26mkdUr!Aprintked int dlp, @@1-2.4Sco:i 	i	/o    olomk tms_bmi	/out4ip);m- }c+egIS_HW*+ 1d_i_sinntUst(!d+			ih lp	/*@  						u  2:t
 d/ho_UCSname(&dnamefoc(att784,26 +784,34.e(+d, read_arrj.26Homk|T333,7 d+			if*ola_/lisdg fnAoup_bh@@1-2.4(
c = dtSW	rc0!dUrs &dname, &i 	ha&bt0tam ROJFS_CREATE)mmeno,pagP oup_b+);g fnA /homdname;m _PEtr 		)
 crest(f+			ifmp_ SIS lomk iinparubm-dUrect
 yd loKS_PEi 	yrp/o    i 	;@@1-2.4(
c = dtInsert(tidt dUrs &dname, &i 	ha&bt0tam )mmeno,pagP oup_b+);g fnA /homdname;m _PEtruupu]egiobje  (ed int /  +ipPER_olomk++sfiesymp_ SIS lomk  /  +ipPER_cbtche= CURRENT_TIME;p_E0x%x6/fk(S_dUrty4dUrsNaPEatomicninc(&ipPER_cs/in);m- d_i_sinntUst(!d+			ih lp	/*@  +ip ULO[0]yrp/o;  +ip ULO[1]e= dia2.4.SW fstxCsmm04(tidt 2, &ip ULO[0],O0V;p_pA|= MS_rc)    d_i_sinntUst(!d+			ih lp	/*+innnnn /homdname:c+d /homUCSname(&dnamefoc+-							u     +txEnd(tidck _p(att845_blo849ext_buffer;
 _arrj.26symHomk|T333,7 ed int dlp-m(unrite *i_fastsymHomk;fs(s64 xleun=ps_bmi_arrbreadn=pss x areb,-Es64 xtoda;p+Es64 e moutn=pss xtoda;p_ -333,7 metapage) ntu_PEs333,7 (KERN_ERR "AFFbu_PEs333,7 tbhem totblkoc(att879,2un+8832.4.e(+d, read_arrj.26symHomk|T333,7 ed int dlp-m(%b n(&JFS_IP dio)uccsmm04.semm S
/%b n(&JFS_IP 	p)uccsmm04.semm S
--1-2.4(
c = dtSW	rc0!dUps &dname, &i 	ha&bt0tam ROJFS_CREATE)mmeno,pagP oup3oc-   tblk fstids)o_tbhem (tidck   tblkucx.c l MivCOMMIT_CREATEk   tblkucipyrp/o;  --/4-
-	f* crest(f+			ifmp_ symboleadlomk iinparubm-dUrect
 yd-pe*/m---1- 	yrp/o    i 	;@-@-@-@-1-2.4(
c = dtInsert(tidt dUps &dname, &i 	ha&bt0tam )mmode-, jPEo) {("j.26symHomk: dtInsert,r dirtod %d",)rAm S-9+trudULcaca SI(ed int / no,pagP oup3oc- -sgc-mPEtruarc symHomk access pt
mossISFd loK 4dUr6crest(!) ANDspiinux-2u.u_cread, lis *td tAsymHomkonres2_ygamA|tto(bap777 access)1_bre90(!AFF894ext_buffer;
 _arrj.26symHomk|T333,7 ed int dlp-m(ipPER_c4/f Miv0777;m _PEtr -Ior;8,      	     symboleadlomk targem-path namW*+  syw     symboleadlomk targem-path namW* loKS_PExtInitR  
(tidt lpck _p(att952,64+	938,64.e(+d, read_arrj.26symHomk|T333,7 ed int dlp-m(rx are da(s are +rbread)0& ~bread bi  xtoda01-09- 	)xleun=pxinit*>> Jy %d I	sbffsl2b	 uns>-/e(++  rc = xtInsert(tidt lp, 0RO0ROxlens &xtodak,0Vm:r= 0s0{_-, 1-o     are das are -t10 16:2whilea(s aremode-, 1I_arrcopy  are damin		 are, t;
-e-2.---/e/e.2ps>nes metapage(lp, xtodak,t;
-e, 1-2.---/e/e-2.4mp:r= dpst/:i -eop cdtDe r
e(tidt dUps &dname, &i 	h
-eop cIoJy %REMOVn)0 16:29+SW fs, dO4.16:29+pagP oup3oc-		( ge-)	ddW
+			0/sfld |=s name, copy  are)0 16:29flush(metapage(mpfoc-#-2.0e-)	ddWx%x6d i, b_uptou]eg(bp, 1-2.-)	ddWx%x6d i, b_dUrty4bp, 1-2.-)	dd-2.4I %dYNC dio)/:i -eop cll_rw_ERR "(WRITEt 1, &bpfoc-, 1I	5:04_on6d i, b(bpfoc-, 1Ige-)	ddbrS_HW(bpfoc-#endifs/ilesy0f*/m-  		s are -= copy  areoc-, 1Ixtoda0+= Jy %d I	sbffsnbperagb*_b-eoptf-, 1-o    rivate rpLBLK2PBLKROMLaxlen);m-  }IS_HW_4/kedcdtDe r
e(tidt dUps &dname, &i 	hoJy %REMOVn)0 +/e(++  rc = xtInsert(tidt lp, 0RO0ROxlens &xtodak,0VmmodeA||stxAborr(tidt 0foc edd,W fs, NOSPC0 er;ipagP oup3 S pageaB-e moutn=pxtoda;p+E1-o     are das are -t10 +:2whilea(s aremode,opp4- T/dondonkind _Prsi2_ygdstc  PATH_MAX0r= 4K s/mA||d_arrcopy  are damin		 are, t;
-e-2.+mA||d.2ps>nes metapage(lp, xtodak,t;
-e, 1-2.+_+, 1-2.4mp:r= dpst/:i +r;indbFf (!lp, e moutLaxlen);m+:29+SW fs, dO4.+:29+txAborr(tidt 0foc+edddg fnAoup3 S2777S.2	ddW
+			0/sfld |=s name, copy  are)0 +:29flush(metapage(mpfoc+ 		s are -= copy  areoc+ 		name
+= copy  areoc+ 		xtoda0+= Jy %d I	sbffsnbperagb*_b+77S.2	d-o    rivate rpLBLK2PBLKROMLaxlen);m27S.2-+E4-
+	f* crest(f+			ifmp_ symboleadlomk iinparubm-dUrect
 yd+	 s/mA|
c = dtSW	rc0!dUps &dname, &i 	ha&bt0tam ROJFS_CREATE) SA|= MSrc:r= 0s0{_2	d- 	yrp/o    i 	;@+r;
c = dtInsert(tidt dUps &dname, &i 	ha&bt0tam ) S+p}mA|= MSSco:i    = MSxlen)1+;indbFf (!lp, e moutLaxlen);m+:2txAborr(tidt 0foc+edtrudULcaca SIw(ed int / +;ipagP oup3 S p}@@  +} sert6/fk(S_hash(ipsNaPE0x%x6/fk(S_dUrty4ip);m- d_i_sinntUst(!d+			ih lp	/*@  +tr 		)
 c*/mitfupu]egiofiparubm-dUrect
 yLs4/fhomk obje  d-pe*
-	f* = Me moutns2_HWs
---  letel ( NOSPC),
-	f* ux-2parubm-ed intdonc*/mit
 < regacaless fnAatic 
-	f* backstatiutiparubm-dUrect
 yLupu]egi(by dtInsert(mmenof* a4/fsubsequubm-dtDe r
e() 
hichEis igrmless wrt,
-	f* =nteg   yg004cern.  
-	f* ux-2symHomk ed intwillibapd/hod -yt/out4)taO0- 04enof* as itWhas anzerofhomk cs/in0(by dtDe r
e()) a4/fenof*  	ypt
mana(isresources. d loKS_P  +ip ULO[0]yrpdip; -	= MSrc:r= 0s0{_-/e(p ULO[1]e= ip; -	.SW fstxCsmm04(tidt 2, &ip ULO[0],O0V;p-sgIS_HW -	.SW fstxCsmm04(tidt 1, &ip ULO[0],O0V;p+e(p ULO[1]e= ip; +.SW fstxCsmm04(tidt 2, &ip ULO[0],O0V;p_p							u  3   +txEnd(tidck * Int01(!AFF1000 unread, read_arrj.26symHomk|T333,7 ed int dlp-m(i2.4Sco:i 	i	/o    olomk tms_bmi	/out4ip);m- }c+egIS_HW*+ 1d_i_sinntUst(!d+			ih lp	/*@  						u  2:t
 d/ho_UCSname(&dnamefoc(att120(!AFF1191ext_buffer;
 _arrj.26rubame(T333,7 ed int ola_aPE  |
+Lomehem toccHernofiutf (e*/_PE  tlPsps>txL
 		tidt ola_lp,@@ dcIor;
(d,* Ok,metapage) )0&JFS_IP ola_lpffsbx.c l,p16:2	      tlPsDTREE | tlPsBTa;
@foc+eddd      tlPsDTREE | tlPsBTa;
@ | tlPsRELINKfoc edddtlb;
* s+333,7 dt_hem to)0& tlPs->H_Pstr eddASSERT(dtlPsucih = n=AL0foc eddlv01-& dtlPsuclv[0]oc(att13482er = 31,66eR sinux-2_arrj.26mkd i|T333,7 ed int dlr, @@  +} sert6/fk(S_hash(ipsNaPE0x%x6/fk(S_dUrty4ip);m- d_i_sinntUst(!d+			ih lp	/*@  +dUrPER_cbtche= dirPER_mbtche= CURRENT_TIME;p_p(att1365_blo1347 unread, read_arrj.26mkd i|T333,7 ed int dlr, @@(i2.4Sco:i 	i	/o    olomk tms_bmi	/out4ip);m- }c+egIS_HW*+ 1d_i_sinntUst(!d+			ih lp	/*@  						u  1:t
 d/ho_UCSname(&dnamefocnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAe(KERN
		res = -EIO;
 			gotojmAe(KERN
	aA3*r(PSIS_HW_4/fs/afjmAe(KERN
	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAe(KERN
	.\n",
 ck %r  *b2OR800
@@ -111,8 +111_bre485UF]l485ext_buffer;
 
-			in04_once(ead( *fo	hakW
+_cabmi	INIT_LIST_HEAD0&j.26/o  anon6/fk(S_ ULO/*  11-n04_rwsem0&j.26/o  rdwrhem /*  11-n04_MUTEX0&j.26/o  csmm04.semm S+B- pinog83_Pin04(&j.26/o  agog83_-2.4.ej.26/o  acb_ge_agBi -1 S p}@@
+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAejmAexattN
		res = -EIO;
 			gotojmAexattN
	aA3*r(PSIS_HW_4/fs/afjmAexattN
	.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bjmAexattN
	.\n",
 _O_m2_TV,5:2ror? */
+			>-P, uns5f551+ON+551+unread, read_arrea_nesSAprintked int ld in, s  0
 	iea_d i->.c l 1-EA_EXTENT2.fsea_d i->.2ps>eROMLmetapage(ld in, todaessDXD(&ji  ea),p16:2	   leugiSDXD(&ji  ea), 1m SA|:2	   leugiSDXD(&ji  ea):<< hb->s rivatenit.bits,SA|:2	   1m S
(i2.4ea_d i->.2psoidpst/b dd, dirty, dO4.fsea_d i->xattNps>ea_d i->.2fld |= S(att81ffaff821+unrea_arrj.26setxattN|T333,7 d+			if*d+			ih S unread--;folome/_arrcan_nes xattN|T333,7 ed int ld in, co4stBchar *namef
:i   if|T33ncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LENm:r= 0s.+p1, dirtms_bmi, dirtmpt
mossISF(ld in, MAY%READfoc;
+		nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAenamei
		res = -EIO;
 			gotonamei
	aA3*r(PSIS_HW_4/fs/afnamei
	.\n"3-08-25 11:44c(b_ins_M;
* s+affs_
 		}
-		bh_array[i] = bnamei
	.\n",
 			     l7:22 0SiS_S4		g-M l /* In583	}
=583_96eR er_u_ */
onal :
s cIi2.4err < 0s. )	ddbrSakffs( ge-)	d+			if= cat_ed_heokup(ndfld+			ih &t dot 0foc+edd+			if= cat_ed_heokup(ndfld+			ih &t dot ndfl.c ls/*  11-2.4!d+			i/:i -eopd+			if= res2_heokup(ndfld+			ih &t dot 0foc+edpd+			if= res2_heokup(ndfld+			ih &t dot ndfl.c ls/*  11	err = PTR_ERR!d+			i/*  11	-2.4I %ERR!d+			i/s. )	ddbrSakffnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAenmAedlr
		res = -EIO;
 			gotonmAedlr
	aA3*r(PSIS_HW_4/fs/afnmAedlr
	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bnmAedlr
	.\n",
 inor = MI8:34 0SiS_S4		g-M l /* In999_blo999ext_buffer;
 _arrn.26rubame(T333,7 ed int ola_aPET333,7 ed int ola_ed int= ola_d+			ifld_ed in;aPET333,7 ed int SIw_ed int= SIw_d+			ifld_ed in;aPET333,7 d+			if*d+			i)= ct a, *rehash)= ct aff-d_arr) {
  fs, BUSY;p+e(arr) {
 /*@  +tr 		)
 To i/mvoutnsny SIw(referubcere	sb32 vtargem-duS000 +0o(rubamehIP_TYP025UF]lP025U.opts= l read_arrn.26rubame(T333,7 ed int ola_aPE  /  +i_BU!new_ed in)lisdg fnAgo_aoccH,-+E4-yIh targem-is anhaca lomk tsb32 vsource,rOH n  	opt / +;) {
  fs0 S+:-2.4NFS_FILEID(new_ed in)psoidFS_FILEID(ola_ed inmme+, pagP oup_b+ +;) {
  fs, BUSY;p 1-2.4S_ISDIR(new_ed inPER_c4/fm)lisdg fnAoup_bh)cked, 2.4atomicne SIS&SIw_d+			ifld_cs/in)o>t(m {_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAenmAeuolomk
		res = -EIO;
 			gotonmAeuolomk
	aA3*r(PSIS_HW_4/fs/afnmAeuolomk
	ved;
 11-2ra23:53b1
+				page = NULL;
 		}
-		bh_array[i] = bnmAeuolomk
	ved;,
 ck %r  *b1:36_ins_M;
* s+affs_itru12ck *sEext_b
 #incluint<}
-		e(Knrpc/st_ed.h>
 #incluint<}
-		e(Knrpc/clnt.h>
 #incluint<}
-		en.26fs.h>
+#incluint<}
-		e5:04.h>
 uct. locke4n.26uolomkd |=0{_(sb-21faff22_96eR siocke4n.26uolomkd |=0{_PET333,7 rpc_task	tead bi T333,7 rpc_cred	*cred;-m(unsigtod _ar	cs/in_b+ +;5:04_queueloccH_t 5:04q;p+e(arr */
 r
ed_bh
;+		  l readsiocke4n.26uolomkd |=	*n.26de r
esoc(att133+aff1u7 unrean.26async(uolomk_done(T333,7 rpc_task *O-lsout_rpccred(d |=  credm S
/% |=  cred)= ct aff
/%out4dUrsNa+/% |=  c*/
 r
ed =t10 +:wake_up(&% |=  5:04qfoc;
+		 /**u(sb-175_k *s81 unrean.26async(uolomk|T333,7 d+			if*d+			i)lisn.26de r
ese= d |= S0/% |=  c*/in0tm1;p_pA|=n04_5:04queueloccH(&% |=  5:04qfoc2-	steadn=p&% |=  tead bi rpc_=n04_tead(tead, clnt,an.26async(uolomk_done , RPC_TASK_AdYNCck   tead  tk_LV_.d |=01-d |= S(att2sEextf2202.4.e(+n.26c*/
 r
e(uolomk|T333,7 d+			if*d+			S0/% |=  c*/in++9-PEn.26c*pymdname!d+			ih % |=m S
/%+			ifld_.c ls &= ~DCACHE_dFSy %RENAMED; -	= MS% |=  tead.tk_rpc5:04tr=p&n.26de r
e_queue)S+:-2.4% |=  tead.tk_rpc5:04tr=p&n.26de r
e_queue):i    T333,7 rpc_cl &e*cl &e1-d |=  tead.tk_clial *  11rpc_wake_up_tead(&% |=  tead)u_+i	9PEowa04_mvout(clnt,a% |=  5:04q,a% |=  c*/
 r
ed == 1m SA|}-PEn.26out_uolomkd |=(% |=m S

+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAeproc/bas(
		res = -EIO;
 			gotoproc/bas(
	aA3*r(PSIS_HW_4/fs/afproc/bas(
	it_b3-11-2ra 8 +S0
 	}
 	me_S3 +S0
 	-.rage = pages[iaA3*r(PSproc/bas(
	it_b,
 inor = MINO26_ins_M;
* s+affs_itru8832un+8832unread, readT333,7 d+			if*proc_heokupfi|T333bmi, dirtmct aff

Aoupoou12B,2:
-	out_B->ss_T333,7(B->ss)_bmi, cH_ou12B,(&B->ss  B->sog83_-2.+eout_B->ss_T333,7(B->ss)_bmoupoou12B,   +}out4id inm_bmoup:+nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAereiser= bjournal
		res = -EIO;
 			gotoreiser= bjournal
	aA3*r(PSIS_HW_4/fs/afreiser= bjournal
	.\n"3-08-25 11:44c(b_ins_M;
* s+affs_
 		}
-		bh_array[i] = breiser= bjournal
	.\n",
 inor = MINO2ror? */
+			>-P, uns5f19ock *s9oc96eR sinux-2_arrs
 	+he_inogist
+hem +SAprint.fd, read
-			_HW	nup_+hem +ogistR_unsign(KERN_ERR "AFp_s_sb elllllllllllllllllllllllllllllllllT333,7 reiser= ogist
+hem + *jbo:i 	(bd(isi/*+in(++ jb->+hem +s
*oidpst/b+e, dirtmoc+-			mp_ -i fs0 ; i < SB_BMAP_NR(p_s_sb) ; i++o:i 	(bin(++ jb->+hem +s[i]o:i 	(binnn /hom+hem +od in(p_s_sb, jb->+hem +s[i]o: S(att2064 un+20672.1
rea_arrjournalPin04(_unsign(KERN_ERR "AFp_s 	(binINIT_LIST_HEAD0&SB_JOURNAL(p_s_sb)->jm+hem +od inso: S	(binINIT_LIST_HEAD 0&SB_JOURNAL(p_s_sb)->jmpres2_oc_hULO/*  m-    reiser= os2_HWs
 ogist
+hem +s(p_s_sb, SB_JOURNAL(p_s_sb)->jmgist
+hem +, p16:2	   SB_BMAP_NR(p_s_sb)o: S+(bin(++ reiser= os2_HWs
 ogist
+hem +s(p_s_sb,c+eddd       SB_JOURNAL(p_s_sb)->jmgist
+hem +, p+eddd       SB_BMAP_NR(p_s_sb)o/b+eg fnA /homand_, dirtmoc+-			 us2_HWs
 m+hem +od ins(p_s_sb) ;*@  				/*Ares0rv < Borrjournal r(dao(KEporr4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAed, r
		res = -EIO;
 			gotod, r
	aA3*r(PSIS_HW_4/fs/afd, r
	.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bd, r
	.\n",
 			     loc14 0SiS_S4		g-M l /* In52UF]l52+unread, read_arrcp_ola_d, r(T333,7 ed int  ed   tmp.st6/fkt= i_OH PER_i 	;@@1tmp.st6m int= ed inPER_c4/f;@@1tmp.st6olomk tmed inPER_nHomk;f+:-2.4tmp.st6olomk !tmed inPER_nHomk/b+ed, dirty, OVERFLOW;@@1SET_OLDSTAT_UID(tmpt ld inPER_uidck   SET_OLDSTAT_GID(tmpt ld inPER_gidck   tmp.st6rdev01-kdev_ts)o_n 	i_OH PER_rdevfoc(att78faff81+unread, read_arrcp_SIw_d, r(T333,7 ed int  ed   tmp.st6/fkt= i_OH PER_i 	;@@1tmp.st6m int= ed inPER_c4/f;@@1tmp.st6olomk tmed inPER_nHomk;f+:-2.4tmp.st6olomk !tmed inPER_nHomk/b+ed, dirty, OVERFLOW;@@1SET_STAT_UID(tmpt ld inPER_uidck   SET_STAT_GID(tmpt ld inPER_gidck   tmp.st6rdev01-kdev_ts)o_n 	i_OH PER_rdevfocnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAeMak B->s	}
-		bh_array[i] = bxmAeMak B->saA3*r(PSIS_HW_4/fs/afxmAeMak B->s.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAeMak B->s.\n",
 			     loc36_ins_M;
* s+affs_itru1,5tmap.c	200#
-# Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
+# Copyrightt(c) \n"0(2Pf4 Silicon Graphics, Inc.  All Rights Res0rv <.
0#
 # T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
 # undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop(att30Y;
+	302.4.e(
 # http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
0#
 
-EXTRA_CFLAGS0+=  -I. -I	}
-		 -funsigtod-char
+EXTRA_CFLAGS0+=  -I. -I	}
-		bh_a -funsigtod-char
@  ifeq ($(CONFIG_Xy %DEBUG),ymenoEXTRA_CFLAGS0+= -g -DSTATIC="" -DDEBUG -DXy DEBUGb+eEXTRA_CFLAGS0+= -g -DSTATIC="" -DDEBUG   EXTRA_CFLAGS0+= -DfsinBUF 1+af_TRACKING  endif  ifeq ($(CONFIG_Xy %TRACE),ymeP_TYP132.4.+P132.4.P_Tobj-yeddd+= x= os2_HW.o \@@ dcIor;x= oqmops.ogs |h Obje  sA_typbuiltpiinuxdondUrect
 yd-obj-yeddd+= }
-		e}
-		_x= .o \@+obj-yeddd+= }
-		bh_ae}
-		_x= .o \@@ dcIor;(KEporr/(KEporr_x= .o
 
-subdirP$(CONFIG_Xy %FS)dd+= }
-		;(KEporr
+subdirP$(CONFIG_Xy %FS)dd+= }
-		bh_a (KEporr
@  ifeq ($(CONFIG_Xy %DMAPI),ymeor;(KbdirP$(CONFIG_Xy %FS)d+= dm +icnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		eMak B->s	}
-		bh_array[i] = bxmAe}
-		eMak B->saA3*r(PSIS_HW_4/fs/afxmAe}
-		eMak B->s.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		eMak B->s.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,6aff0,4.e(
-#
-# Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
-#
-# T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-# undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-# tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-#
-# T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-# WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
-# MERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-#
-# FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-# d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-# orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-# oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-#  ny, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-# oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-#
-# You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
-#  inv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-# Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
-#
-# Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
-# M*/inaom(View, CA  94043, or:
-#
-# http://www.sgi.c*/
-#
-# ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
-#
-# http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-#
-# Mak B->s	BorrXy pSF,L
-		..---EXTRA_CFLAGS0+= -I.. -I. -funsigtod-char
---ifeq ($(CONFIG_Xy %DEBUG),ymenoEXTRA_CFLAGS0+= -g -DSTATIC="" -DDEBUG -DXy DEBUGbnoEXTRA_CFLAGS0+= -DfsinBUF 1+af_TRACKING -endif -ifeq ($(CONFIG_Xy %TRACE),ymenoEXTRA_CFLAGS0+= -DXy %RW%TRACE -DfsinBUF TRACEeno# EXTRA_CFLAGS0+= -DXy %VNODE TRACEenendif -
-O_TARGETdcI:= }
-		_x= .o
-ifneq ($(MAKECMDGOALS),2.4u>ss_i_sinll)
-6Tobj-m	dcI:= $(O_TARGET)enendif -
-obj-$(CONFIG_PROC%FS)dd+= x= od, r .o
-obj-$(CONFIG_SYSCTL)dd+= x= odysctl.o
-obj-yeddd+= x= osops.o \@- dcIor;x= oB->s.o \@- dcIor;x= oB odubr.o \@- dcIor;x= oglobals.o \@- dcIor;x= oioctl.o \@- dcIor;x= oiops.o \@- dcIor;x= olrw.o \@- dcIor;x= o(KERN
o \@- dcIor;x= ovfs.o \@- dcIor;x= ov_OH .o	\@- dcIor;x= obuf.o \@- dcIor;mrhem .o \@- dcIor;kW
+.o
-
-incluint$(TOPDIR)/Ru>ss.mak cnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		ekW
+.		res = -EIO;
 			gotoxmAe}
-		ekW
+.	aA3*r(PSIS_HW_4/fs/afxmAe}
-		ekW
+.	.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		ekW
+.	.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,244ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf2 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/m---#incluint<}
-		e(t_ed.h>
-#incluint<}
-		emm.h>
-#incluint<}
-		evms2_HW.h>
-#incluint<}
-		eslab.h>
-
-#incluint"btch.h"
-#incluint"kW
+.h"
-
-# /home/DEF_PRIORITY	(6)
-# /home/MAX_SLAB_;
-e	0x1affs_-# /home/MAX_SHAKE	8
-
-d, readkW
+_shake_funW_t	shake_ ULO[MAX_SHAKE]2. read--;DECLARE_MUTEX0shake_semm S-
-kW
+_shaker_t
-kW
+_shake_regismor(kW
+_shake_funW_t sfunW-
-{I-E_ar	i2.---/%b n(&shake_semm S-	mp_ -i fs0; i < MAX_SHAKE; i++o:i -/e(++ shake_ ULO[i]:r= dpst/:i -eopshake_ ULO[i]:r sfunW_b-eopbrSakff-  }c- }c- (++ i:r= MAX_SHAKEmeno,BUG(-2.-sup(&shake_semm S-
-d, dirty(kW
+_shaker_t)sfunW_b-gc-m-tic 
-kW
+_shake_dISegismor(kW
+_shaker_t sfunW-
-{I-E_ar	i2.---/%b n(&shake_semm S-	mp_ -i fs0; i < MAX_SHAKE; i++o:i -/e(++ shake_ ULO[i]:r= (kW
+_shake_funW_t)sfunW-
-eopbrSakff- }c- (++ i:r= MAX_SHAKEmeno,BUG(-2.-smp_ -; i < MAX_SHAKE -t10 i++o:i -/eshake_ ULO[i]:r shake_ ULO[i+1]ff- }c- shake_ ULO[i]:r ct aff-dup(&shake_semm S-}
-
-d, read_o/flome__d
-			kW
+_shake(ead(st-{I-E_ar	i2.---/%b n(&shake_semm S-	mp_ -i fs0; i < MAX_SHAKE && shake_ ULO[i]0 i++o -/e(*shake_ ULO[i])(0,O0V;p-sup(&shake_semm S-	delay(10)_b-gc-m-tic  -
-kW
+_s2_HW(enit.t  are, _arr.c ls/t-{I-E_ar	shromk  fsDEF_PRIORITYuiesy#*btchs 	sb ryRfnAshromk cat_ee*/m-      (bd(isssssl.c ls 01-kW
+_.c ls_convert(.c ls/* -      (bd(isssssnosleep>= .c ls & KM_NOSLEEP S-	tic 	*rval2.---rep at:c- (++ MAX_SLAB_;
-e <  aremode-, esyA
-			doiig) ->ssystem sensib_ge stu1+a+er46efb/do,*/m-  rval>= __vms2_HW( are, l.c ls, fsin_KERNELV;p-sgIS_HWode-, rval>= kms2_HW( are, l.c ls)2.-sgc-m- (++ rval>||snosleepo -/e, dirt rval2.---/4-
-	f* KM_SLEEPELV_.crsndon'O0- pe  (a  letured-pe*/m-e(++ shromkmode-, kW
+_shake(-2.---/eshromk-30 16:g fnArep at2.-sgc-m- rval>= __vms2_HW( are, l.c ls, fsin_KERNELV;p-s= MS_rval>&& !nosleepo -/epanic("kW
+_s2_HW: ct a mem
 yLSF KM_SLEEPErequust!"foc- - , dirt rval2.-gc-m-tic  -
-kW
+_zs2_HW(enit.t  are, _arr.c ls/t-{I-Etic 	*ptroc- - pta01-kW
+_s2_HW(enit, .c ls)2.-p-s= MSptao -/eW
+set((char *)ptat 0,O(_ar) are)0 1
-d, dirty(ptao_b-gc-m-tic 
-kW
+_d/ho(ead( *ptat enit.t  are/t-{I-E_++  (unsigtod long)pta < VMAL1+a_START)>||
-Ior;
((unsigtod long)pta >= VMAL1+a_END)mode-, kd/ho(ptao_b-sgIS_HWode-, vd/ho(ptao_b-sg.-gc-m-tic  -
-kW
+_res2_oc(ead( *ptat enit.t newenit, enit.t old are, _arr.c ls/t-{I-Etic t SIw0 1
-dSIw(1-kW
+_s2_HW(newenit, .c ls)2.-s= MSptao:i -/e(++ new-
-eopW
+			0new, ptat@- dcI((old areB<m94w aremo? old are :m94w arem);m-  kW
+_d/ho(ptat old are)2.-sgc-m- , dirtySIw0 1}S-
-kW
+_zont.t *
-kW
+_zont.in04(_arrsnit, char *zont.namef
-{I-E, dirtykW
+_cat_e6crest(!zont.name,rsnit, 0RO0ROct a, dpst/2.-gc-m-tic  -
-kW
+_zont.s2_HW(kW
+_zont.t *zont, _arr.c ls/t-{I-E_ar	shromk fsDEF_PRIORITYuiesy#*btchs 	sb ryRfnAshromk cat_ee*/m-Etic 	*ptr:r ct aff---rep at:c- pta01-kW
+_cat_e6s2_HW(zont, kW
+_.c ls_convert(.c ls/)2.-p-s= MSpta>||s(.c ls & KM_NOSLEEP)o -/e, dirt ptroc- - 4-
-	f* KM_SLEEPELV_.crsndon'O0- pe  (a  letured-pe*/m-e(++ shromkmode-, kW
+_shake(-2.---/eshromk-30 16:g fnArep at2.-sgc-m- (++ .c ls & KM_SLEEP) -/epanic("kW
+_zont.s2_HW: ct a mem
 yLSF KM_SLEEPErequust!"foc- - , dirt ct aff-gc-m-tic  -
-kW
+_zont.zs2_HW(kW
+_zont.t *zont, _arr.c ls/t-{I-E_ar	shromk fsDEF_PRIORITYuiesy#*btchs 	sb ryRfnAshromk cat_ee*/m-Etic 	*ptr:r ct aff---rep at:c- pta01-kW
+_cat_e6s2_HW(zont, kW
+_.c ls_convert(.c ls/)2.-p-s= MSptamode-, W
+set(ptat 0,OkW
+_cat_e6snit(zontm);m-  , dirt ptroc-sgc-m- (++ .c ls & KM_NOSLEEP) -/e, dirt ptroc- - 4-
-	f* KM_SLEEPELV_.crsndon'O0- pe  (a  letured-pe*/m-e(++ shromkmode-, kW
+_shake(-2.---/eshromk-30 16:g fnArep at2.-sgc-m- (++ .c ls & KM_SLEEP) -/epanic("kW
+_zont.zs2_HW: ct a mem
 yLSF KM_SLEEPErequust!"foc- - , dirt ct aff-gc-m-tic 
-kW
+_zont.d/ho(kW
+_zont.t *zont, ead( *pta/t-{I-EkW
+_cat_e6d/ho(zont, ptao_b-gcnit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		ekW
+. }
 
 void
diff -NaAFFxmAe}
-		ekW
+. aA3*r(PSIS_HW_4/fs/afxmAe}
-		ekW
+.h.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		ekW
+.h.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,114ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_KMEM_H___-# /home/__Xy %SUPPORT_KMEM_H___-
-#incluint<}
-		eslab.h>
-
-4-
-68,mem
 yLmana0emal  {
utbifs
-e*/c-# /home/KM_SLEEP	0xn"01c-# /home/KM_NOSLEEP	0xn"02c-# /home/KM_NOFS		0xn"04
-
-# /home	kW
+_zontEkW
+_cat_e6sc-# /home/kW
+_zont.tEkW
+_cat_e6t
-
-type /h unsigtod long;x= op.c ls_2bf---# /home/PFLAGS_TEST_NOIO()llllllllllllll(currubmfs.c ls & PF_NOIO)--# /home/PFLAGS_TEST_FSTRANS()lllllllllll(currubmfs.c ls & PF_FSTRANS)f---# /home/PFLAGS_SET_NOIO(STATEP) doA{llll\@- *(STATEP) = currubmfs.c ls; llll\@-llllllllcurrubmfs.c ls |= PF_NOIO; lllll\@-} whilea(0)f---# /home/PFLAGS_SET_FSTRANS(STATEP) doA{l\@- *(STATEP) = currubmfs.c ls; llll\@-llllllllcurrubmfs.c ls |= PF_FSTRANS;lll\@-} whilea(0)f---# /home/PFLAGS_CLEAR_FSTRANS(STATEP) doA{l\@- *(STATEP) = currubmfs.c ls;	\@- currubmfs.c ls &= ~PF_FSTRANS;	\@-} whilea(0)f-----# /home/PFLAGS_RESTORE(STATEP) doA{llll \@- currubmfs.c ls = *(STATEP);lllll\@-} whilea(0)f---# /home/PFLAGS_DUP(OSTATEP, dSTATEP) doA{l\@- *(NSTATEP) = *(OSTATEP);	\@-} whilea(0);
-
-d, read_o/flome unsigtod _ar kW
+_.c ls_convert(_arr.c ls/t-{I-      (bd(isl.c ls* -      (bc-#-2.DEBUGbno(++ uolokely .c ls & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS)mmode-, pS00tk(KERN_WARNING -dd    "Xy :,mem
 yLs2_HWs
--- winv2wrong;.c ls (%x)\n", .c ls)2.-s,BUG(-2.-s}c-#endif -      (bc-      (bl.c ls =  .c ls & KM_NOSLEEP) ? GFP_ATOMIC : GFP_KERNEL; -      (bc-      (besyatic vrecus_ge LV_.backs 	sbB->ssystem %uS000 +fansa_SISFse*/m-e(++ PFLAGS_TEST_FSTRANS()l||s(.c ls & KM_NOFS)m.-s,l.c ls &= ~__GFP_FS; -      (bc-      (b, dirt l.c ls* -gc-m-- mSenFkW
+_zont.t  *kW
+_zont.in04(_ar, char *-2.-- mSenFtic 	  (b*kW
+_zont.zs2_HW(kW
+_zont.t *, _ar-2.-- mSenFtic 	  (b*kW
+_zont.s2_HW(kW
+_zont.t *, _ar-2.-- mSenFtic lllllllllkW
+_zont.d/ho(kW
+_zont.t *, ead( *);
-
-- mSenFtic 	  (b*kW
+_s2_HW(enit.t, _ar-2.-- mSenFtic 	  (b*kW
+_res2_oc(ead( *, enit.t, enit.t, _ar-2.-- mSenFtic 	  (b*kW
+_zs2_HW(enit.t, _ar-2.-- mSenFtic lllllllllkW
+_d/ho(ead( *, enit.t);
-
-type /h tic 	  (b*kW
+_shaker_t;
-type /h _ar	llll(*kW
+_shake_funW_t)(_ar, unsigtod _ar);
-
-- mSenFkW
+_shaker_t kW
+_shake_regismor(kW
+_shake_funW_t-2.-- mSenFtic 	  (bkW
+_shake_dISegismor(kW
+_shaker_t);
-d, read_o/flome _ar	kW
+_shake_s2_Hw(unsigtod _ar read)0{b, dirt 1; gc-m-#endifbesy__Xy %SUPPORT_KMEM_H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		emrhem .		res = -EIO;
 			gotoxmAe}
-		emrhem .	aA3*r(PSIS_HW_4/fs/afxmAe}
-		emrhem .	.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		emrhem .	.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,274ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/m---#incluint<}
-		ebtch.h>
-#incluint<}
-		est_ed.h>
-#incluint<asm/system.h>
-#incluint<}
-		esfb_irupt.h>
-#incluint<asm/currubm.h>
-
-#incluint"mrhem .h"
-
-c-#-2.USE%RW%WAIT_QUEUE_SPIN1+af
-#  /home/wq_w    _hem 	w    _hem m-#e_HW -#  /home/wq_w    _hem 	 pinog83_c-#endif -
-4-
-68,Wendon'O0seemRfnAamA|tg83_Ptypet(only one (KEporred)s name, orp-f* sequubcs. Buy,yXy pwillipass itWso ler  *legafROH m7H reymp_ Sow.
-e*/m-esyARGSUSEDe*/m-tic 
-mrhem .in04(mrhem .t *mrp, _arrg83_Ptype,Bchar *name, long;sequubcs/t-{I-Emrp->mr_c*/in0tmNLY-Emrp->mr_, cHEowa04iigdtmNLY-Emrp->mr_w    Eowa04iigdtmNLY-E=n04_5:04queueloccH(&mrp->mr_, cHerq)LY-E=n04_5:04queueloccH(&mrp->mr_w    rq)LY-Emrp->mr_RR "A= SPIN 1+af_UN1+afED; -} -
-4-
-68,Macros 	sbRR "/ou12B, OH umrhem .t.
-e*/m---# /home/MR1+af(m)B- pinog83_(&(m)->mr_RR "foc-# /home/MRUN1+af(m)B- pinoou12B,(&(m)->mr_RR "foc- -
-4-
-68,hem .5:04tdeGuldAnkveribapcV_.cdpiin30 sfb_irupt OH, cH.
- -
-68,mrhem s7-30 sleep>(i.e.pcV_. st_edule) a4/fssb32 y7-30'tBkverp-f* bapcV_.cdpfverS30 sfb_irupt OH, cH.
- -
-68,OH, cHs t 0Siwake-uptdeGuldAalsoAnkveribapinvokcdpfverSsfb_irupt OH, cHs.
- -
-68,Buy,y5:04queuelhem t)s,hem cdpfverSsfb_irupt OH, cHs -ta4/fwe r(d
-68,cV_.cdpwinv2sfb_iruptondULab.cd,fssbim-is a_. OK.
-e*/m---esyARGSUSEDe*/m-tic 
-hem .5:04(5:04_queueloccH_t *q, sginhem .t *hem , _arrrw/t-{I-EDECLARE_WAITQUEUE(y5:04, currubm foc- - _6set_currubmod, re(TASK_UNINTERRUPTIBLe-2.---/wq_w    _hem (&q->H_Ps)2.-s= MSrw/ode-, __add_5:04_queuelnaol(q, &5:04o_b-sgIS_HWode-, __add_5:04_queue(q, &5:04o_b-sg.---/wq_w    _ou12B,(&q->H_Ps)2.-s pinoou12B,(RR "foc- -	st_edule(-2.---/wq_w    _hem (&q->H_Ps)2.-s__, move_5:04_queue(q, &5:04o_b-swq_w    _ou12B,(&q->H_Ps)2.-.-s pino12B,(RR "foc- -	/*Aredirt winv2hem tocld,KS_-} -
-4-yARGSUSEDe*/m-tic 
-mrd/ho(mrhem .t *mrp/t-{I-} -
-4-yARGSUSEDe*/m-tic 
-mr12B,(mrhem .t *mrp, _arrtype,B_arr.c ls/t-{I-E_2.4typetr= MR_ACCESSo -/eWraccess(mrp/_b-sS_HW -	.mrupu]eg(mrp/_b-} -
-4-yARGSUSEDe*/m-tic 
-mraccessf(mrhem .t *mrp, _arr.c ls/t-{I-EMR1+af(mrp/_b-sif(mrp->mr_w    Eowa04iigd> 0s0{_-/emrp->mr_, cHEowa04iig++9--s,lem .5:04(&mrp->mr_, cHerq, &mrp->mr_RR ",O0V;p-semrp->mr_, cHEowa04iig-30 16}c- whilea(mrp->mr_c*/in0< 0s0{_-/emrp->mr_, cHEowa04iig++9--s,lem .5:04(&mrp->mr_, cHerq, &mrp->mr_RR ",O0V;p-semrp->mr_, cHEowa04iig-30 16}c- mrp->mr_c*/in++9--sMRUN1+af(mrp/_b-} -
-4-yARGSUSEDe*/m-tic 
-mrupu]egf(mrhem .t *mrp, _arr.c ls/t-{I-EMR1+af(mrp/_b-swhile(mrp->mr_c*/ins0{_-/emrp->mr_w    Eowa04iig++9--s,lem .5:04(&mrp->mr_w    rq, &mrp->mr_RR ",O1V;p-semrp->mr_w    Eowa04iig-30 16}c-I-Emrp->mr_c*/in0tm-1;besyw    rLSF ite*/m-eMRUN1+af(mrp/_b-} -
-il p-mrtryaccess(mrhem .t *mrp/t-{I-EMR1+af(mrp/_b-s4-
-	f* Ih  nyone is wa04iigdmp_ upu]egiaccess orrOH ulem t)s,ocld,mp_ upu]eg
-	f*  let +0o(ruquust.d-pe*/m-sif(mrp->mr_w    Eowa04iigd> 0l||smrp->mr_c*/in0< 0s0{_-/eMRUN1+af(mrp/_b-p1, dirtms_b16}c- mrp->mr_c*/in++9--sMRUN1+af(mrp/_b-	, dirt 1;b-} -
-il p-mrtrypromoto(mrhem .t *mrp/t-{I-EMR1+af(mrp/_b-m-sif(mrp->mr_c*/in0t=t(m {besyWe r(d +0o(only 	H, cHywinv2OH ulem t*/m-  mrp->mr_c*/in0tm-1;besyw    rLSF ite*/m-eeMRUN1+af(mrp/_b-p1, dirtm10 16}c-I-EMRUN1+af(mrp/_b-	, dirt 0;b-} -
-il p-mrtryupu]eg(mrhem .t *mrp/t-{I-EMR1+af(mrp/_b-m-sif(mrp->mr_c*/ins0{_-/eMRUN1+af(mrp/_b-p1, dirtms_b16}c-I-Emrp->mr_c*/in0tm-1;besyw    rLSF ite*/m-eMRUN1+af(mrp/_b-	, dirt 1;b-} -
-d, read_o/flome__d
-			mrwake(mrhem .t *mrp/t-{I-E4-
-	f* First, _PrOH uc*/in0don_b 402 we amA|tto(wake-upt nyone wa04iig.d-pe*/m-sif (!mrp->mr_c*/ins0{_-/e-2.4mrp->mr_w    Eowa04iigs0{	/*AWake-uptfirstyw    rLwa04iigd*/m-  	wake_up(&mrp->mr_w    rq)LY-EsgIS_HWo-2.4mrp->mr_, cHEowa04iigs0{	/*AWakeupt ny , cHersLwa04iigd*/m-  	wake_up(&mrp->mr_, cHerq)LY-E }c- }c-gc-m-tic 
-mraccou12B,(mrhem .t *mrp/t-{I-EMR1+af(mrp/_b-smrp->mr_c*/in-30 16mrwake(mrp/_b-sMRUN1+af(mrp/_b-} -
-tic 
-mruu12B,(mrhem .t *mrp/t-{I-EMR1+af(mrp/_b-s-2.4mrp->mr_c*/in0< 0s0{_-/emrp->mr_c*/in0tmNLY-EgIS_HWode-, mrp->mr_c*/in-30 16} 16mrwake(mrp/_b-sMRUN1+af(mrp/_b-} -
-il p-ismrhem ed(mrhem .t *mrp, _arrtype)	/*ANo amA|tto(lem tdstc  edmp7-30 changed*/m-{I-E_2.4typetr= MR_ACCESSo -/e, dirty(mrp->mr_c*/in0> 0s;besyR cHylem t*/m- S_HWo-2.4typetr= MR_UPDATE) -/e, dirty(mrp->mr_c*/in0< 0s;besyW     lem t*/m- S_HWo-2.4typetr= (MR_UPDATE | MR_ACCESSo) -/e, dirty(mrp->mr_c*/in)uiesyAnyStypetof2hem tocld,KS_- S_HWoesyAnySwa04ersL*/m-  r dirty(mrp->mr_, cHEowa04iigd|smrp->mr_w    Eowa04iigs; -} -
-4-
-68,DemotopfverSupu]egifnAaccess.yWe betteribap+0o(only 	H, cHywinv2OH 
-68,hem piinupu]egim intssbim-deGuldAbapeasyRfnAs6efbo 1.
-68,Wake-upt ny , cHersLwa04iig.
-e*/m---tic 
-mrdemoto(mrhem .t *mrp/t-{I-EMR1+af(mrp/_b-emrp->mr_c*/in0tm1_b-s-2.4mrp->mr_, cHEowa04iigs0{	/*AWakeupt _. , cHersLwa04iigd*/m-  wake_up(&mrp->mr_, cHerq)LY-E}b-sMRUN1+af(mrp/_b-} nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		emrhem . }
 
 void
diff -NaAFFxmAe}
-		emrhem . aA3*r(PSIS_HW_4/fs/afxmAe}
-		emrhem .h.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		emrhem .h.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,87ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_MR1+af_H___-# /home/__Xy %SUPPORT_MR1+af_H___---#incluint<}
-		ebtch.h>
-#incluint<}
-		e5:04.h>
-#incluint<asm/atomic.h>
-#incluint<asm/semaphore.h>
-
-4-
-68,I/
 rmal  mrhem s7SF,L
-		 t 0Siwork	BorrXy .
-68
-68,T/ese r(d sleep>hem s7a4/f_typsginhem s.yIh one wantonresd/w     sginhem s,
- syusu>eROMLRR ",Ow    _hem , ... see sginhem .h.
-e*/m---type /h d,* Ok,mrhem .sode-,_ar	, mr_cs/in_b-(unsigtod deGrt, mr_, cHEowa04iig_b-(unsigtod deGrt, mr_w    Eowa04iig_b-sw:04_queueloccH_t	mr_, cHerq_b-sw:04_queueloccH_t	mr_w    rq2.-s pinhem .t, mr_H_Pstr-}umrhem .t;m---# /home/MR_ACCESS	1--# /home/MR_UPDATE	2m---# /home/MR1+af_BARRIER		0x1--# /home/MR1+af_AL1+W_EQUAL_PRI	0x8
-
-4-
-68,mraccessf/mrupu]egf take;.c ls fnAbeipassBdpiinwhileasleepiig_b-f* only PLTWAITtdoncurrubm_ygdKEporred.
-e*/m---- mSenFtic 	mraccessf(mrhem .t *, _ar-2.-- mSenFtic 	mrupu]egf(mrhem .t *, _ar-2.-- mSenFtic lllllmr12B,(mrhem .t *, _ar, _ar-2.-- mSenFtic lllllmruu12B,(mrhem .t *-2.-- mSenFtic lllllmraccou12B,(mrhem .t *-2.-- mSenFd(isssss mrtryupu]eg(mrhem .t *-2.-- mSenFd(isssss mrtryaccess(mrhem .t *-2.-- mSenFd(i	mrtrypromoto(mrhem .t *-2.-- mSenFtic lllllmrdemoto(mrhem .t *);
-
-- mSenF_ar	ismrhem ed(mrhem .t *, _ar-2.-- mSenFtic lllllmr12B,.in04(mrhem .t *, _arrtype,Bchar *name, long;sequubcs/2.-- mSenFtic lllllmrd/ho(mrhem .t *);m---# /home/mrin04(mrps name)	mr12B,.in04(mrps MR1+af_BARRIERs name, -1)--# /home/mraccess(mrp/		mraccessf(mrp, 0)oesygrab	BorrREAD/ACCESSe*/c-# /home/mrupu]eg(mrp/		mrupu]egf(mrp, 0)oesygrab	BorrWRITE/UPDATE */c-# /home/mrishem ed_access(mrp/	((mrp/->mr_c*/in0> 0sc-# /home/mrishem ed_upu]eg(mrp/	((mrp/->mr_c*/in0< 0s.-m-#endifbesy__Xy %SUPPORT_MR1+af_H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		emuVBx. }
 
 void
diff -NaAFFxmAe}
-		emuVBx. aA3*r(PSIS_HW_4/fs/afxmAe}
-		emuVBx. .\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		emuVBx. .1970-01-01 00:00:00_ins_M;
* s+affs_itru1,53ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_MUTEX_H___-# /home/__Xy %SUPPORT_MUTEX_H___-
-#incluint<}
-		esginhem .h>
-#incluint<asm/semaphore.h>
-
-4-
-68,Map OH umuVBx'espfverSIRIXRfnAL
-		 semaphores.
- -
-68,DeLOkoy jusrrsnmplyRin04ializhs 	sb-99nwhich-deGuldAbhem p _. oOH r
-68,cV_.crs.
-e*/m-# /home/MUTEX_DEFAULT		0xn--type /h d,* Ok,semaphore	muVBx.t;m---# /home/muVBx.in04(hem , type,Bname)		sema.in04(hem , 1)--# /home/muVBx.deLOkoy(RR "f			sema.in04(hem , -99)--# /home/muVBx.12B,(RR ",Bnum)B-/%b n(RR "f--# /home/muVBx.try12B,(RR "fdcI(%b n.try12B,(RR "f ? 0 : 1)--# /home/muVBx.ou12B,(RR "fdcIup(RR "f--m-#endifbesy__Xy %SUPPORT_MUTEX_H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		esema. }
 
 void
diff -NaAFFxmAe}
-		esema. aA3*r(PSIS_HW_4/fs/afxmAe}
-		esema. .\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		esema. .1970-01-01 00:00:00_ins_M;
* s+affs_itru1,67ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf2 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_SEMA_H___-# /home/__Xy %SUPPORT_SEMA_H___---#incluint<}
-		ebtch.h>
-#incluint<}
-		e5:04.h>
-#incluint<asm/atomic.h>
-#incluint<asm/semaphore.h>
-
-4-
-68,sema.t d,* Okuru jusrrm +s
fnAs,* Ok,semaphorepiinL
-		 kernel.
-e*/m---type /h d,* Ok,semaphorepsema.t;m---# /home/=n04_sema(sp, va2,)c, d)	sema.in04(sp, va2)--# /home/=n04sema(sp, va2)		sema.in04(sp, va2)--# /home/=n04nsema(sp, va2,)name)	sema.in04(sp, va2)--# /home/psema(sp, b)B-/%b n(sp)--# /home/vsema(spfdcIup(sp)--# /home/valusema(spfdcI4atomicne SIS&(spf  c*/in))--# /home/d/hosema(sema)
-
-4-
-68,Map cpsema ( ryRfnA46efb/epsema)RfnA%b n.try12B,.yWe amA|tto(swinch
-68,OHeAredirt valueredstc  cpsema redirts 1 (acquiredm 0 ( letedm _4/
-68,%b n.try12B, redirts OHeAreverse 0 (acquiredm 1 ( letedm.
-e*/m---# /home/cpsema(spfdcI4%b n.try12B,(spf ? 0 : 1)--
-4-
-68,Did0'tBdoAcvsema(spf. Ntypsuru howtto(map OHis
fnAup/%b n/...
-68,ItBdoes anvsema _PrOH uvaluereis
< 0 oOH rnwisennorhiig.
-e*/m---#endifbesy__Xy %SUPPORT_SEMA_H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		esgin. }
 
 void
diff -NaAFFxmAe}
-		esgin. aA3*r(PSIS_HW_4/fs/afxmAe}
-		esgin. .\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		esgin. .1970-01-01 00:00:00_ins_M;
* s+affs_itru1,74ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf2 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_SPIN H___-# /home/__Xy %SUPPORT_SPIN H___-
-#incluint<}
-		est_ed.h>	/*Apf (mpt amA|sfb/do,*/m-#incluint<}
-		esginhem .h>
-
-4-
-68,Map hem .t fverSIRIXRfnAL
-		 sginhem s.
- -
-68,Notntt 0Si}
-		;dirts on/o1+asginhem s dependiigdSF CONFIG_SMP.
-68,Wendon'O0amA|tto(wor yLsboutBSMP p_ Sot7H re.
-e*/m---# /home/SPLDECL(sfdcunsigtod long;sm---type /h dginhem .t hem .t;m---# /home/dginhem .in04(hem , name)	spino12B,.in04(hem )--# /homes pinhem .deLOkoy(RR "f -
-d, read/flome unsigtod long;muVBx. pinhem (hem .t *hem /t-{I-E pino12B,(RR "foc-	, dirt 0;b-} -
-/*ARGSUSED*/m-d, read/flome 
-			muVBx. pinunhem (hem .t *hem , unsigtod long;s/t-{I-E pinoou12B,(RR "foc-} -
-d, read/flome 
-			neLOed. pinhem (hem .t *hem /t-{I-E pino12B,(RR "foc-} -
-d, read/flome 
-			neLOed. pinunhem (hem .t *hem /t-{I-E pinoou12B,(RR "foc-} -
-#endifbesy__Xy %SUPPORT_SPIN H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		esv. }
 
 void
diff -NaAFFxmAe}
-		esv. aA3*r(PSIS_HW_4/fs/afxmAe}
-		esv. .\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		esv.h.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,89ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf2 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_SV H___-# /home/__Xy %SUPPORT_SV H___-
-#incluint<}
-		e5:04.h>
-#incluint<}
-		e(t_ed.h>
-#incluint<}
-		esginhem .h>
-
-4-
-68,SynchronisaSISF variab.cs.
- -
-68,(Parame4ersL"pri", "svf"7a4/f"rts" r(d _typi/
 rmal e(st-e*/m---type /h d,* Ok,sv.sode-,5:04_queueloccH_t wa04erstr-}usv.t;m---# /home/SV FIFO		0xn, esysv.t donFIFOStypet*/m-# /home/SV LIFO		0x2, esysv.t donLIFOStypet*/m-# /home/SV PRIO		0x4, esysv.t donPRIOStypet*/m-# /home/SV KEYED	0x6, esysv.t donKEYEDStypet*/m-# /home/SV DEFAULTsssss SV FIFOc- -
-d, read/flome 
-			_sv.5:04(sv.t *sv, sginhem .t *hem , _arrd, ret@- dcssss unsigtod long;btchout/t-{I-EDECLARE_WAITQUEUE(5:04, currubm/_b-m-sadd_5:04_queuelexclus_ge(&sv->wa04ers, &5:04o_b-s_6set_currubmod, re(d, re)2.-s pinoou12B,(RR "foc- -	st_edule_btchout(btchout/;c- - , move_5:04_queue(&sv->wa04ers, &5:04o_b-}m---# /home/=n04_sv(sv,type,name,.c l)l\@- =n04_5:04queueloccH(&(sv)->wa04ers)--# /home/sv.in04(sv,.c l,name)l\@- =n04_5:04queueloccH(&(sv)->wa04ers)--# /home/sv.deLOkoy(sv)l\@- /*NOTHING*/m-# /home/sv.5:04(sv, tri, hem , s)l\@- _sv.5:04(sv, hem , TASK_UNINTERRUPTIBLe, MAX_SCHEDULE_TIMEOUT)m-# /home/sv.5:04_sig(sv, tri, hem , s)l l\@- _sv.5:04(sv, hem , TASK_INTERRUPTIBLe, MAX_SCHEDULE_TIMEOUT)m-# /home/sv.btchd5:04(sv, tri, hem , s, svf,nus, rts)l\@- _sv.5:04(sv, hem , TASK_UNINTERRUPTIBLe, btchspec_to_j21+ier(ts))m-# /home/sv.btchd5:04_sig(sv, tri, hem , s, svf,nus, rts)l\@- _sv.5:04(sv, hem , TASK_INTERRUPTIBLe, btchspec_to_j21+ier(ts))m-# /home/sv.sigtal(sv)l\@- wake_up(&(sv)->wa04ers)--# /home/sv.broadcast(sv)l\@- wake_up_s2_(&(sv)->wa04ers)--
-#endifbesy__Xy %SUPPORT_SV H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		ebtch.h	}
-		bh_array[i] = bxmAe}
-		ebtch.haA3*r(PSIS_HW_4/fs/afxmAe}
-		ebtch.h.\n",
 2-18a *r3 *b1ize, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		ebtch.h.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,55ff0,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf3 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.  AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-#-2n /h __Xy %SUPPORT_TIME H___-# /home/__Xy %SUPPORT_TIME H___-
-#incluint<}
-		e(t_ed.h>
-#incluint<}
-		ebtch.h>
---type /h d,* Ok,btchspec btchspec_t; -
-d, read/flome 
-			delay(long;btcks/t-{I-Ecurrubmfsd, re = TASK_UNINTERRUPTIBLe; -	st_edule_btchout(btcks/oc-} -
-d, read/flome 
-			nanoreme(d,* Ok,btchspec *tvp/t-{I-Ed,* Ok,btchval>tv;c- - do_getbtchofday(&tv)2.-stvp->tv.sec =>tv.tv.sec2.-stvp->tv.nsec =>tv.tv.usec * 1affoc-} -
-#endifbesy__Xy %SUPPORT_TIME H__4KS_nit_Pstruc21+affs_init_b ffs_init_Pstruc21+affs_init_bx6smAexmAe}
-		ex= oaops.		res = -EIO;
 			gotoxmAe}
-		ex= oaops.	aA3*r(PSIS_HW_4/fs/afxmAe}
-		ex= oaops.	.\n",
 44/4a *r05c(size, GFP_KERNEL);
 		}
-		bh_array[i] = bxmAe}
-		ex= oaops.	.1970-01-01 00:00:00_ins_M;
* s+affs_itru1,13* s+a,4.e(
-4-
-68,Copyrightt(c) \n"0(2Pf4 Silicon Graphics, Inc.  All Rights Res0rv <.
-68
-68,T/dontrogram dond/ho(softwarureyou7-30 16dULOkibuVB_itW_4//
 t2.4ify_it
-f* undIS_OH uct
miS_PrversISF 2S_PrOH uGNU,8 +268,7PubleadLicense aop-f* tubles;
 }byrOH uFf (rSoftwaru F{
-	s
---.
-68
-68,T/dontrogram dondULOkibuVBdpiinux-2hopntt 0Sidt wGuldAbenusufu2,)d t
-68,WITHOUT ANY WARRANTY;  invoutBkveinuxo(impliBdpwarrantyS_P
- syMERCHANTABILITY 
 tFITNESS FOR A PARTICULAR PURPOSE.
-68
-68,FurOH r,nuxdonsoftwaru dondULOkibuVBdp invoutBsny warrantySt 0Sidt iop-f* d/ho(_PrOH urightfu2	_Haim if( nySt irdmpt
son regacaiigd/ffS000emal p-f* orrOH ulike.	 AnySlicense troviaed7H rein, wheOH r impliBdporp-f* oOH rwise,Aappliereonly 	sb ldonsoftwaru B->s.  Pamoutnlicenses, iP
-f* a4y, troviaed7H rein doA_typapplyRfnAcombins
---iS_PrOHdontrogram  invp-f* oOH rnsoftwaru, orr nySoOH rntrod3,7 w 0Ssokver.
-68
-68,You7deGuldAigafRreceiv < a copyS_PrOH uGNU,8 +268,7PubleadLicense along
- sywinv2OHdontrogram;n(++_ty,yw     OH uFf (rSoftwaru F{
-	s
---, Inc., 59
-68,Te/
 r Place -tSuite 3302 Boston MA 02111nt307, USA.
- -
-68,Conta,7 edmp_maSISF: Silicon Graphics, Inc.,   * sAmphiOH atru Pkwy,
- syM*/inaom(View, CA  94043, or:
- -
-68,http://www.sgi.c*/
-68
-68,ForrfurOH r edmp_maSISF regacaiigdOHdonnoreae, see:
- -
-68,http://oss.sgi.c*/Sproje  s/8 +Info/SGIGPLNoreaeExplan/
-e*/c-
-#incluint"x= .h"
-#incluint"x= o
-	m.h"
-#incluint"x= olog.h"
-#incluint"x= osb.h"
-#incluint"x= odir.h"
-#incluint"x= odir2.h"
-#incluint"x= o+fans.h"
-#incluint"x= odmapi.h"
-#incluint"x= om*/in.h"
-#incluint"x= obmap_btruh.h"
-#incluint"x= oa2_HW_btruh.h"
-#incluint"x= oia2_HW_btruh.h"
-#incluint"x= os2_HW.h"
-#incluint"x= obtruh.h"
-#incluint"x= osttr_sf.h"
-#incluint"x= odir_sf.h"
-#incluint"x= odir2_sf.h"
-#incluint"x= odinodh.h"
-#incluint"x= oinodh.h"
-#incluint"x= oerror.h"
-#incluint"x= orw.h"
-#incluint"x= oiomap.h"
-#incluint<}
-		esobuf.h>
---STATIC 
-			x= oc*/in_pageod, re(d,* Ok,page *, _arr*, _arr*, _arr*)2.-STATIC 
-			x= oc*nvert_page(d,* Ok,inodh *, e,* Ok,page *,@- dc	x= oiomap.t *, ead( *, _ar, _ar-2.-c-#-2. /homed(Xy %RW_TRACE) -tic 
-x= opageo+face(e-,_ar	,tag,I-Ed,* Ok,inodh	*inodh,I-Ed,* Ok,page	*page,e-,_ar	,read)t-{I-Ex= oinodh_t	*ip2.-sbhv.deLc_t	*bdp2.-svnodh_t		*vp>= LINVy %GET_VP(inodh)2.-sloff_t		i are = i6snitne SISinodh)2.-sloff_t		offs6ef=,page->indIx << fsin_CACHE_SHIFT;e-,_ar	,dela2_HW0tm-1, unmappe 0tm-1, unw   mou0tm-1;.-p-s= MSpageoha obufft
sSpageo) -/ex= oc*/in_pageod, re(page, &dela2_HW, &unmappe , &unw   mou/;c- - bdp0tmvn_bhv.lookup(VN_BHV_HEAD(vp/, &x= ovnodhops/_b-s-p0tmXy %BHVTOI(bdpV;p-s= MS_ip->iorw+face) -/e, dirt;c- - k+face_al er(ip->iorw+face,@- d(ead( *)((unsigtod long)tag),@- d(ead( *)ip,@- d(ead( *)inodh,I-Ed(ead( *)page,e-,d(ead( *)((unsigtod long)read),e-,d(ead( *)((unsigtod long)((ip->iod.di6snit >> 32) & 0xffffffff)),e-,d(ead( *)((unsigtod long)(ip->iod.di6snit & 0xffffffff)),e-,d(ead( *)((unsigtod long)((isnit >> 32) & 0xffffffff)),e-,d(ead( *)((unsigtod long)(isnit & 0xffffffff)),e-,d(ead( *)((unsigtod long)((offs6ef>> 32) & 0xffffffff)),e-,d(ead( *)((unsigtod long)(offs6ef& 0xffffffff)),e-,d(ead( *)((unsigtod long)dela2_HW),e-,d(ead( *)((unsigtod long)unmappe ),e-,d(ead( *)((unsigtod long)unw   mou/,e-,d(ead( *)ct a,e-,d(ead( *)ct a/oc-} -#e_HW -# /home/x= opageo+face(tag,,inodh, page, read)t-#endif -
-tic 
-hinv= ounw   mou_stre(e-,d,* Ok,bufft
loccH	*bh,e-,_ar	,	uptou]eg)t-{I-Epageobuf_t		*pb =  pageobuf_t *)bh->b_priv]eg;c- - ASSERT(bufft
lunw   mou(bhm);m- bh->b_endoio:r ct aff-	clear_bufft
lunw   mou(bhm;p-s= MS_uptou]eg)t-	Epagebuf_ioerror(pb, EIOm;p-s= MSatomicndec__4/_test(&pb->pb_io_, maomiigs0t=t(m {t-	Epagebuf_iostre(pb, 1,O1V;p-s}b-sendobufft
lio_async(bh, uptou]eg); -} -
-4-
-68,Issue +fansa_SISFsefnAconvert a bufft
 rangedfverSunw   mou
-68,to(w   mou0- mSnts.
-e*/m-STATIC 
-		
-hinv= ounw   mou_convert(I-Ex= obuf_t	*bp/t-{I-Evnodh_t		*vp>= Xy %BUF_FSPRIVATE(bp, vnodh_tr*)2.-,_ar	,error;c- - BUG_ON4atomicne SIS&bp->pb_hold) <O1V;p-sVOP_BMAP(vp, Xy %BUF_OFFSET(bp/, Xy %BUF_SIZE(bp/,@- dcBMAPI_UNWRITTENROct a, dpst, errorV;p-sXy %BUF_SET_FSPRIVATE(bp, ct a/oc-sXy %BUF_CLR_IODONE_FUNC(bp/oc-sXy %BUF_UNDATAIO(bp/oc-siput(LINVy %GET_IP(vpm);m- pagebuf_iostre(bp, 0,O0V;p-}
---STATIC il p-x= omap_bhem s(e-,d,* Ok,inodh		*inodh,I-Eloff_t			offs6e,I-Edenit.t			c*/in,I-Ex= oiomap.t		*iomapp,e-,_ar	,	.c ls/t-{I-Evnodh_t			*vp>= LINVy %GET_VP(inodh)2.-s_ar	,	error, niomaps0tm1_b-p-s= MS((.c ls & (BMAPI_DIRECT|BMAPI_SYNC)s0t=tBMAPI_DIRECT) &&p-sllll(offs6ef>= i6snitne SISinodh)o) -/ec*/in0tmmax_t(senit.t, c*/in, Xy %WRITE_IO_LOG)2.-, dry:p-sVOP_BMAP(vp, offs6e, c*/in, .c ls,,iomapp, &niomaps, errorV;p-s= MS(error0t=tEAGAIN)l||s(error0t=tEIOm) -/e, dirty-error;c-o(++ uolokely (.c ls & (BMAPI_WRITE|BMAPI_DIRECT)s0t=@- dc		(BMAPI_WRITE|BMAPI_DIRECT) && niomaps0&&p-sdc		(iomapp->iomap..c ls & IOMAP_DELAY)mmode-, .c ls = BMAPI_AL1+CATELY-E g fnAredry;p-s}b-s(++ .c ls & (BMAPI_WRITE|BMAPI_AL1+CATEmmode-, VMODIFY(vpm;p-s}b-s, dirty-error;c-} -
-4-
-68,Finds OHeAcorrespondiigdmappiigd/fAbhem p@map arrayS_PrOH 
-68,givein@offs6efwinviin3 @page.
-e*/m-STATIC x= oiomap.t *p-x= ooffs6e_to_map(e-,d,* Ok,page		*page,e-,x= oiomap.t		*iomapp,e-,unsigtod long		offs6e/t-{I-Eloff_t			fullooffs6euiesyoffs6effverSd, rt _PrB->se*/c-
- ASSERT(offs6ef< fsin_CACHE_SIZE/;c- - fullooffs6ef=,page->indIx;, esyNB: usiigd64bitBnumbt
 */m- fullooffs6ef<<= fsin_CACHE_SHIFT;iesyoffs6effverSB->sed, rt */m- fullooffs6ef+= offs6eui	iesyoffs6effverSpage d, rt */m-b-s(++ .ullooffs6ef< iomapp->iomap.offs6e/t-/e, dirtyct aff-	(++ iomapp->iomap.offs6e + iomapp->iomap.bsnit > .ullooffs6e/t-/e, dirtyiomappoc-	, dirt ct aff-}
---STATIC 
-		p-x= omap_atooffs6e(e-,d,* Ok,page		*page,e-,d,* Ok,bufft
loccH	*bh,e-,unsigtod long		offs6e,e-,_ar	,	bhem _bits,e-,x= oiomap.t		*iomapp)t-{I-Ex= odaddr_t 	bn2.-sloff_t		,delta2.-s_ar	,	sector_shift;c- - ASSERT(!(iomapp->iomap..c ls & IOMAP_HOLEm);m- ASSERT(!(iomapp->iomap..c ls & IOMAP_DELAY)m;m- ASSERT(iomapp->iomap.bn != IOMAP_DADDR_ct a/oc- - deltaf=,page->indIx; - deltaf<<= fsin_CACHE_SHIFT; - deltaf+= offs6eu - deltaf-= iomapp->iomap.offs6eu - deltaf>>= bhem _bitsoc- -	sector_shift = bhem _bits - BBSHIFT; - bu0tmiomapp->iomap.bn >> sector_shift;c- bu0+= delta2.-sASSERT((bu0<< sector_shift)f>= iomapp->iomap.bn/oc- - hem _bufft
(bhm;p-sbh->b_bhem nr = bn;p-sbh->b_dev0tmiomapp->iomap., rget->pbr_kdev; -	s6e_bufft
lmappe (bhm;p-sclear_bufft
ldelay(bhm;p-} -
-4-
-68,Look	BorraSpage 0SidndIx which-is ou12B, < andAconnaoms our
-f* unw   mou0- mSnt .c lg
 }bufft
s 0Sidts,ocad.  Redirts page
-f* 12B, < andAwinv2au0- mra reft
etc  c*/in, andAlengnv2_PrOH 
-68,unw   mou0- mSnt componSnt on2OHdontage t 0Siwe7-30 w    ,
- syiinun04s _PrB->ssystem bhem s.
- -/m-STATIC e,* Ok,page *
-x= oprobeounw   mou_page(e-,d,* Ok,address_space	*mappiig,e-,unsigtod long		dndIx,e-,x= oiomap.t		*iomapp,e-,pageobuf_t		*pb,e-,unsigtod long		max_offs6e,e-,unsigtod long		*fsbs,e-,unsigtod d(isssss       bbits/t-{I-Ed,* Ok,page		*pageoc- - page =rB-4/_try12B,_page(mappiig,idndIxm;p-s= MS_pageot-/e, dirty0;.-p-s= MSpage->mappiigd&& pageoha obufft
sSpageo)ode-, d,* Ok,bufft
loccH	*bh, *occHLY-E unsigtod long		pooffs6ef=,0;.-p-s	*fsbs0tmNLY-Esbh0tmoccHf=,pageobufft
sSpageoLY-EsdoA{p-sdc= MS_bufft
lunw   mou(bhm)p-sdc	be Sk;p-sdc= MS_x= ooffs6e_to_map(page, iomapp, p.offs6e/)p-sdc	be Sk;p-sdc= MSpooffs6ef>tmmax_offs6e/t-/ec	be Sk;p-sdcx= omap_atooffs6e(page, bh, pooffs6e, bbits, iomappoLY-Es	s6e_bufft
lunw   mou_io(bhm;p-s		bh->b_priv]egf=,pb;p-s		pooffs6ef+= bh->b_snit;p-s		(*fsbs)++9--s,} whilea((bh0tmbh->b_OHdo_page) != occH/oc- - c= MSpooffs6e/t-/ec, dirtypageoc-6}c-I-Eou12B,_page(pageoLY-E, dirt ct aff-}
---4-
-68,Look	BorraSpage 0SidndIx which-is ou12B, < andA_typmappe 
-68,y6ef- clusteriigdmp_ mmap w     case.
-e*/m-STATIC unsigtod d(i
-x= oprobeounmappe _page(e-,d,* Ok,address_space	*mappiig,e-,unsigtod long		dndIx,e-,unsigtod d(i		pg_offs6e/t-{I-Ed,* Ok,page		*pageoc-s_ar	,	r6ef=,0;.-p-spage =rB-4/_try12B,_page(mappiig,idndIxm;p-s= MS_pageot-/e, dirty0;.-p-s= MSpage->mappiigd&& PageDirtySpageo)ode-, = MSpageoha obufft
sSpageo)A{p-sdcd,* Ok,bufft
loccH	*bh, *occHLY-p-s		bh0tmoccHf=,pageobufft
sSpageoLY-EssdoA{p-sdc = MSbufft
lmappe (bhml||s_bufft
luptou]eg(bhm)p-sdc		be Sk;p-sdc	r6ef+= bh->b_snit;p-s		s= MSr6ef>tmpg_offs6e/t-sdc		be Sk;p-sdc} whilea((bh0tmbh->b_OHdo_page) != occH/oc-EsgIS_HWt-/ec, d = fsin_CACHE_SIZEoc-6}c-I-Eou12B,_page(pageoLY-E, dirt r6eu -}
---STATIC unsigtod d(i
-x= oprobeounmappe _cluster(e-,d,* Ok,inodh		*inodh,I-Ed,* Ok,page		*d, rtpage,e-,d,* Ok,bufft
loccH	*bh,e-,d,* Ok,bufft
loccH	*occH/t-{I-Eunsigtod long		tdndIx, tlast, tloff;e-,unsigtod d(i		len, total0tmNLY-Ed,* Ok,address_space	*mappiig0tminodh->iomappiig;c- -	/*AFirst sumdmp_wards in2OHdontage */m- doA{p-sd= MSbufft
lmappe (bhm/t-sdcbe Sk;p-sdtotal0+= bh->b_snit;p-s} whilea((bh0tmbh->b_OHdo_page) != occH/oc- - /* Ih wu>eROt_ed OHeAendA_PrOH upage, sumdmp_wards in
-	f*  o2_Hwiig0pages.d-pe*/m-sif (bh0t= occH/A{p-sdtlast = i6snitne SISinodh) >> fsin_CACHE_SHIFT; -  /* Prune2OHdonbaB, Oo aead( pathological0behavio
 */m- 	tloff0tmmin(tlast, d, rtpage->indIx +d64/oc-Esmp_ (tdndIx0tmd, rtpage->indIx +d1; tdndIx0< tloff; tdndIx++)A{p-sdclou0tmx= oprobeounmappe _page(mappiig,itdndIx,e-,,,,,,,fsin_CACHE_SIZE/;c-sdc= MS_lou)p-sdc	r6eirt total;c-sdctotal0+= louoc-Esgp-sd= MStdndIx0t= tlast0&&p-sdllll(tloff0tmi6snitne SISinodh) & (fsin_CACHE_SIZEf- 1)mmode-, ctotal0+= x= oprobeounmappe _page(mappiig,e-,,,,,,,tdndIx, tloff)LY-E }c- }c-	r6eirt total;c-}
---4-
-68,Probe	BorraSgiveintage (dndIxmpiinux-2inodh andAtestn(++im-is delaye 
-68,andAwinvoutBunw   mou0bufft
s.  Redirts page 12B, < andAwinv2au0- mra
-68,reft
etc  c*/in.
- -/m-STATIC e,* Ok,page *
-x= oprobeodela2_HW_page(e-,d,* Ok,inodh		*inodh,I-Eunsigtod long		dndIx/t-{I-Ed,* Ok,page		*pageoc- - page =rB-4/_try12B,_page(inodh->iomappiig,idndIxm;p-s= MS_pageot-/e, dirtyct aff-p-s= MSpage->mappiigd&& pageoha obufft
sSpageo)ode-, d,* Ok,bufft
loccH	*bh, *occHLY-E _ar	,	acceptab.cf=,0;.-p-s	bh0tmoccHf=,pageobufft
sSpageoLY-EsdoA{p-sdc= MSbufft
lunw   mou(bhm)A{p-sdc acceptab.cf=,0;.-dc		be Sk;p-sdc} S_HWo-2.4bufft
ldelay(bhm)A{p-sdc acceptab.cf=,1;p-sdc}--s,} whilea((bh0tmbh->b_OHdo_page) != occH/oc- - c= MSacceptab.c/t-/ec, dirtypageoc-6}c-I-Eou12B,_page(pageoLY-E, dirt ct aff-}
---STATIC il p-x= omap_unw   mou(e-,d,* Ok,inodh		*inodh,I-Ed,* Ok,page		*d, rt_page,e-,d,* Ok,bufft
loccH	*occH,e-,d,* Ok,bufft
loccH	*curr,I-Eunsigtod long		p_offs6e,e-,_ar	,	bhem _bits,e-,x= oiomap.t		*iomapp,e-,_ar	,	d, rtio,e-,_ar	,	a2__bhmt-{I-Ed,* Ok,bufft
loccH	*bh0tmcurr;e-,x= oiomap.t		*tmp;m- pageobuf_t		*pb2.-sloff_t		,offs6e, snit;p-sunsigtod long		nbhem sf=,0;.-p-soffs6ef=,d, rt_page->indIx; - offs6ef<<= fsin_CACHE_SHIFT; - offs6ef+= p.offs6eu - - /* 46efau0"(mpty" pagebuftto(manage IO compleSISF
-	f* ProperuvaluerewillibeAs6efbeforep, dirtiigd*/m- pb = pagebuf_lookup(iomapp->iomap., rget, 0,O0,O0V;p-s= MS_pb) -/e, dirty-EAGAINu - - /* Take;a reft
etc  	sb l-2inodh 	sbprevenSidt fver
-	f* beiigdre_HaimBdp hileawu>igafRoutd, ndiigdunw   mou
-	f* - mSnt IO SF it.d-pe*/m-sif ((igrabSinodh)o != inodh) {p-sdpagebuf_d/ho(pb); -/e, dirty-EAGAINu -6}c-I-E/* S6efb/epc*/in0bo 1Rin04ially,nuxdonwillistopt n I/O
-	f* compleSISF,cV_.outBwhich-happets beforepwu>igafRd, rte 
-	f*  _. b/epI/OffverScV_.iig0pagebuf_iostre0boo early.d-pe*/m-satomicns6e(&pb->pb_io_, maomiig,O1V;p- -	/*AFirst map mp_wards in2OH upageAconsecutive0bufft
s
-	f* coveriigduxdonunw   mou0- mSntd-pe*/m-sdoA{p-sd= MS_bufft
lunw   mou(bhm)p-sdcbe Sk;p-sdtmp0tmx= ooffs6e_to_map(d, rt_page, iomapp, p.offs6e/;p-sd= MS_tmp)p-sdcbe Sk;p-sdx= omap_atooffs6e(d, rt_page, bh, pooffs6e, bhem _bits, iomappoLY-Ess6e_bufft
lunw   mou_io(bhm;p-s	bh->b_priv]egf=,pb;p-s	pooffs6ef+= bh->b_snit;p-s	nbhem s++9--s} whilea((bh0tmbh->b_OHdo_page) != occH/oc- - atomicnadd(nbhem s, &pb->pb_io_, maomiigsoc- - /* Ih wu>eROt_ed OHeAendA_PrOH upage, map mp_wards in2any
-	f*  o2_Hwiig0pagesBwhich-aru alsoAcover
 }byrOHdon- mSnt.d-pe*/m-sif (bh0t= occH/A{p-sdd,* Ok,address_space	*mappiig0tminodh->iomappiig;c-E unsigtod long		tdndIx, tloff, tlast, bs;c-E unsigtod _ar	,bbits0tminodh->ioblkbitsoc-	Ed,* Ok,page		*pageoc- - dtlast = i6snitne SISinodh) >> fsin_CACHE_SHIFT; -  tloff0tm iomapp->iomap.offs6e + iomapp->iomap.bsnit) >> fsin_CACHE_SHIFT; -  tloff0tmmin(tlast, tloff)LY-E mp_ (tdndIx0tmd, rt_page->indIx +d1; tdndIx0< tloff; tdndIx++)A{p-sdcpage =rx= oprobeounw   mou_page(mappiig,e-,,,,,,tdndIx, iomapp, pb,e-,,,,,,fsin_CACHE_SIZE, &bs, bbits/;c-sdc= MS_pageot-/e		be Sk;p-sdcnbhem sf+= bsoc-	E atomicnadd(bs, &pb->pb_io_, maomiigsoc-	/ex= oc*nvert_page(inodh, page, iomapp, pb,e-,,,,,,	d, rtio, a2__bhmoc-	/eesystopt= Mc*nvertiigduxe amxk,page mighttaddc-	/ef* -nough bhem s t 0SiOHeAcorrespondiigdbytec-	/ef* c*/in0won'O0fim-in our ulong;page buftlengnv2*/m-  	= MSnbhem sf>tm (ULONG_MAXf- fsin_SIZE/ >> bhem _bitsm)p-sdc	g fnA-noughLY-E }c-p-sd= MStdndIx0t= tlast0&&p-sdllll(tloff0tm(i6snitne SISinodh) & (fsin_CACHE_SIZEf- 1)mm)A{p-sdcpage =rx= oprobeounw   mou_page(mappiig,e-,,,,,,,tdndIx, iomapp, pb,e-,,,,,,	tloff, &bs, bbits/;c-sdc= MSpage) {p-sdc nbhem sf+= bsoc-	E  atomicnadd(bs, &pb->pb_io_, maomiigsoc-	/eex= oc*nvert_page(inodh, page, iomapp, pb,e-,,,,,,	d, rtio, a2__bhmoc-	/e	= MSnbhem sf>tm (ULONG_MAXf- fsin_SIZE/ >> bhem _bitsm)p-sdc		g fnA-noughLY-E c}--s,} -6}c-I--nough:p-s are = nbhem s;, esyNB: usiigd64bitBnumbt
 H re2*/m-  are <<= bhem _bitso esyconvert fsb's fnAbyte ranged*/m-b-sXy %BUF_DATAIO(pb); -/Xy %BUF_ASYNC(pb); -/Xy %BUF_SET_SIZE(pb, snit); -/Xy %BUF_SET_COUNT(pb, snit); -/Xy %BUF_SET_OFFSET(pb, offs6e/;p-sXy %BUF_SET_FSPRIVATE(pb, LINVy %GET_VP(inodh)/;p-sXy %BUF_SET_IODONE_FUNC(pb, hinv= ounw   mou_convert/_b-m-sifMSatomicndec__4/_test(&pb->pb_io_, maomiigs0t=t(m {t-	Epagebuf_iostre(pb, 1,O1V;p-s}b-
-	, dirt 0;b-} -
-STATIC 
-		p-x= osubmit_page(e-,d,* Ok,page		*page,e-,d,* Ok,bufft
loccH	*bh_arr[],e-,_ar	,	cntmt-{I-Ed,* Ok,bufft
loccH	*bhoc-s_ar	,	i_b-m-sifMScins0{_-/emp_ (if=,0; i0< cin; i++)A{p-sdcbh0tmbh_arr[i]LY-Es	s6e_bufft
lasync_io(bhm;p-s		= MSbufft
lunw   mou(bhm)p-sdc	s6e_bufft
lunw   mou_io(bhm;p-s		s6e_bufft
luptou]eg(bhm;p-s		clear_bufft
ldirtySbhm;p-s	}c-p-sdmp_ (if=,0; i0< cin; i++)A{p-sdcrefile_bufft
(bh_arr[i]m;p-s		submit_bh(WRITE, bh_arr[i]m;p-s	} -6}IS_HWt-/eou12B,_page(pageoLY-}
---4-
-68,A2_HW]egf& map bufft
s mp_ page giveinOHeAe mSnt map.yW     itBout.
-68,except mp_ OHeAoriginal page if(  w    page, OHdondoncV_.cdA_u
-68,dela2_HW/unw   mou0pagesBonly, mp_ OHeAoriginal page im-is possibl 
-68,t 0SiOHeApage haonnodmappiigd0Sia2_.
-e*/m-STATIC 
-		
-x= oc*nvert_page(e-,d,* Ok,inodh		*inodh,I-Ed,* Ok,page		*page,e-,x= oiomap.t		*iomapp,e-,tic 			*priv]eg,e-,_ar	,	d, rtio,e-,_ar	,	a2__bhmt-{I-Ed,* Ok,bufft
loccH	*bh_arr[MAX_BUF_PER_fsin], *bh, *occHLY-Ex= oiomap.t		*mp0tmiomapp, *tmp;m- unsigtod long		end, offs6e, endoindIx; - _ar	,	if=,0,idndIxf=,0;.-d_ar	,	bbits0tminodh->ioblkbitsoc-
-sendodndIxf=,i6snitne SISinodh) >> fsin_CACHE_SHIFT; - = MSpage->dndIx0< endodndIx)A{p-sdendA= fsin_CACHE_SIZEoc-6} S_HWo{p-sdendA= i6snitne SISinodh) & (fsin_CACHE_SIZE-1V;p-s}b-sbh0tmoccHf=,pageobufft
sSpageoLY-EdoA{p-sdoffs6ef=,i0<< bbitsoc-	E= MS_(PageUptou]eg(page) || bufft
luptou]eg(bhmm)p-sdcconninueoc-	E= MSbufft
lmappe (bhml&& a2__bh0&&p-sdllll_bufft
lunw   mou(bhml&& !bufft
ldelay(bhm)A{p-sdc= MSd, rtiol&& (offs6ef< endm)A{p-sdc hem _bufft
(bhm;p-ssdcbh_arr[indIx++]0tmbhLY-E c}--s,cconninueoc-	E}p-sdtmp0tmx= ooffs6e_to_map(page, mp, offs6e/;p-sd= MS_tmp)p-sdcconninueoc-	EASSERT(!(tmp->iomap..c ls & IOMAP_HOLEm);m- EASSERT(!(tmp->iomap..c ls & IOMAP_DELAY)m;m-
-  /* If OHdondona amw,unw   mou0- mSnt bufft
 (i.e. onep-sdl* t 0Siwe7igafn'O0passBdpiinpriv]egfu]ea mp_,iwe7mustp-sdl* now(map OHis
bufft
 too.p-sdl*/c-	E= MSbufft
lunw   mou(bhml&& !bh->b_endoio)A{p-sdcASSERT(tmp->iomap..c ls & IOMAP_UNWRITTENsoc-	/ex= omap_unw   mou(inodh, page, occH, bh,e-,			,offs6e, bbits, tmp, d, rtio, a2__bhmoc-	/} S_HWo-2.4!MSbufft
lunw   mou(bhml&& bufft
lhem ed(bhmm)A{p-sdcx= omap_atooffs6e(page, bh, offs6e, bbits, tmpm;p-s		= MSbufft
lunw   mou(bhm)A{p-sdc s6e_bufft
lunw   mou_io(bhm;p-s			bh->b_priv]egf=,priv]eg;c-	sdcASSERT(priv]eg)LY-E c}--s,} -6c= MSd, rtiol&& (offs6ef< endm)A{p-sdcbh_arr[indIx++]0tmbhLY-E } S_HWo{p-sdeou12B,_bufft
(bhm;p-ssdmark_bufft
ldirtySbhm;p-s	}c-s} whilea(i++, (bh0tmbh->b_OHdo_page) != occH/oc- - = MSd, rtio)A{p-sdx= osubmit_page(page, bh_arr,idndIxm;p-s} S_HWo{p-sdou12B,_page(pageoLY-E}Y-}
---4-
-68,Convert & w     outBs cluster if(pagesBin2OH usameAe mSnt as. /homed
-68,by mp andA o2_Hwiig0OH us, rt page.
-e*/m-STATIC 
-		
-x= ocluster_w    (e-,d,* Ok,inodh		*inodh,I-Eunsigtod long		tdndIx,e-,x= oiomap.t		*iomapp,e-,_ar	,	d, rtio,e-,_ar	,	a2__bhmt-{I-Eunsigtod long		tlast;I-Ed,* Ok,page		*pageoc- - tlast =  iomapp->iomap.offs6e + iomapp->iomap.bsnit) >> fsin_CACHE_SHIFT; - mp_ (; tdndIx0< tlast; tdndIx++)A{p-sdpage =rx= oprobeodela2_HW_page(inodh, tdndIxm;p-sc= MS_pageot-/e	be Sk;p-sdx= oc*nvert_page(inodh, page, iomapp, dpst, d, rtio, a2__bhmoc-	}Y-}
---4-
-68,CV_.iig0uxdonwinvoutBd, rtiols6e meansiwe7aru beiigdaskA|tto(make;a dirtyp-f* tage e SIy mp_ d/hoiigd/t's0bufft
s.  WhenncV_.cdAwinv2d, rtiols6e OH u
-68,we7aru comiigdmverSw    page.
- -
-68,WhenncV_.cdAwinv2d, rtiols6e im-is imporrain0b 0Siwe7w     OH uWHOLEp-f* tage = Mpossibl .
-68,T/e bh->b_s, re'oncVn_typknow(if( nyS_PrOH ubhem sfp_ which-bhem pforp-f* b 0Simatter aru dirty duh 	sbmmap w    s, andAOH reforepbh0uptou]eg iop-f* only vaild _PrOH upage imself ion'O0compleSely uptou]eg.  SomeAlayerop-f* may clearrOH upage dirty .c l,prip_ OoScV_.iig0w     page, undIS_OH 
-68,assumpSISF,OHeAentir upage willibeAw   mou0out;,by _typw   iigdSut_OH 
-68,wholentage t  upageAcanibeAreusBdpbeforep _. val			dirty d]ea iop-f* w   mou0out.  Notn:Bin2OH ucase if(  tage t 0Sihaonbeou0dirty' }byp-f* mapw     andAbuk,par4iallyls6eup,by bhem _pr pare_w     OH 
-68,bh->b_s, res'onwilli_typagf (randAonly onesls6eup,by BPW/BCWnwilliigaf
-68,val			d, ret OHus OHeAwholentage mustibeAw   mou0out rhiig.
-e*/m---STATIC il p-x= opageod, re_convert(I-Ed,* Ok,inodh	*inodh,I-Ed,* Ok,page	*page,e-,_ar	,d, rtio,e-,_ar	,unmappe )besyalsoAimpliBs page uptou]eg */m-{I-Ed,* Ok,bufft
loccH	*bh_arr[MAX_BUF_PER_fsin], *bh, *occHLY-Ex= oiomap.t		*iomp, iomap;m- unsigtod long		pooffs6ef=,0, endoindIx; - loff_t		,offs6e;m- unsigtod long long	endooffs6e;m- _ar	,	len, err,id, cinf=,0, uptou]eg =,1;p-s_ar	,	.c ls0tmd, rtiol? 0 : BMAPI_TRY1+af;p-s_ar	,	pageodirty tm1_b-p-
- /* Arepwu>off0OHeAendA_PrOH uB->se?l*/c-	endodndIxf=,i6snitne SISinodh) >> fsin_CACHE_SHIFT; - = MSpage->dndIx0>= endodndIx)A{p-sdif ((page->dndIx0>= endodndIx +d1) ||p-sdllll_(i6snitne SISinodh) & (fsin_CACHE_SIZEf- 1)mmo{p-sdeerr0tm-EIO;p-ssdg fnA-rror;c-o,} -6}c-I-doffs6ef=,(loff_t)page->dndIx0<< fsin_CACHE_SHIFT;e-,endooffs6e0tmmin_t(unsigtod long long,e-,		offs6e + fsin_CACHE_SIZE, i6snitne SISinodh)ooc- - bh0tmoccHf=,pageobufft
sSpageoLY-Eiomp:r ct aff- - lou0tmbh->b_snit;p-sdoA{p-sd= MSoffs6ef>tmendooffs6eot-/e	be Sk;p-sd= MS_bufft
luptou]eg(bhm)p-sdcuptou]eg =,0oc-	E= MS_(PageUptou]eg(page) || bufft
luptou]eg(bhmml&& !d, rtio)p-sdcconninueoc-c-	E= MSiomp)A{p-sdc=omp0tmx= ooffs6e_to_map(page, &iomap, p.offs6e/;p-sd}m-
-  /*p-sdl* First case, map an,unw   mou0- mSnt andApr parepforp-		f* - mSnt d, re conversISF +fansa_SISF SF compleSISF.p-sdl*/c-	E= MSbufft
lunw   mou(bhm)A{p-sdc= MS!iomp)A{p-sdceerr0tmx= omap_bhem s(inodh, offs6e, len, &iomap,e-,			,cBMAPI_READ|BMAPI_IGNSTATE/;c-sdcc= MSerr)A{p-sdcedg fnA-rror;c-o, c}--s,cc=omp0tmx= ooffs6e_to_map(page, &iomap,e-,			,c		pooffs6e)LY-E c}--s,E= MSiompl&& d, rtio)A{p-sdsd= MS_bh->b_endoio)A{p-sdcceerr0tmx= omap_unw   mou(inodh, page,e-,			,c	occH, bh, p_offs6e,e-,,,,,,,inodh->ioblkbits, iomp,e-,,,,,,	d, rtio, unmappe );c-o, cc= MSerr)A{p-sdceddg fnA-rror;c-o, cc}--s,cc}p-ssdcbh_arr[cin++]0tmbhLY-E c	pageodirty tm0LY-E c}--s,/*p-sdl* Second case, a2_HW]egfspace	BorraSdela2_HW0bufft
.p-sdl*,Wen-30 16dirt EAGAIN H re2in2OH ureleas upageAcase.
-sdl*/c-	E} S_HWo-2.4bufft
ldelay(bhm)A{p-sdc= MS!iomp)A{p-sdceerr0tmx= omap_bhem s(inodh, offs6e, len, &iomap,e-,			,cBMAPI_AL1+CATE | .c ls/;c-sdcc= MSerr)A{p-sdcedg fnA-rror;c-o, c}--s,cc=omp0tmx= ooffs6e_to_map(page, &iomap,e-,			,c		pooffs6e)LY-E c}--s,E= MSiomp)A{p-sdcex= omap_atooffs6e(page, bh, pooffs6e,e-,			,cinodh->ioblkbits, iomp/;c-sdcc= MSd, rtio)A{p-sdsdcbh_arr[cin++]0tmbhLY-E c	} S_HWo{p-sdedeou12B,_bufft
(bhm;p-ssdsdmark_bufft
ldirtySbhm;p-s	 c}--s,ccpageodirty tm0LY-E c}--s,} S_HWo-2.4(bufft
luptou]eg(bhm || PageUptou]eg(page))0&&p-sdclll(unmappe 0|| d, rtio))A{p-p-sdc= MS!bufft
lmappe (bhm/A{p-sdsd=ar	snit;p-p-sdsd/*p-sdsdl*,Getbtng H re2impliBs an,unmappe 0bufft
p-sdsdl*,was mpund, andAwe7aru iin3 path wherepwup-sdsdl*,amA|tto(w     OH uwholentage out.
-sdsdl*/p-sdsd= MS_iomp)A{p-sdces are = x= oprobeounmappe _cluster(e-,,			,cinodh, page, bh, occH/oc-Esdceerr0tmx= omap_bhem s(inodh, offs6e,e-,,,,,,	dare, &iomap,e-,			,c	BMAPI_WRITE|BMAPI_MMAP);c-o, cc= MSerr)A{p-sdceddg fnA-rror;c-o, cc}--s,ccc=omp0tmx= ooffs6e_to_map(page, &iomap,e-,			,c		     pooffs6e)LY-E cc}--s,cc= MSiomp)A{p-sdceex= omap_atooffs6e(page,e-,			,c	bh, p_offs6e,e-,,,,,,,inodh->ioblkbits, iomp);c-o, cc= MSd, rtio)A{p-sdsdccbh_arr[cin++]0tmbhLY-E c		} S_HWo{p-sdedeeou12B,_bufft
(bhm;p-ssdsddmark_bufft
ldirtySbhm;p-s	 cc}--s,cccpageodirty tm0LY-E cc}--s,c} S_HWo-2.4d, rtio)A{p-sdsd= MSbufft
luptou]eg(bhm &&p-sdc	llll_test__4/_s6e_bit(BH_Lem , &bh->b_s, re))A{p-sdsdcbh_arr[cin++]0tmbhLY-E c	cpageodirty tm0LY-E cc}--s,c}c-o,} -6} whilea(offs6ef+= len, pooffs6ef+= len,c-o,((bh0tmbh->b_OHdo_page) != occH//oc- - = MSuptou]eg && bh0t= occH/c-o,SetPageUptou]eg(page)oc- - = MSd, rtio)
-sdx= osubmit_page(page, bh_arr,icnt/_b-m-sifMSiomp)
-sdx= ocluster_w    (inodh, page->indIx +d1, iomp, d, rtio, unmappe );c-
-c, dirtypageodirty;c-
--rror:p-smp_ (if=,0; i0< cin; i++)A{p-sdou12B,_bufft
(bh_arr[i]m;p-s}c-I-E/*
-	f* Ifd/t's0dela2_HW0andAwe7igafRnowherep	sbpue im,
-	f* throw(it away, unless OHeAlowerAlayerop	sl 
-	f* us fnA ryRagain.d-pe*/m-sif (err0!=y-EAGAIN)A{p-sdif (!unmappe )b{p-sdcb12B,_flushpage(page, 0m;p-s	}c-s	ClearPageUptou]eg(page)oc- }c-	r6eirt err;c-} -
-STATIC il p-hinv= og6e_b12B,_cor (e-,d,* Ok,inodh		*inodh,I-Elong			ib12B,,e-,d,* Ok,bufft
loccH	*bh_resule,e-,_ar	,	ce Seg,e-,_ar	,	direce,e-,bmapi..c ls_t		.c ls/t-{I-Evnodh_t			*vp>= LINVy %GET_VP(inodh)2.-sx= oiomap.t		iomap;m- _ar	,	r6epbbm =,1;p-s_ar	,	-rror;c-odenit.t			snit;p-sloff_t		,offs6ef=,(loff_t)ib12B,0<< inodh->ioblkbitsoc-
-s/* Ih wu>aru doiig0w    s 0SiOHeAendA_PrOH uB->s,
-	f* a2_HW]egfiinchunksd-pe*/m-sif (ce Segl&& (offs6ef>= i6snitne SISinodh)obesy&& ! .c ls & BMAPI_SYNC)e*/)
-sd are = 10<< Xy %WRITE_IO_LOG;e-,e_HWt-/e are = 10<< inodh->ioblkbitsoc-
-sVOP_BMAP(vp, offs6e, dare,t-/ece Segl? .c ls : BMAPI_READ, &iomap, &r6epbbm, errorV;p-s= MSerrorVt-/e, dirty-error;c-p-s= MSr6epbbm ==,0ot-/e, dirty0;.-p-s= MSiomap.iomap.bn != IOMAP_DADDR_ct a/A{p-sdx= odaddr_t 	bn2.-ssloff_t		,delta2.---s,/*,Forrunw   mou0- mSnts doA_typr port a disk,addressA_u
-sdl* t e e SIucase (te Se as.ih wu're e SIiigd/fOo a hole).p-sdl*/c-	E= MSce Segl||s_Siomap.iomap..c ls & IOMAP_UNWRITTENs)b{p-sdcdeltaf=,offs6ef- iomap.iomap.offs6e;m- 	 deltaf>>= inodh->ioblkbitsoc-
-s	 bu0tmiomap.iomap.bn >> (inodh->ioblkbits - BBSHIFTm;p-s		bu0+= delta2.-p-s		bh_resule->b_bhem nr = bn;p-s		s6e_bufft
lmappe (bh_resulem;p-s	}c-s	if (ce Segl&& (iomap.iomap..c ls & IOMAP_UNWRITTENs)b{p-sdcs6e_bufft
lunw   mou(bh_resulem;p-s	cs6e_bufft
ldelay(bh_resulem;p-s	}c-s}c-
-s/* Ih OHdondona e SlbtchuB->s, d]ea mighttbe SF a amw,device2*/m- bh_resule->b_dev0tmiomap.iomap., rget->pbr_kdev; -
-s/* Ih wu>previously a2_HW]eg< a b12B,0out beyond eif( n 
-	f* wu>aru now(comiigdbaB, Oo use im-OH uiwe7willi_mA|tto
-	f* .c l,ie as.amw,kvein(++im-haona disk,address.d-pe*/m-sif (ce Segl&&
-sllll(S!bufft
lmappe (bh_resuleml&& !bufft
luptou]eg(bh_resulem) ||p-s llll(offs6ef>= i6snitne SISinodh)o)/A{p-sdd6e_bufft
lamw(bh_resulem;p-s}.-p-s= MSiomap.iomap..c ls & IOMAP_DELAY)A{p-sdif (uolokely direcem)p-sdcBUG(m;p-sc= MSce Seg)b{p-sdcs6e_bufft
lmappe (bh_resulem;p-s	}c-s	s6e_bufft
ldelay(bh_resulem;p-s}b-
-	, dirt 0;b-} -
-il p-hinv= og6e_b12B,(e-,d,* Ok,inodh		*inodh,I-Elong			ib12B,,e-,d,* Ok,bufft
loccH	*bh_resule,e-,_ar	,	ce Seg/t-{I-E, dirt hinv= og6e_b12B,_cor (inodh, ib12B,, bh_resule,e-,		,	ce Seg,,0, BMAPI_WRITEV;p-}
---STATIC il p-hinv= og6e_b12B,_sync(e-,d,* Ok,inodh		*inodh,I-Elong			ib12B,,e-,d,* Ok,bufft
loccH	*bh_resule,e-,_ar	,	ce Seg/t-{I-E, dirt hinv= og6e_b12B,_cor (inodh, ib12B,, bh_resule,e-,		,	ce Seg,,0, BMAPI_SYNC|BMAPI_WRITEV;p-}
---STATIC il p-hinv= og6e_b12B,_direce(e-,d,* Ok,inodh		*inodh,I-Elong			ib12B,,e-,d,* Ok,bufft
loccH	*bh_resule,e-,_ar	,	ce Seg/t-{I-E, dirt hinv= og6e_b12B,_cor (inodh, ib12B,, bh_resule,e-,		,	ce Seg,,1, BMAPI_WRITE|BMAPI_DIRECT);p-}
---STATIC il p-hinv= obmap(e-,d,* Ok,address_space	*mappiig,e-,long			bhem /t-{I-E ,* Ok,inodh		*inodhf=,(d,* Ok,inodh *)mappiig->host;I-Evnodh_t			*vp>= LINVy %GET_VP(inodh)2.-s_ar	,	error; -
-svn_+face_al ry(vp, "hinv= obmap", (inst_tr*)__, dirt_address)oc-
-sVOP_RW1+af(vp, VRW1+af_READV;p-sVOP_FLUSH_fsinS(vp, (x= ooff_t)0, -1, 0, FI_REMAPF, errorV;p-sVOP_RWUN1+af(vp, VRW1+af_READV;p-s, dirt g +26ic_b12B,_bmap(mappiig,ib12B,, hinv= og6e_b12B,_direce);p-}
---STATIC il p-hinv= oe SIpage(e-,d,* Ok,B->s		*unusBd,I-Ed,* Ok,page		*page/t-{I-E, dirt b12B,_e SI_.ullopage(page, hinv= og6e_b12B,);p-}
---STATIC 
-		
-x= oc*/in_pageod, re(I-Ed,* Ok,page		*page,e-,_ar	,	*dela2_HW,e-,_ar	,	*unmappe ,e-,_ar	,	*unw   mou/m-{I-Ed,* Ok,bufft
loccH	*bh, *occHLY-p-s*dela2_HW0tm*unmappe 0tm*unw   mouf=,0;.-p-sbh0tmoccHf=,pageobufft
sSpageoLY-EdoA{p-sd= MSbufft
luptou]eg(bhm && !bufft
lmappe (bhm/e-,		(*unmappe )b=,1;p-sdS_HWo-2.4bufft
lunw   mou(bhml&& !bufft
ldelay(bhm)e-,		clear_bufft
lunw   mou(bhm;p-sdS_HWo-2.4bufft
lunw   mou(bhm/e-,		(*unw   mou/b=,1;p-sdS_HWo-2.4bufft
ldelay(bhm)e-,		(*dela2_HW/b=,1;p-s} whilea((bh0tmbh->b_OHdo_page) != occH/oc-}b-p-
-4-
-68,w    page:,CV_.e 0mverStre0_PrOwo places:
- -
-68,1. wu>aru flushiigdaSdela2_HW0bufft
,ocad.
- -
-68,2. wu>aru w   iigdSut_a dirty page. TypicallyrOH upage dirty
-68,,,,d, re donclearBdpbeforepwu>46efhere. In2OHdoncase dondt
-68,,,,conceivab.cfwe7igafRno0bufft
,ocads.
- -
-68,Forrdela2_HW0space	on2OH upageAwe,amA|tto(a2_HW]egfspace	 n 
-f* .cush it.,Forrunmappe 0bufft
,ocads	on2OH upageAwe,deGuld
-68,a2_HW]egfspace	_PrOH upage is uptou]eg. Forr nySoOH rndirty
-68,bufft
,ocads	on2OH upageAwe,deGuld .cush OH m.
- -
-68,Ih wu>detecn0b 0Sia +fansa_SISF wGuldAbenrequirA|tto(.cushp-f* b   page, we7igafROoScheB, Ohe trocessA.c ls first,.ih wu
-68,arep _e SIy iin3 +fansa_SISF Sr disk,I/Ofduriigda2_HW]eISFs
- syis _Pf,Awe,amA|tto(fai. b/epw    page0andA16dUrtyrOH upage.
-e*/m---STATIC il p-hinv= ow    page(I-Ed,* Ok,page		*page/m-{I-E_ar	,	-rror;c-o_ar	,	amA|o+fans;c-o_ar	,	dela2_HW, unmappe , unw   mou;I-E ,* Ok,inodh		*inodhf=,page->mappiig->host;I-Ex= op.c ls_t		p.c ls;.-p-sx= opageo+face(Xy %WRITEfsin_ENTER,,inodh, page, 0soc- - /*
-	f* We,amA|t3 +fansa_SISF if:
-	f* ,1. Thereparu dela2_HW0bufft
s	on2OH upage
-	f* ,2. Theupage is uptou]eg0andAwe7igafRunmappe 0bufft
s
-	f*  3. Theupage is uptou]eg0andAwe7igafRno0bufft
s
-	f*  4. Thereparu unw   mou0bufft
s	on2OH upage
-	f*/m-b-s(++ _pageoha obufft
sSpageo)ode-, unmappe 0tm1;p-sdamA|o+fansb=,1;p-s} S_HWo{p-sdx= oc*/in_pageod, re(page, &dela2_HW, &unmappe , &unw   mou/;c-sdif (!PageUptou]eg(page))e-,		unmappe 0tm0;p-sdamA|o+fansb=,dela2_HW0+Runmappe 0+ unw   mou;I-E}c-I-E/*
-	f* Ifdwe,amA|t3 +fansa_SISF andAOH  trocessA.c ls say
-	f* wu>aru  _e SIy iin3 +fansa_SISF, orrno0IOndona2_Hwe 
-	f* OH uimarkrOH upage dirty again andAlegafROH upage
-	f* as.is.d-pe*/m-b-s(++ (PFLAGS_TEST_FSTRANS(m || PFLAGS_TEST_NOIO(mml&& amA|o+fans)e-,	g fnASut_fai.oc- - /*
-	f* Delay hookiigdup,bufft
,ocads	/ini. we7igaf
-	f* made our go/no-go,decisISF.p-se*/m-sif (_pageoha obufft
sSpageo)t-/ece Seg_(mptyobufft
sSpage, inodh->iodev, 10<< inodh->ioblkbitssoc- - /*
-	f* Convert delaye ,a2_HW]eg, unw   mou0orrunmappe 0space
-	f* Oo e Slfspace	 n  .cush out ro disk.p-se*/m-sif (amA|o+fans)e-,	PFLAGS_SET_NOIO(&p.c ls/;c-serror0t x= opageod, re_convert(inodh, page, 1, unmappe );c-oif (amA|o+fans)e-,	PFLAGS_RESTORE(&p.c ls/;c-s= MSerror ==,-EAGAIN)e-,	g fnASut_fai.oc- - if (uolokely error < 0s)A{p-sdou12B,_page(pageoLY-E	r6eirt error;c-o}b-
-	, dirt 0;b-
-Sut_fai.:
-	SetPageDirtySpageo;c-oou12B,_page(pageoLY-E, dirt 0;b-} -
-4-
-68,CV_.A|tto(move(  tage /fOo cleanab.cfd, re -	 n  .verSOH re
-68,to(b ureleas d. PossiblyrOH upage is  _e SIy clean. We,always
- syigafRbufft
,ocads	in2OHdonca2_.
-e*
- syRedirts 0	_PrOH upage is ok Oo e leas , 10oOH rwise.
-e*
- syPossiblcfdcenarios>aru:
- -
-68,1. We7aru beiigdcV_.A|tto(releas u  tage which-haonbeou0w   mou
-68,,,,to(via e gular,I/O.Rbufft
,ocads	willibeAdirty andApossibly
-68,,,,dela2_HW. IfdnoSdela2_HW0bufft
,ocads	in2OHdoncase-OH uiwe
-68,,,,can justi, dirt zero.
- -
-68,2. We7aru cV_.A|tto(releas u  tage which-haonbeou0w   mou(via
-68,,,,mmap,  _. we,amA|tto(doAdon-nsureSOH re donnoSdela2_HW
-68,,,,d, re dn2OH ubufft
,ocads,n(++_tyiwe7-30 l6efb/epcV_.Ar
-68,,,,d/ho(OH m0andAwe7deGuld comeAbaB, later via w    page.
- -/--STATIC il p-hinv= oe leas _page(e-,d,* Ok,page		*page,e-,_ar	,	gfp_read)t-{I-E ,* Ok,inodh		*inodhf=,page->mappiig->host;I-E_ar	,	dirty, dela2_HW, unmappe , unw   mou;I-p-sx= opageo+face(Xy %RELEASEfsin_ENTER,,inodh, page, gfp_read);I-p-sx= oc*/in_pageod, re(page, &dela2_HW, &unmappe , &unw   mou/;c-sif (_dela2_HW0&& !unw   mou/m-E	r6eirt 1_b-p-s= MS!(gfp_read & __GFP_FS)ot-/e, dirty0;.-p-s/* Ih wu>aru  _e SIy iisidh a +fansa_SISF Sr OH uche SIucan_ty
-	f* doAI/O,iwe7-30_typr leas uOHdontage.p-se*/m-sif (PFLAGS_TEST_FSTRANS(m || PFLAGS_TEST_NOIO(mmt-/e, dirty0;.-p-s/*
-	f* Convert dela2_HW0space	Oo e Slfspace, doA_typ.cush OH 
-	f* d]ea out ro disk,0b 0SiwillibeAdtre0byrOH ucV_.Ar.p-se* Nkver,amA|tto(a2_HW]egfspace	H re -iwe7willialways
-	f* comedbaB, Oo w    page0dn2OHatAcase.
-se*/m-sdirty tmx= opageod, re_convert(inodh, page, 0,O0V;p-s, dirty(dirty ttm00&& !unw   mou/ ? 10: 0;b-} -
-STATIC il p-hinv= opr pare_w    (e-,d,* Ok,B->s		*B->s,
-	d,* Ok,page		*page,e-,unsigtod _ar	,.ver,e-,unsigtod _ar	,to/m-{I-E_++ .ilea&& (.ile->f..c ls & O_SYNC)s0{t-/e, dirtybhem _pr pare_w    (page, .ver, Oo,e-,,,,,,hinv= og6e_b12B,_syncm;p-s} S_HWo{p-sd, dirtybhem _pr pare_w    (page, .ver, Oo,e-,,,,,,hinv= og6e_b12B,moc-	}Y-}
---4-
-68,In04iatepI/OfSF a ksobuf0_Pruser,memory
- -/--STATIC il p-hinv= odirece_IO(I-E_ar	,	rw,I-Ed,* Ok,inodh		*inodh,I-Ed,* Ok,ksobuf		*iobuf,I-Eunsigtod long		bhem nr,e-,_ar	,	bhem snit)t-{I-Ed,* Ok,page		**maplist;I-Ednit.t			pageooffs6e;m- pageobuf_t		*pb2.-sx= oiomap.t		iomap;m- _ar	,	error0t 0;.-d_ar	,	pb_.c ls,,map..c ls,mpg_dndIxf=,0;.-ddnit.t			lengnv, total;c-sloff_t		,offs6e, map.snit;p-senit.t			snit;p-svnodh_t			*vp>= LINVy %GET_VP(inodh)2.-p-s/* Notn -	 lnvoughb l-2iomap c*/ldAigafRa 64-bitBdare,t-/68,ksobuf->lengnv2ireonly 30 _ar, ssb l-2min(map.snit,tlengnv)
-	f* Oestnwillikeep us mverStverf_Hwiig0OH upagebuf0enit.t0enit.
-se*/m-stotal0tmlengnv2tmiobuf->lengnv;p-soffs6ef=,bhem nr;p-soffs6ef<<= inodh->ioblkbitsoc-
-smaplist2tmiobuf->maplist;I-Epageooffs6e2tmiobuf->offs6eu - - map..c ls = (rw ? BMAPI_WRITE : BMAPI_READm |tBMAPI_DIRECT;I-Epb..c ls = (rw ? PBF_WRITE : PBF_READm |tPBF_FORCEIOn|tPBF_DIRECTIO;p-swhilea(lengnv)o{p-sderror0t x= omap_bhem s(inodh, offs6e, lengnv, &iomap, map..c ls/;c-sdif (errorVt-/e	be Sk;p-sdBUG_ON4iomap.iomap..c ls & IOMAP_DELAY)2.-p-s	map.snit0tmiomap.iomap.bsnit0- iomap.iomap.delta2.-se are = (enit.t)min(map.snit,t(loff_t)lengnv);c-c-	E= MS4iomap.iomap..c ls & IOMAP_HOLEm ||p-sdllllS4iomap.iomap..c ls & IOMAP_UNWRITTENsa&& rw ttmREADm)b{p-sdcsnit.t	zero_lou0tmsnit;p-p-sds= MSrw ttmWRITEVe-,,,,be Sk;p-e-,,,/* NmA|tto(zero,ie alli*/p-sdswhilea(zero_lou)A{p-sdc s,* Ok,page	*page;p-sdc snit.t		pg_lou;I-p-s			pg_lou0tmmin((enit.t)e-,,,,,,(fsin_CACHE_SIZEf- pageooffs6e),e-,,,,,,zero_lou);I-p-s			page =rmaplist[pg_dndIx];I-p-s			mems6e(kmap(page) + pageooffs6e, 0,Opg_loum;p-s	 c.cush_dcOt_e_page(pageoLY-E			kunmap(page)oc- - ,,,zero_louf-= pg_lou;I-sdsd= MS(pg_lou0+ pageooffs6es0t=tfsin_CACHE_SIZE/A{p-sdsdcpg_dndIx++9--s,			pageooffs6e tm0LY-E cc} S_HWo{p-sdedepageooffs6e tm(pageooffs6e +Opg_loum &p-sdc				~fsin_CACHE_MASKLY-E cc}
-s,c}c-o,} S_HWo{p-sde_ar	pg_c*/inoc- - ,,pg_c*/in = (enit0+ pageooffs6e + fsin_CACHE_SIZEf- 1)p-sdc		>> fsin_CACHE_SHIFT; -  d= MS(pb = pagebuf_lookup(iomap.iomap., rget, offs6e,e-,,,,,,snit,tpb..c ls)s0t=tct a/A{p-sdsderror0t -ENOMEM;e-,,,,be Sk;p- cc}
-s,c/* NmA|tto(hookdup,pagebuf0to(ksobuf0pagesi*/p-sdspb->pb_pagesi= &maplist[pg_dndIx];I-sdspb->pb_offs6ef=,page.offs6e;m- 	 pb->pb_page_c*/in = pg_c*/inoc- 	 pb->pb_bu0tmiomap.iomap.bn +MSiomap.iomap.deltaf>> BBSHIFTm;p-c- 	 error0t pagebuf_iod, rt(pb, pb..c ls); -  d= MS!error0&& (iomap.iomap..c ls & IOMAP_UNWRITTENs)b{p-sdcsVOP_BMAP(vp, Xy %BUF_OFFSET(pb),e-,,,,,Xy %BUF_SIZE(pb),e-,,,,,BMAPI_UNWRITTENROct a, dpst, errorV;p-ssd}m-
-  Epagebuf_r le(pb); - -  d= MSerrorVA{p-sdsd= MSerror0>,0ot-/edsderror0t --rror;c-o, cbe Sk;p- cc}
-
-  Epageooffs6e tm(pageooffs6e +Osnit) & ~fsin_CACHE_MASKLY-E c= MSpageooffs6e/t-sdc	pg_c*/in--; - ,,pg_indIx += pg_c*/inoc- 	}
-
-  offs6ef+= snit;p-s	lengnv2-= snit;p-s}b-
-	, dirt Serror0? error : (_ar-(total0-tlengnv)/oc-}b-p-
-d,* Ok,address_space_oper]eISFs hinv= oaops0tm{p-s.e SIpage		= hinv= oe SIpage,e-,.w    page		= hinv= ow    page,e-,.sync_page		= b12B,_sync_page,e-,.r leas page		= hinv= oe leas _page,e-,.pr pare_w    		= hinv= opr pare_w    ,e-,.commit_w    		= g +26ic_commit_w    ,e-,.bmap			= hinv= obmap,e-,.direce_IO		= hinv= odirece_IO,e-};
diff -Naur -p -X /home/marcelo/lib/dtrtdiff }
-		-2.4.26/fs/x= /}
-		ex= obuf.c }
-		-2.4.27-rc4/fs/x= /}
-		ex= obuf.c
--- }
-		-2.4.26/fs/x= /}
-		ex= obuf.c	2004-04-14 13:05:40.000000000 +0000
+++ }
-		-2.4.27-rc4/fs/x= /}
-		ex= obuf.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,2308 +0,0 @@--4-
-68,Copyrightt(c) 2000-2004 Silicon Graphics,mInc. ,A2_ Rights Reserved.
- -
-68,THdontrogram2ired/ho(software; youn-30 16distribu   itBand/p_ modifyndt
-68,undIS_OH  Oerms _PrversISF 2A_PrOH uGNU G +26al0Public Licens u s
- sypublish
 }byrOHe F/ho(Software FpundaSISF.p- -
-68,THdontrogram2iredistribu  d dn2OH uhope2OHatAit wGuldAbenuseful,Abuk
-68,WITHOUT ANY WARRANTY;nwinvoutBeveinOHeAimpliBd warrantyS_P
-68,MERCHANTABILITY Sr FITNESS FOR A fsRTICULAR PURPOSE.
- -
-68,FurOH r, OHdonsoftware2iredistribu  d winvoutB nySwarrantySOHatAit iop-f* d/ho(_PrOH urightful _Haim if( nyrOHdrd perso0 16garIiigd/ffriigemSntd-f* oS_OH  loke. ,Anyrlicens utrovid d H rein, wheOH rnimpliBd orp-f* oOH rwise, appliBs only 	sb ldonsoftware2.ile. ,PamSnt licens s,n(+
-68,any,utrovid d H rein doA_typapplyefnAcombin]eISFs oh OHdontrogram2winvp-f* oOH rnsoftware, orr nySoOH rntrod Ok,wHatsokver.
- -
-68,YoundeGuld igafRreceivA|t3 copyA_PrOH uGNU G +26al0Public Licens u long
-68,winv2OHdontrogram;n(++_ty,(w     OH uF/ho(Software FpundaSISF,mInc., 59
-68,Temple Place0-tSu    330, Bod,o0 MA 02111-1307, USA.
- -
-68,ConnaOk,informaSISF: Silicon Graphics,mInc., 1600 AmphiOH atre Pkwy,
- syM*/inain View, CA  94043, or:
- -
-68,http://www.sgi.com
- -
-68,ForrfurOH r,informaSISF 16garIiigdOHdon_tyice, see:
- -
-68,http://oss.sgi.com/trojeces/G +Info/SGIGPLNtyiceExplan/
-e*/m---4-
-68 pageobuf.c
- -
-68	Theupageobuf modul utrovid s an,abs+fact bufft
 cOt_e model	on2OopS_P
-68	OH uL
-		upageAcat_e. ,COt_ed metad]ea bhem sfBorraSB->sedystem are
-68	hash
 }	sb l-2inodh mp_ OHeAb12B,0device. ,Theupageobuf modul 
-68	assBmbles
bufft
  pageobuf_t) objeces	on2demandAOo agg16gaegfsucvp-f*	cOt_ed pagesimp_ I/O.
- -
-68
-68,,,, yW   mou0by Stkve Lord, Jim Mod,ek, RussB2_ Cattelanp-f*	dllllandARajagopal0Ananthanarayanat S"ananth") 0SiSGI.
- -
-68/m---#includh <}
-		estddef.h>--#includh <}
-		eerrno.h>--#includh <}
-		eslab.h>--#includh <}
-		epagemap.h>--#includh <}
-		ein04.h>--#includh <}
-		evma2_HW.h>--#includh <}
-		eblkdev.h>--#includh <}
-		ehem s.h>--#includh <}
-		esysctl.h>--#includh <}
-		eproc_fs.h>----#includh "x= o}
-		.h"----# /home BN_ALIGN_MASK	((10<< (fsin_CACHE_SHIFT - BBSHIFTm)f- 1)p---#ifndIf GFP_READAHEAD--# /home GFP_READAHEAD	0--#end(+
---4-
-68,AdbaB,port _PrOH u2.5 st_edul r is us
 }byrm nySveidors oh 2.4-bas d
-68,distribu ISFs.
-68,Wen-30 only guessA/t's0pr setc s}byrOHe laB, _PrOH uSCHED_YIELDA.c l.
-68,Ih OH uheuristic doeon'O0work, changedOHdon /home byrhand.
- -/--#ifndIf SCHED_YIELD--# /home __HAVE_NEW_SCHEDULER	1--#end(+
---4-
-68,cpuread_t is us
 }mp_ supportiigdNR_CPUS0>,BITS_PER_LONG.
-68,Ih support mp_ OHdondonpr sete, migrate_to_cpu exists andAprovid s
-68,a(w apper arpund0OH uset_cpu oa2_Hwe  rputiie.
- -/--#ifdIf copy_cpuread--# /home __HAVE_CPUMASK_T	1--#end(+
---#ifndIf __HAVE_CPUMASK_T--# ifndIf __HAVE_NEW_SCHEDULER--# n /home migrate_to_cpu(cpu)	\
-EdoA{mcurrete->cpu oa2_Hwe  = 1UL0<< (cpu); } whilea(0ot-#IS_HWt-# n /home migrate_to_cpu(cpu)	\
-Eset_cpu oa2_Hwe (currete, 1UL0<< (cpu)ot-#ISnd(+
-#end(+
---4-
-68,Fileawidh globals
-e*/m---STATIC kmem_cOt_e_t *pagebuf_cOt_e;----# /home MAX_IO_DAEMONS		NR_CPUS--# /home CPU_TO_DAEMON(cpu)	(cpu)--STATIC il  pb.logio_daemSFs[MAX_IO_DAEMONS];I-STATIC e,* Ok,listloccH pagebuf_logiostre_tq[MAX_IO_DAEMONS];I-STATIC wait_queueloccH_t pagebuf_logiostre_wait[MAX_IO_DAEMONS];I-STATIC il  pb.d]eaio_daemSFs[MAX_IO_DAEMONS];I-STATIC e,* Ok,listloccH pagebuf_d]eaiostre_tq[MAX_IO_DAEMONS];I-STATIC wait_queueloccH_t pagebuf_d]eaiostre_wait[MAX_IO_DAEMONS];I---4-
-68,Fp_ pre-a2_HW]eg< bufft
,ocad pool
-68/m---# /home NR_RESERVED_BH	64
-d,atic wait_queueloccH_tEpb.r sv_bh_wait;
-d,atic spiu12B,_t	Epb.r sv_bh_12B,0= SPIN_1+af_UN1+afED;
-d,* Ok,bufft
loccH		*pb.r sv_bh:r ct afc/* list2_Prbv2*/m-_ar	,	Epb.r sv_bh_cinf=,0fc/* #2_Prbv2availab.cf*/m---STATIC ead( pagebuf_d]emSF_wakeup(ead();--STATIC ead( _pagebuf_ioapply pageobuf_t *);--STATIC ead( pagebuf_delw  _queue pageobuf_t *,,int);--STATIC ead( pagebuf_runa2__queues(e,* Ok,listloccH[]);I---4-
-68,Pagebuf0debugging
-68/m---#ifdIf fsinBUF_TRACE
-
-		
-pagebuf_+face(m- pageobuf_t	*pb,e-,char		*id,e-,tic 		*d]ea,e-,tic 		*ra)t-{I-Ek+face_al er(pagebuf_+face_buf,I-E	pb, id,e-,	(ead( *)(unsigtod long)pb->pb_.c ls,e-,	(ead( *)(unsigtod long)pb->pb_hold.c*/iner,e-,	(ead( *)(unsigtod long)pb->pb_sBma.c*/in.c*/iner,e-,	(ead( *)currete,e-,	d]ea, ra,e-,	(ead( *)(unsigtod long)S(pb->pb_.ile_offs6e>>32) & 0xffffffff),e-,	(ead( *)(unsigtod long)Spb->pb_.ile_offs6e & 0xffffffff),e-,	(ead( *)(unsigtod long)pb->pb_bufft
lhengnv,e-,	ct a, dpst, dpst, dpst, dpst/oc-}b-k+face_t *pagebuf_+face_buf;--# /home fsinBUF_TRACE_SIZE	4096--# /home fB_TRACE(pb, id, d]ea)	\
-Epagebuf_+face(pb, id, (ead( *)d]ea, (ead( *)__builtii_, dirt_address(0oot-#S_HWt-# /home fB_TRACE(pb, id, d]ea)	doA{m} whilea(0ot-#end(+
---#ifdIf fsinBUF_1+af_TRACKINGt-#I /home fB_SET_OWNER(pb)	S(pb)->pb_last_holder0t currete->pid)t-#I /home fB_CLEAR_OWNER(pb)	S(pb)->pb_last_holder0t -1)t-#I /home fB_GET_OWNER(pb)	S(pb)->pb_last_holderot-#S_HWt-#I /home fB_SET_OWNER(pb)	doA{m} whilea(0ot-#I /home fB_CLEAR_OWNER(pb)	doA{m} whilea(0ot-#I /home fB_GET_OWNER(pb)	doA{m} whilea(0ot-#end(+
---4-
-68,Pagebuf0a2_HW]eISF / d/hoiig.
-68/m---# /home pb_to_gfp .c ls) \
-E(( .c ls) & PBF_READ_AHEAD/ ? GFP_READAHEAD : \
-E ( .c ls) & PBF_DONT_B1+af/ ? GFP_NOFS : GFP_KERNEL)m---# /home pb_to_km .c ls) \
-E (( .c ls) & PBF_DONT_B1+af/ ? KM_NOFS : KM_SLEEP)b-p-
-# /home pagebuf_a2_HW]eg .c ls) \
-Ekmem_ztre_a2_HW(pagebuf_cOt_e, pb_to_km .c ls))
-# /home pagebuf_dea2_HW]eg pb) \
-Ekmem_ztre_d/ho(pagebuf_cOt_e,  pb));I---4-
-68,Pagebuf0hashing
-68/m---# /home NBITS	8--# /home NHASH	(1<<NBITS)b-p-typedIf e,* Ok,{I-Ed,* Ok,listloccHEpb.hash;p-sepiu12B,_t	Epb.hash_12B,oc-} pb.hash_noc- -STATIC pb.hash_nEpbhash[NHASH];--# /home pb_hash(pb)	&pbhash[pb->pb_hash_dndIx] -
-STATIC il p-_bhash(e-,d,* Ok,b12B,_device2*bdev,c-sloff_t		bas /m-{I-E_ar	,bie, hva.oc- - bas f>>= 9; - bas f^= (unsigtod long)bdev / L1_CACHE_BYTES; - mp_ (bitB= hva.f=,0; bas f&& bief< snitof(bas /68,8; bief+= NBITSVA{p-sdhva.f^= (int)bas f& (NHASH-1V;p-s bas f>>= NBITS;p-s}b-	, dirt hva.oc-}
---4-
-68,Mappiigd_Prmulti-page0bufft
s	/fOo conniguous virtuSlfspace
-e*/m---STATIC ead( *pagebuf_mapSut_hem ed(pageobuf_t *);--p-typedIf e,* Ok,a_list2{e-,tic 		*vm_addr;e-,d,* Ok,a_list	*amxkoc-} a_list_noc- -STATIC a_list_n		*as_d/ho_occHLY-STATIC il 		as_list_lou;I-STATIC epiu12B,_t	as_l2B,0= SPIN_1+af_UN1+afED;
---4-
-68,TryefnAbatch vunmaponbecause-OH y7aru costly.d-e*/m-STATIC 
-		
-d/ho_address(e-,tic 		*addr/m-{I-Ea_list_n	*aal ryoc- - aal ry0= kma2_HW(snitof(a_list_n), GFP_ATOMIC/;c-sif (aal ry/A{p-sddpiu_l2B,(&as_l2B,V;p-s aal ry->amxk,= as_d/ho_occHLY-s aal ry->vm_addr,= addr;e-,	as_d/ho_occH,= aal ryoc-		as_list_lou++9--s,dpiu_ou12B,(&as_l2B,V;p-s} S_HWo{p-sdvunmap(addr/oc-	}Y-}
---STATIC 
-		
-purgo_addresses(ead()m-{I-Ea_list_n	*aal ry, *old_b-p-s= MSas_d/ho_occH,==tct a/
-sd, dirt_b-p-sdpiu_l2B,(&as_l2B,V;p-saal ry0= as_d/ho_occHLY-sas_d/ho_occH,= ct aff-	as_list_louf=,0;.-ddpiu_ou12B,(&as_l2B,V;p-
-swhilea((old,= aal ry) != ct a/A{p-sdvunmap(aal ry->vm_addrV;p-s aal ry,= aal ry->amxk;p-s kd/ho(oldmoc-	}Y-}
---4-
-68	Iinernal pagebuf0_bjecerm nipulaSISF
-e*/m---STATIC ead(p-_pagebuf_in04ialnit(m- pageobuf_t		*pb,e-,pb_t rget.t		*t rget,c-sloff_t			range_bas ,I-Ednit.t			range_hengnv,e-,pageobuf_.c ls_t	.c ls/t-{I-E/*
-	f* We,don'O0wain0cernain .c ls Oo appearriinpb->pb_.c ls.
-se*/m-s.c ls &= ~(PBF_1+af|PBF_MAPPED|PBF_DONT_B1+af|PBF_READ_AHEAD/u - - mems6e(pb, 0, snitof(pageobuf_t)V;p-satomicns6e(&pb->pb_hold,O1V;p-sin04_MUTEX_1+afED(&pb->pb_iostresBmaV;p-sINIT_LIST_HEAD(&pb->pb_listV;p-sINIT_LIST_HEAD(&pb->pb_hash_1istV;p-sin04_MUTEX_1+afED(&pb->pb_sBmaV;besyheld,Ono waitt
s	*/m-sfB_SET_OWNER(pb);I-Epb->pb_t rget,= t rget;I-Epb->pb_.ile_offs6e = range_bas ;I-E/*
-	f* S6efbufft
lhengnv andAc*/in_desirA|tto(OH usameAvalueRin04ially.p-se* IO rputiiesndeGuld use-c*/in_desirA|, which-willibeAOH usameAiu
-	f* most casesAbuk,may b ures6e (e.g. Xy Rrectvery).
-se*/m-spb->pb_bufft
lhengnv0t pb->pb_c*/in_desirA|t= range_lengnv;p-spb->pb_.c lst= .c lst|tPBF_NONE;p-spb->pb_bu0tmfsin_BUF_DADDR_ct a;p-satomicns6e(&pb->pb_piu_c*/in,O0V;p-s=n04_waitqueueloccH(&pb->pb_waitt
s/u - - Xy %STATS_INC(pb_ce Seg/;m-sfB_TRACE(pb, "in04ialnit", t rgetoLY-}
---4-
-68,A2_HW]egf  tage array capab.cf_PrholdiigdaSspecifiBd numbt
p-f* of0pages, andApoinSiOHeApage buf0at it.d- -/--STATIC il p-_pagebuf_get.pages(m- pageobuf_t		*pb,e-,_ar	,	pageoc*/in,e-,pageobuf_.c ls_t	.c ls/t-{I-E/*,Makgfsure t 0Siwe7igaff  tage list2*/m-sif (pb->pb_pagesi== ct a/A{p-sdpb->pb_offs6ef=,page.buf_poffSpb->pb_.ile_offs6eV;p-s pb->pb_page_c*/in = page_c*/in;c-sdif (page_c*/in <= fB_fsinS)A{p-sdcpb->pb_pagesi= pb->pb_page_arrayoc- 	} S_HWo{p-sdepb->pb_pagesi= kmem_a2_HW(snitof(s,* Ok,page *) *p-sdsd	pageoc*/in, pb_to_km .c ls))LY-E c= MSpb->pb_pagesi== ct a/p-sdsd, dirty-ENOMEM;e-,,}
-s,mems6e(pb->pb_pages, 0, snitof(s,* Ok,page *) * page_c*/in)oc- }c-	r6eirt 0;b-} -
-4-
-68,Walkf  tagebuf0e leasiigda2_iOHeApages connaomed,winvin it.d- -/--STATIC illome ead(p-_pagebuf_d/hopages(m- pageobuf_t		*pb/m-{I-E_ar	,	buf_indIx; - - mp_ (buf_indIxf=,0; buf_indIxf< pb->pb_page_c*/in; buf_indIx++)A{p-sds,* Ok,page	*pagei= pb->pb_pages[buf_indIx];I-p-s	= MSpage) {p-sdcpb->pb_pages[buf_indIx],= ct aff-	d	pageocOt_e_e leas (pageoLY-E	}c-	}Y-}
---4-
-68	pagebuf_d/ho
- -
-68	pagebuf_d/hopr leas s OHeAspecifiBd bufft
. ,TheumodificaSISF
-e*	d, re if( nyrassoci]eg< pages is left unchanged.
- -/--
-		
-pagebuf_d/ho(m- pageobuf_t		*pb/m-{I-EfB_TRACE(pb, "d/ho",O0V;p-sp-sASSERT(list_(mpty(&pb->pb_hash_1istV)2.-p-s/* releas u nySvirtuSlfmappiig -/ ;m-sif (pb->pb_.c ls & _PBF_ADDR_AL1+CATED/A{p-sdvad( *vaddr,= pagebuf_mapSut_hem ed(pb/;c-sdif (vaddr) {p-sdcd/ho_address(vaddrV;p-s }c-s}c-
-sif (pb->pb_.c ls & _PBF_MEM_AL1+CATED/A{p-sd= MSpb->pb_pages) {p-sdc/* releas uOHeApages dn2OH uaddressAlist2*/m-s d= MS(pb->pb_pages[0])0&&p-sdclll (pb->pb_.c ls & _PBF_MEM_SLABs)b{p-sdcskd/ho(pb->pb_addrV;p-s c} S_HWo{p-sded_pagebuf_d/hopages(pb/;c-sdc}--s,E= MSpb->pb_pagesi!= pb->pb_page_array)p-sdcskd/ho(pb->pb_pages);m- 	 pb->pb_pages,= ct aff-	d}p-s pb->pb_.c ls &= ~(_PBF_MEM_AL1+CATED|_PBF_MEM_SLABs;p-s}b-
-	pagebuf_dea2_HW]eg pb);b-} -
-4-
-68d_pagebuf_lookup_pages
- -
-68	_pagebuf_lookup_pages findona2_Apages which-match OH ubufft

-68	dn2quesSISF andAOH  rangedif(B->seoffs6es suppliBd,
-68	andAbuildsiOHeApage list2mp_ OHeAbufft
,	_PrOH 
-68	page list2don_ty  _e SIy formBd orn(++_tyia2_AofuOHeApages are
-68	 _e SIy iinOH  lost. Inval			pages (pages which-igafRnot y6efbeou
-68	e SIuin .verSdisk)>aru  ssigtod forr nySpages which-aru not mpund.d- -/--STATIC il p-_pagebuf_lookup_pages(m- pageobuf_t		*pb,e-,d,* Ok,address_space	*aspace,e-,pageobuf_.c ls_t	.c ls/t-{I-Eloff_t			amxk_bufft
loffs6e;m- unsigtod longd	pageoc*/in, pi,idndIx;e-,d,* Ok,page		*page;p-s_ar	,	gfp_readi= pb_to_gfp .c ls);p-s_ar	,	a2__mappe , good_pages, rval,i, dries;c-odnit.t			bhem snit2.-p-samxk_bufft
loffs6ei= pb->pb_.ile_offs6e + pb->pb_bufft
lhengnv;c-ogood_pages = page_c*/in tm(pageobuf_btHW(amxk_bufft
loffs6e) - - ,,,   pageobuf_btHWtSpb->pb_.ile_offs6eV/_b-m-sifMSpb->pb_.c ls & _PBF_ALL_fsinS_MAPPED)b{p-sd/* Briigdpagesimp_warIuin cOt_e */m-s mp_ (pif=,0; pi0< page_c*/in; pi++)A{p-sdcmark_page_accessed(pb->pb_pages[pi]m;p-s	} -6d= MS(.c ls & PBF_MAPPEDml&& !Spb->pb_.c ls & PBF_MAPPEDm)A{p-sdca2__mappe 0tm1;p-sd	rva.f=,0;p-sd	g fnAmapit;p-s	} -6dr6eirt 0;b-s}c-
-s/* EnsureSpb_pages,fiBld igonbeou0in04ialns
 }*/m-srva.f=,_pagebuf_get.pages(pb, pageoc*/in, .c ls/;c-s= MSrva.mt-/e, dirtyrva.oc- - a2__mappe 0tm1;p-sbhem sniti= pb->pb_, rget->pbr_bsnit2.-p-s/* EnteruOHeApages dn2OH utage list2*/m-sindIxf=,Spb->pb_.ile_offs6e - pb->pb_offs6e) >> fsin_CACHE_SHIFT; - mp_ (pif=,0; pi0< page_c*/in; pi++,idndIx++)A{p-sd= MSpb->pb_pages[pi] ==,0oA{p-sdcredriesf=,0;p-sd,,,, yredry:f-	d	paget= .indoor_ce Seg_page(aspace,idndIx, gfp_read);I-  d= MS!page) {p-sdcE_++ .c ls & PBF_READ_AHEAD/p-sdsd	, dirty-ENOMEM;e-,,sd/*p-sdsdl*,THdonc*/ldAdeadhem . ,But	/ini. a2_iOHep-sdsdl*,Xy Rlowlevelnc*de2irerevampA|tto(handlep-sdsdl*,bufft
,a2_HW]eISF fai.uresiwe7-30't dop-sdsdl*,much.
-sdsdl*/p-sdsd= MS_(++redriesf% 100))A{p-sdsdcpriitk(KERN_ERRp-sdsdc,,,, y "possiblyAdeadhem iigd/f %s\n",p-sdsdc,,,, y __FUNCTION__)LY-E cc}--s,ccXy %STATS_INC(pb_page_redries)LY-E ccpagebuf_d]emSF_wakeup()LY-E cccurrete->d, re = TASK_UNINTERRUPTIBLELY-E ccst_edul _btchSut(10)LY-E ccg fnAredry;c-sdc}--s,EXy %STATS_INC(pb_page_mpund)LY-E cmark_page_accessed(pageoLY-E		pb->pb_pages[pi] = page;p-s	} S_HWo{p-sdepagei= pb->pb_pages[pi]LY-E		12B,_page(pageoLY-E	}m-
-  /* Ifdwe,amA|tto(doAI/OfSF a pageirectrdAOH  fact */c-	E= MS!Page_Uptou]eg(page))0{p-sd	g od_pages--; - ,,-2.4(bhem sniti==tfsin_CACHE_SIZE/A&&p-sdclll (.c ls & PBF_READ)/t-sdc	pb->pb_lem ed0tm1;p-sd}c-s}c-
-sif (!pb->pb_lem ed)0{p-sdmp_ (pif=,0; pi0< page_c*/in; pi++)A{p-sdc= MSpb->pb_pages[pi]/t-sdc	ou12B,_page(pb->pb_pages[pi]m;p-s	} -6}b-
-	pb->pb_.c ls |= _PBF_fsinCACHE;p-mapit:
-	pb->pb_.c ls |= _PBF_MEM_AL1+CATED;c-sif (a2__mappe /A{p-sdpb->pb_.c ls |= _PBF_ALL_fsinS_MAPPED;m-
-  /* A siigleApage buff r is alwaysfmappab.cf*/m-sdif (page_c*/in ==t1) {p-sdcpb->pb_addr,= (caddr_t/t-sdc	pago_address(pb->pb_pages[0])0+ pb->pb_offs6eLY-E		pb->pb_.c ls |= PBF_MAPPED;p-s	} S_HWo_++ .c ls & PBF_MAPPED)b{p-sds= MSas_list_louf> 64/t-sdc	purgo_addresses(oLY-E		pb->pb_addr,= vmap(pb->pb_pages, pageoc*/in,e-,,,,,VM_AL1+C,tfsin_KERNEL)LY-E c= MSpb->pb_addr,== ct a/p-sdsd, dirty-ENOMEM;e-,,	pb->pb_addr,+= pb->pb_offs6eLY-E		pb->pb_.c ls |= PBF_MAPPED | _PBF_ADDR_AL1+CATED;p-s	} -6}b- /* Ifdsomedpages werepfound0winv2d]ea in2OH m
-	f* wu>aru nok,intPBF_NONE,d, re.p-se*/m-sif (good_pages !=,0oA{p-sdpb->pb_.c ls &= ~(PBF_NONE/;c-sdif (good_pages !=,page_c*/in) {p-sdcpb->pb_.c ls |= PBF_fsRTIAL;p-s	} -6}b-
-	fB_TRACE(pb, "lookup_pages",t(long)good_pages);c-
-c, dirtyrva.oc-}
---
-4-
-68dPre-a2_HW]eISF Sf(  too_Aofubufft
,ocads	mp_ use iu
-68	low-memory situa ISFs.
-68/ -
-4-
-68d_pagebuf_prea2_HW_bh
- -
-68	Pre-a2_HW]ee(  too_Aofu"c*/in"ubufft
,ocads	atBd, rtup.
-68	Puts(OH m0SF a list2atB"pb.r sv_bh"
-68	Redirts numbt
2_Prbv2actuSlly a2_HW]eg< 	sbpoo_.d- -/--STATIC il p-_pagebuf_prea2_HW_bh(I-E_ar	,	c*/in)m-{I-Ed,* Ok,bufft
loccH	*bh;p-s_ar	,	i; - - mp_ (if=,0; i0< c*/in; i++)A{p-sdbh:r kmem_cOt_e_a2_HW(bh_cOt_ep, SLAB_KERNEL)LY-E = MS_bhVt-/e	be Sk;p-sdbh->b_pprevi= &pb.r sv_bh;p-sdbh->b_amxk,= pb.r sv_bh;p-sdpb.r sv_bh:r bh;p-sdpb.r sv_bh_cin++oc- }c-	r6eirt i;b-} -
-4-
-68d_pagebuf_get.prea2_HW_bh
- -
-68	G6e tre0bufft
,ocad mverStu_ pre-a2_HW]eg< poo_.d- -	If too_Adon-mpty, sleep 'ni. tre0comesdbaB, iF.p- -	Redirts aforemSntISFg< bufft
,ocad.d- -/--STATIC d,* Ok,bufft
loccH -
-_pagebuf_get.prea2_HW_bh(ead()m-{I-Eunsigtod longd	.c ls;.-Ed,* Ok,bufft
loccH	*bh;p-sDECLARE_WAITQUEUE	(wait, currete);c-
-cdpiu_l2B,_irqsave(&pb.r sv_bh_12B,, .c ls/;c-m-sifMSpb.r sv_bh_cinf<t1) {p-sdadd_wait_queue(&pb.r sv_bh_wait, &wait)LY-E doA{p-sdEset_curreteod, re(TASK_UNINTERRUPTIBLEm;p-s	cspiu_ou12B,_irqr stor (&pb.r sv_bh_12B,, .c ls/;c-			bhk_run_queues(m;p-s	cst_edul (m;p-s	cspiu_l2B,_irqsave(&pb.r sv_bh_12B,, .c ls/;c-	s} whilea(pb.r sv_bh_cinf<t1);c-	s__set_curreteod, re(TASK_RUNNINGoLY-E	r6move_wait_queue(&pb.r sv_bh_wait, &wait)LY-E}b-
-	BUG_ON4pb.r sv_bh_cinf<t1);c-	BUG_ON4!pb.r sv_bh/;c-m-sbh,= pb.r sv_bh;p-spb.r sv_bh:r bh->b_amxk;p-spb.r sv_bh_cin--; -
-cspiu_ou12B,_irqr stor (&pb.r sv_bh_12B,, .c ls/;c-	, dirtybh;b-} -
-4-
-68d_pagebuf_d/ho_bh
- -
-68	Takgfcaru ofubufft
,ocads	t 0Siwe're2.inish
 }winv.p- -	Ca2_iOHdondnstccH ofujustikmem_cOt_e_d/ho(bh_cOt_ep, bhVt- -	wH uiyou'reAdtre0winv2a bh.
- -
-68	If tu_ pre-a2_HW]eg< poo_2iredull,ujustid/ho(OH  bufft
,ocad.d- -	OOH rwise, pue imdbaB, iF2OH utoo_, andAwakgfup anybodyt- -	wa  iigdmp_ one.
- -/--STATIC illome ead(p-_pagebuf_d/ho_bh(I-Ed,* Ok,bufft
loccH	*bh)m-{I-Eunsigtod longd	.c ls;.-E_ar	,	./ho;c-m-sifMS!+ ./ho(= pb.r sv_bh_cinf>= NR_RESERVED_BH)/A{p-sddpiu_l2B,_irqsave(&pb.r sv_bh_12B,, .c ls/;c-m-ssifMS!+ ./ho(= pb.r sv_bh_cinf>= NR_RESERVED_BH)/A{p-sddbh->b_pprevi= &pb.r sv_bh;p-sddbh->b_amxk,= pb.r sv_bh;p-sddpb.r sv_bh:r bh;p-sddpb.r sv_bh_cin++oc-Y-E c= MSwaitqueuela_SIve(&pb.r sv_bh_wait))A{p-sdsdwakg_up(&pb.r sv_bh_wait);c-sdc}--s,}m-
-  spiu_ou12B,_irqr stor (&pb.r sv_bh_12B,, .c ls/;c-	}m-sifMS./ho)A{p-sdkmem_cOt_e_d/ho(bh_cOt_ep, bhV;c-	}m-} -
-4-
-68dFindiigdandAR SIiigdBufft
s
-68/ -
-4-
-68d_pagebuf_.ind
- -
-68	Looks up, andAce Segs.ih absete, a l2B,ab.cfbufft
,forp-f*	a giveinrangedif(30 _aode. ,Theubuff r is , dirt d
-68	lem ed.	 IfdoOH rntverlappiig bufft
s	exist,-OH y7aru
-68	e leas dpbeforepOH uamw,buff r is ce Segd andAlem ed,t- -	wHich-maynimplySOHatAOHdonca2_-willibl2B,0/ini. those0bufft
sp-f*	aru unlem ed.  NoAI/OfdondmpliBd byrOHdonca2_.
-e*/--STATIC pageobuf_t -
-_pagebuf_.ind(,,sd/* .indfbufft
,foribl2B,	*/m-spb_t rget.t		*t rget,/* t rget,foribl2B,		*/m-sloff_t			i_Pf,d/* d, rtiigd_Pfs6e if(range	*/m-sdnit.t			isnit,c/* lengnv0if(range		*/m-spageobuf_.c ls_t	.c ls,c/* PBF_TRY1+af			*/m-spageobuf_t		*amw_pb)/*,amwly a2_HW]eg< bufft
	*/m-{I-Eloff_t			range_bas ;I-Ednit.t			range_hengnv;.-E_ar	,	hva.oc-Epb.hash_t		*h;.-Ed,* Ok,listloccHE*p;m- pageobuf_t		*pb;.-E_ar	,	nok_lem ed;c-
-c,ange_bas ,= (i_Pf0<< BBSHIFTm;p-srange_hengnv,= (isniti<< BBSHIFTm;p-
-s/* EnsureSwe,amver,doAIOs smV_.ArSOHan0OH usectp_ sniti*/m-sBUG_ON4range_hengnv,< (10<< , rget->pbr_sshiftV)2.-p-s/* EnsureSwe,amver,doAIOs b 0Siaru nok,sectp_ aligtod */m-sBUG_ON4range_bas f& (loff_t), rget->pbr_sread);I-p-shva.f=,_bhash(, rget->pbr_bdev, range_bas m;p-shi= &pbhash[hva.];c-
-cdpiu_l2B,(&h->pb_hash_12B,V;p-slistlfor_eOt_(p, &h->pb_hashoA{p-sdpb0tmlist_(l ry(p, pageobuf_t, pb.hash_1istV;p-m-sdif (pb->pb_t rget,== t rgetA&&p-sd    pb->pb_.ile_offs6e == range_bas A&&p-sd    pb->pb_bufft
lhengnv0t= range_lengnv) {p-sdc/* Ifdwe,look	atBdomethiigdbriigdittto(OH p-sdcl* d/ont _PrOH ulist2mp_ amxk,btchp-sdcl*/p-sdsatomicninc(&pb->pb_hold);c-sdclist_move(&pb->pb_hash_1ist, &h->pb_hasho;p-sd	g fnAfound;p-s	} -6}b-
-	/* No-match found0*/m-sif (amw_pb) {p-sd_pagebuf_in04ialnit(amw_pb, t rget, range_bas ,e-,,,,range_hengnv, .c ls/;c-	samw_pb->pb_hash_dndIxB= hva.;c-	slist_add(&amw_pb->pb_hash_1ist, &h->pb_hasho;p-s} S_HWo{p-sdXy %STATS_INC(pb_miss_lem ed)LY-E}b-
-	dpiu_ou12B,(&h->pb_hash_12B,V;p-s, dirt Samw_pb);p-m-found:
-	dpiu_ou12B,(&h->pb_hash_12B,V;p-
-	/* Att-mpttto(g6efb/epsBmaphorepwinvoutBsleepiig,e-, syih OHdondoeo+_tyiworkrOH ndwe,amA|tto(drop OH 
-	f* epiu12B, andAdo a harIuatt-mpttonfb/epsBmaphore.p-se*/m-snok_lem edb=,down_+fy12B,(&pb->pb_sBmaV;m-sif (aok_lem ed)A{p-sdif (! .c ls & PBF_TRY1+af)) {p-sdc/* wait,foribufft
,ownt
shipl*/p-sdsfB_TRACE(pb, "get.lem ",O0V;p-sccpagebuf_12B,(pb/;c-sdcXy %STATS_INC(pb_get.lem ed_waited)LY-E	} S_HWo{p-sde/* We,eadod forr  +fy12B,	 n  .ailed,Ono amA|p-sdcl* to(look	atBB->seoffs6e andAlengnv0H re,pwup-sds68,know(OHatAOHdontagebuf0atAleastntverlaps tu_p-sds68,tagebuf0andAis lem ed,SOH reforeptu_ bufft

-sds68,eiOH rndoeo+_tyiexist,-or is OHdonbufft

-sds68/m-
-  Epagebuf_r le(pb); -sdcXy %STATS_INC(pb_busy_lem ed)LY-Esd, dirty(dpst/oc-o,} -6} S_HWo{p-sd/* tfy12B,	workod */m-ssfB_SET_OWNER(pb);I-E}c-
-sif (pb->pb_.c ls & PBF_STALEVe-,,pb->pb_.c ls &= PBF_MAPPED | \e-,,,,_PBF_ALL_fsinS_MAPPED | \e-,,,,_PBF_ADDR_AL1+CATED | \e-,,,,_PBF_MEM_AL1+CATED | \e-,,,,_PBF_MEM_SLAB;I-EfB_TRACE(pb, "got.lem ",O0V;p-sXy %STATS_INC(pb_get.lem edV;p-s, dirt Spb);b-} -
---4-
-68	pagebuf_dind
- -
-68	pagebuf_dind , dirtona bufft
,matchiig0OH uspecifiBd rangedif
-68	d]ea mp_ OHeAspecifiBd t rget, if( nyr_PrOH ur levain0bhem sp-f*	aru iF2memory. ,Theubuff r maynigafRuna2_HW]eg< holes,n(+
-68	dome,Abuk+_tyia2_,r_PrOH ubhem sfaru iF2memory. ,EveinwH re
-68	pages arenpr sete dn2OH ubufft
,+_tyia2_AofumverySpage,may b 
-68	val		.
-e*/--pageobuf_t -
-pagebuf_.ind(,,sd/* .indfbufft
,foribl2B,	*/m-s,,sd/* iPrOH ubhem fdondF2memory	*/m-spb_t rget.t		*t rget,/* t rget,foribl2B,		*/m-sloff_t			i_Pf,d/* d, rtiigd_Pfs6e if(range	*/m-sdnit.t			isnit,c/* lengnv0if(range		*/m-spageobuf_.c ls_t	.c ls)c/* PBF_TRY1+af			*/m-{p-s, dirt _pagebuf_.ind(t rget, i_Pf,Aisnit, .c ls,mdpst/oc-}b---4-
-68	pagebuf_get
- -
-68	pagebuf_get,assBmbles
a bufft
,ctveriig0OH uspecifiBd range.d- -	Somedp_ allr_PrOH ubhem sfdn2OH urangedmay b uval		.  Stp_age
-68	dn2memory fp_ allrportiSFs oh OHeubuff r willibeAa2_HW]eg<,
-68	alnvoughbbaB,iig0stp_agedmay _tyibe. ,IfdPBF_READfdons6e iu
-68	.c ls,mpagebuf_iod, rt donca2_e ,a2so.
-e*/--pageobuf_t -
-pagebuf_get(,,sd/* a2_HW]ee(  bufft
		*/m-spb_t rget.t		*t rget,/* t rget,foribufft
		*/m-sloff_t			i_Pf,d/* d, rtiigd_Pfs6e if(range	*/m-sdnit.t			isnit,c/* lengnv0if(range		*/m-spageobuf_.c ls_t	.c ls)c/* PBF_TRY1+af			*/m-{p-spageobuf_t		*pb, *amw_pb;.-E_ar	,	error; -
-samw_pb,= pagebuf_a2_HW]eg .c ls);m-sif (uolokely !amw_pb)mt-/e, dirty(dpst/oc-m-spbf=,_pagebuf_.ind(t rget, i_Pf,Aisnit, .c ls,mamw_pb);p-sif (pb !=,amw_pb) {p-sdpagebuf_dea2_HW]eg amw_pb);p-ssif (uolokely !pb)mt-/ed, dirty(dpst/oc-o} - - Xy %STATS_INC(pb_getoLY-
-	/* filliin any missiigdpagesi*/m-serror0t _pagebuf_lookup_pages(pb, pb->pb_, rget->pbr_mappiig,i.c ls);m-sif (uolokely errorV) {p-sdpriitk(KERN_WARNINGt-/ed"pagebuf_get:Swarniig,i.ailed to(lookup,pages\n");p-ssg fnAno_bufft
oc-o} - - /*
-	f* Alwaysffilliin OH ubhem fnumbt
2now,b l-2mappe 0casesA-30 do
-	f*  l-i
,ownntverlay oh OHdonlater.
-se*/m-spb->pb_bu0tmioff;m-spb->pb_c*/in_desirA|t= pb->pb_bufft
lhengnv;c-m-sifMS.c ls & PBF_READ)A{p-sdif (PBF_NOT_DONE(pb)) {p-sdcfB_TRACE(pb, "get.e SI",t(unsigtod long).c ls/;c-			Xy %STATS_INC(pb_get.rccH/oc-  Epagebuf_iod, rt(pb, .c ls/;c-	s} S_HWo_++ .c ls & PBF_ASYNC) {p-sdcfB_TRACE(pb, "get.e SI_async",t(unsigtod long).c ls/;c-			/*p-sds syRea ,ah SIuca2_-wHich-is  _e SIy satisfiBd,
-sds sydrop OH nbufft

-sds68/m-	ssg fnAno_bufft
oc-o	} S_HWo{p-sdefB_TRACE(pb, "get.e SI_dtre",t(unsigtod long).c ls/;c-			/* We,do+_tyiwain0e SIuin OH  fc ls */p-sdspb->pb_.c ls &= ~PBF_READoc-o,} -6} S_HWo{p-sdfB_TRACE(pb, "get.w    ",t(unsigtod long).c ls/;c-	}b-
-	, dirt pb;.-
-no_bufft
:m-sifMS.c ls & (PBF_1+aft|tPBF_TRY1+af))p-sdpagebuf_ou12B,(pb);I-Epagebuf_r le(pb); -s, dirt ct aff-} -
-4-
-68,Ce SegdaSskeletal pagebuf0(aoApages associ]eg< winv2it).
-e*/--pageobuf_t -
-pagebuf_lookup(
-,d,* Ok,pb_, rget	*t rget,c-sloff_t			i_Pf,m-sdnit.t			isnit,m-spageobuf_.c ls_t	.c ls)m-{p-spageobuf_t		*pb;c-m-s.c ls |= _PBF_fRIVATE_BH;m-spbf=,pagebuf_a2_HW]eg .c ls);m-sif (pb) {p-sd_pagebuf_in04ialnit(pb, t rget, i_Pf,Aisnit, .c ls)oc- }c-	r6eirt pb;c-}
---4-
-68,If wu>aru nok,low(on2memory OH nddorOH ur adah SIuiin3 deadhem 
-68,saf-2manner.
- -/--
-		
-pagebuf_r adah SI(m-spb_t rget.t		*t rget,c-sloff_t			i_Pf,m-sdnit.t			isnit,m-spageobuf_.c ls_t	.c ls)m-{p-s.c ls |= (PBF_TRY1+af|PBF_READ|PBF_ASYNC|PBF_READ_AHEAD/u -	pagebuf_get(t rget, i_Pf,Aisnit, .c ls/oc-}b---pageobuf_t -
-pagebuf_get_(mpty(
-ddnit.t			len,e-,pb_t rget.t		*t rget)m-{p-spageobuf_t		*pb;c-m-spbf=,pagebuf_a2_HW]eg 0);m-sif (pb)p-sd_pagebuf_in04ialnit(pb, t rget, 0, len,O0V;p-s, dirtypb;c-}
---d,atic illome s,* Ok,page *
-mem_to_page(
-,tic 			*addr/m-{I-E-2.4((unsigtod long)addr,< VMAL1+C%STARTm ||p-sllllS4unsigtod long)addr,>= VMAL1+C%END)s0{t-/e, dirtyvirt_to_page(addr/oc-	} S_HWo{p-sd, dirtyvma2_HW_to_page(addr/oc-	}c-}
---il p-pagebuf_associ]eg_memory(m- pageobuf_t		*pb,e-,tic 			*mem,
-ddnit.t			len/m-{I-E_ar	,	rva.oc-s_ar	,	if=,0;.-ddnit.t			ptr;.-ddnit.t			end,ISnd_cur;.-doff_t		,offs6eoc-s_ar	,	page_c*/in;b-
-	page_c*/in tmfsin_CACHE_ALIGN(loum >> fsin_CACHE_SHIFT; - offs6e tm(off_t)2mem -a((off_t)mem & fsin_CACHE_MASK);m-sif (offs6e &&a(len >tfsin_CACHE_SIZE/)p-sdpage_c*/in++oc-Y-E/* F/ho( nySprevious s6e if(page poinSt
s	*/m-s= MSpb->pb_pagesi&&a(pb->pb_pagesi!= pb->pb_page_array))A{p-sdkd/ho(pb->pb_pages);m- }m-spb->pb_pages = ct aff-	pb->pb_addr,= mem;c-
-c,va.f=,_pagebuf_get.pages(pb, pageoc*/in, 0);m-sif (rva.mt-/e, dirtyrva.oc- - pb->pb_offs6ef=,offs6e;m- ptr = (enit.t) mem & fsin_CACHE_MASK;m- Snd tmfsin_CACHE_ALIGN((enit.t) mem + loum;p-sSnd_cur tmend;p-s/* d6efup,first,page */m-spb->pb_pages[0],= mem_to_page(mem/oc-m-sptr,+= fsin_CACHE_SIZE;m-spb->pb_page_c*/in tm++i;b-swhilea(ptr,<mendoA{p-sdpb->pb_pages[i],= mem_to_page((ead( *)ptrV;p-s pb->pb_page_c*/in = ++i;b-ssptr,+= fsin_CACHE_SIZE;m-s}m-spb->pb_lem edb=,0oc- - pb->pb_c*/in_desirA|t= pb->pb_bufft
lhengnv0tmlen;m-spb->pb_.c ls |= PBF_MAPPED | _PBF_fRIVATE_BH;m-
-	r6eirt 0;b-} -
-pageobuf_t -
-pagebuf_get_no_daddr(
-ddnit.t			len,e-,pb_t rget.t		*t rget)m-{p-s_ar	,	rva.oc-stic 			*rmem = ct aff-	pageobuf_.c ls_t	.c ls =tPBF_FORCEIOff-	pageobuf_t		*pb;.-Ednit.t			tlouf=,0;.-m-sif (uolokely len >t0x20000)mt-/e, dirtyct aff-m-spbf=,pagebuf_a2_HW]eg .c ls);m-sif (!pb)p-sd, dirtyct aff-m-s_pagebuf_in04ialnit(pb, t rget, 0, len,O.c ls/;c-m-sdoA{p-sdif (tlouf==,0oA{p-sdctlouf=,len; /* first,btch */p-sd} S_HWo{p-sdekd/ho(rmem/o /* f/ho(OH  mem .verSOH Sprevious  ry,*/p-sdstlouf<<= 1o /* doub.cfOH usnitiandAOry again */p-sd}p-sdif ((rmem = kma2_HW(tlen,OGFP_KERNEL))f==,0oA{p-sdcpagebuf_d/ho(pb); -sdc, dirtyct aff-o,} -6} whilea((enit.t)rmem != ((enit.t)rmem & ~, rget->pbr_sread)/;c-m-sifMS(,va.f=,pagebuf_associ]eg_memory(pb, rmem, len)) !=,0oA{p-sdkd/ho(rmem/op-sdpagebuf_d/ho(pb); -sd, dirtyct aff-o}b- /* oOH rwise pagebuf_d/houjustiigtoresiit */m-spb->pb_.c ls |= (_PBF_MEM_AL1+CATED | _PBF_MEM_SLABs;p-sfB_CLEAR_OWNER(pb);p-sup(&pb->pb_sBmaV; /* Redirt unlem ed pagebuf08/m-
- fB_TRACE(pb, "no_daddr", rmem);c-
-c, dirtypb;c-}
-----4-
-68	pagebuf_hold
- -
-68	IncremSntur ft
etc  c*/in(on2bufft
,+to(hold OHeubuff r concurretelyt- -	winv2anoOH rnche SIuwHich-maynreleas uS./ho)AOHeubuff r asynchronously.d-e*t- -	Mustihold OHeubuff r  _e SIy Oo ca2_iOHdonfuncSISF.p- -/--
-		
-pagebuf_hold(m- pageobuf_t		*pb/m-{I-Eatomicninc(&pb->pb_hold);c-sfB_TRACE(pb, "hold",O0V;p-}b---4-
-68	pagebuf_rele
- -
-68	pagebuf_relepr leas s aihold onfb/epspecifiBd bufft
. ,IPrOH 
-68	OH uholdAc*/in-is 1,mpagebuf_relepca2_s pagebuf_d/ho.
- -/--
-		
-pagebuf_r lo(m- pageobuf_t		*pb/m-{I-Epb.hash_t		*hash,= pb.hash(pb);m-
- fB_TRACE(pb, "r lo", pb->pb_rS_HW/;c-m-sifMSatomicndec_and_12B,(&pb->pb_hold,O&hash->pb_hash_12B,V)A{p-sdiar	,do_./ho(= 1_b-p-ss= MSpb->pb_rS_HW/A{p-sdcatomicninc(&pb->pb_hold);c-sdcdpiu_ou12B,(&hash->pb_hash_12B,V;c-sdc(*Spb->pb_rS_HW/) (pb); -sdcdpiu_l2B,(&hash->pb_hash_12B,V;c-sdcdo_./ho(= 0ff-o,} -p-ss= MSpb->pb_.c ls & PBF_DELWRI) {p-sdcpb->pb_.c ls |= PBF_ASYNC;p-sdcatomicninc(&pb->pb_hold);c-sdcpagebuf_delw  _queue pb,O0V;p-sccdo_./ho(= 0ff-o,} S_HWo_++ pb->pb_.c ls & PBF_FS_MANsinD)b{p-sdsdo_./ho(= 0ff-o,} -p-ss= MSdo_./ho)b{p-sdslist_del_in04(&pb->pb_hash_1istV;p-sdcdpiu_ou12B,(&hash->pb_hash_12B,V;c-sdcpagebuf_d/ho(pb); -sd} S_HWo{p-sdedpiu_ou12B,(&hash->pb_hash_12B,V;c-sd}c-	}Y-}
-----4-
-68	MutuSlfexclusISF on2bufft
s. ,Lem iigdmodel:
- -
-68	Bufft
s associ]eg< winv2iaodes	mp_ wHich-buff r hem iig
-68	do+_tyienab.cd>aru nok,protectBd byrsBmaphores, andAare
-68	 ssumed to(befexclusIvely,owntd0byrOH ucV_.Ar. ,There2irea
-68	dpiu12B, dn2OH ubufft
,+us
 }byrOH ucV_.Ar wH uiconcurrete
-68	 ccessndonpossible.
-68/ -
-4-
-68dpagebuf_cond_12B,
- -
-68	pagebuf_cond_12B, hem sfaibufft
,objece, if(it2don_ty  _e SIy lem ed.
-68	Notn OHatAOHdondn2no way
-68	lem siOHeAundISlyiigdpages, ssbit2dononly useful}mp_ synchroniziig
-68	concurrete use if(page bufft
,objeces, not mp_ synchroniziigidndIpendete
-68	 ccessnto(OH uundISlyiigdpages.
-68/ -il p-pagebuf_cond_12B,(			/* 12B, bufft
,+(++_tyilem ed	*/m-s,,sd/* , dirton-EBUSY+(++lem edV	*/m-spageobuf_t		*pb/m-{I-E_ar	,	lem ed;c-
-clem edb=,down_+fy12B,(&pb->pb_sBmaVf==,0;m-sif (lem ed)A{p-sdfB_SET_OWNER(pb);I-E}c- fB_TRACE(pb, "cond_12B,",t(long)lem edV;p-s, dirt(lem ed ? 0 :n-EBUSYV;p-}b---4-
-68	pagebuf_12B,_value
- -
-68	Redirt 12B, valueRforr  pagebuf
-68/ -il p-pagebuf_12B,_value(m- pageobuf_t		*pb/m-{I-E, dirt(atomicnrccH(&pb->pb_sBma.c*/in)V;p-}b---4-
-68	pagebuf_12B,
- -
-68	pagebuf_12B, hem sfaibufft
,objece.  Notn OHatAOHdondn2no way
-68	lem siOHeAundISlyiigdpages, ssbit2dononly useful}mp_ synchroniziig
-68	concurrete use if(page bufft
,objeces, not mp_ synchroniziigidndIpendete
-68	 ccessnto(OH uundISlyiigdpages.
-68/ -il p-pagebuf_12B,(m- pageobuf_t		*pb/m-{I-EfB_TRACE(pb, "lom ",O0V;p-sifMSatomicnrccH(&pb->pb_ionrcmainiig)mt-/ebhk_run_queues(m;p-sdown(&pb->pb_sBmaV;m-sfB_SET_OWNER(pb);I-EfB_TRACE(pb, "lom ed",O0V;p-	r6eirt 0;b-} -
-4-
-68dpagebuf_ou12B,
- -
-68	pagebuf_ou12B,pr leas s OHeA12B,pon2OH ubufft
0_bjecerce Segd by
-68	pagebuf_12B, p_ pagebuf_cond_12B, (_ty  ny
-68	pinniigd_PrundISlyiigdpagesrce Segd by pagebuf_pin).
- -/--
-		
-pagebuf_ou12B,(,,sd/* ou12B,pbufft
		*/m-spageobuf_t		*pb/d/* bufft
0to(ou12B,		*/m-{p-sfB_CLEAR_OWNER(pb);p-sup(&pb->pb_sBmaV;I-EfB_TRACE(pb, "ou12B,",O0V;p-}b---
-4-
-68dPinniigdBufft
 Stp_agendn2Memory
- -/--
-4-
-68dpagebuf_piu
-68
-68dpagebuf_piu hem sfallr_PrOH umemory repr setegd by aibufft
,iu
-68	memory. ,Multiplepca2_s to pagebuf_pin andApagebuf_oupin, forp-f*	OH usameAp_ differete bufft
s afftctiigdaSgiveinpage, will
-68dproperly c*/in-OH uaumbt
2_Proutstandiigd"pin" requesSs. ,The
-68dbuff r maynbepr leas dAafteruOHeApagebuf_pin andAa differete
-68dbuff r us
 }wH uica2_iigdpagebuf_oupin, if0desirA|.
-68dpagebuf_piu deGuld benuse }byrOH uB->sedystem wH uiiyiwains b 
-68	 ssurA|ttHatAno att-mpttwillibeAmade fnAforccfOH uafftct d
-68	memory OoSdisk.	 Itndoeo+_tyi ssurA b 0SiaSgiveinlogical paget- -	willi_tyibe movedAOo a differete physical page.
- -/--
-		
-pagebuf_piu(m- pageobuf_t		*pb/m-{I-Eatomicninc(&pb->pb_piu_c*/inV;I-EfB_TRACE(pb, "pin",t(long)pb->pb_piu_c*/in.c*/inerV;p-}b---4-
-68	pagebuf_oupin
- -
-68	pagebuf_oupiu rmvers s OHeA12B,iigd_Prmemory performBd by
-68	pagebuf_piu.  Notn OHatAbonv2funcSISFsuafftct d OHeA12gical
-68	pages associ]eg< winv2OH ubufft
,+_tyiOH ubufft
0itself.
- -/--
-		
-pagebuf_oupiu(m- pageobuf_t		*pb/m-{I-EifMSatomicndec_and_tesS(&pb->pb_piu_c*/inV)A{p-sdwakg_up_a2_(&pb->pb_waitt
s/u -E}c- fB_TRACE(pb, "oupiu",t(long)pb->pb_piu_c*/in.c*/inerV;p-}b---il p-pagebuf_ispiu(m- pageobuf_t		*pb/m-{I-Er6eirt atomicnrccH(&pb->pb_piu_c*/inV;I-}b---4-
-68	pagebuf_wait_oupin
- -
-68	pagebuf_wait_oupin waits	/ini. a2_i_PrOH umemory associ]eg<t- -	winv2OH ubufft
0is+_tyileng r hem  d dn2memory. ,It , dirto
-68	dmmBdi]egly (++_tno(_PrOH uafftct d pages are lem ed.
-68/--d,atic illome ead(p-_pagebuf_wait_oupin(m- pageobuf_t		*pb/m-{I-EDECLARE_WAITQUEUE	(wait, currete);c-
-cifMSatomicnrccH(&pb->pb_piu_c*/inVf==,0o -sd, dirt;c-
-cadd_wait_queue(&pb->pb_waitt
s, &wait)LY-Emp_ (;;)A{p-sdcurrete->d, re = TASK_UNINTERRUPTIBLELY-E ifMSatomicnrccH(&pb->pb_piu_c*/inVf==,0o -sd	be Sk;p-sdifMSatomicnrccH(&pb->pb_ionrcmainiig)mt-/e	bhk_run_queues(m;p-s	st_edul (m;p-s}c-	r6move_wait_queue(&pb->pb_waitt
s, &wait)LY-Ecurrete->d, re = TASK_RUNNING;p-}b---
-4-
-68dBufft
 Uni.ity Rputiies
- -/--
-4-
-68dpagebuf_iostre
- -
-68	pagebuf_iostre marksfaibufft
,mp_ wHich-I/Ofdondnntrogress
-68	dtre0winv2respecerto(OHatAI/O.	Theupb_iostre rputiie,n(+
-68	pr sete, willibeAca2_e ,asfaiside-efftct.
- -/--
-		
-pagebuf_iostre_st_ed(
-,tic 			*v)m-{p-spageobuf_t		*pb tm(pageobuf_t *)v;c-
-cifMSpb->pb_iostre)A{p-sd(*Spb->pb_iostre)) (pb); -sd, dirt;c-E}c-
-sif (pb->pb_.c ls & PBF_ASYNC) {p-sdif (!pb->pb_rS_HW/c-sdcpagebuf_ou12B,(pb);I-EEpagebuf_r le(pb); -s}Y-}
---
-		
-pagebuf_iostre(m- pageobuf_t		*pb,e-,_ar	,	d]eaio,e-,_ar	,	st_edul /m-{I-Epb->pb_.c ls &= ~(PBF_READf|tPBF_WRITE);m-sif (pb->pb_error0t=,0oA{p-sdpb->pb_.c ls &= ~(PBF_fsRTIALt|tPBF_NONE/;c-	}b-
-	fB_TRACE(pb, "iodtre",tpb->pb_iostre);c-m-sifMS(pb->pb_iostre)A|| (pb->pb_.c ls & PBF_ASYNC)) {p-sdif (st_edul /b{p-sds=ar	d]emSF tmCPU_TO_DAEMON(smp_processor_id()/;c-m-s	sINIT_TQUEUE(&pb->pb_iostre_st_ed,e-,,,,pagebuf_iostre_st_ed, (ead( *)pb); -sdcqueueltask(&pb->pb_iostre_st_ed, d]eaio ?e-,,,,&pagebuf_d]eaiostre_tq[d]emSF] :e-,,,,&pagebuf_logiostre_tq[d]emSF]); -sdcwakg_up(d]eaio ?e-,,,,&pagebuf_d]eaiostre_wait[d]emSF] :e-,,,,&pagebuf_logiostre_wait[d]emSF]); -sd} S_HWo{p-sdepagebuf_iostre_st_ed(pb); -sd}
-	} S_HWo{p-sdup(&pb->pb_iostresBmaV;p-s}Y-}
---4-
-68	pagebuf_ioerror
- -
-68	pagebuf_ioerror0s6es OH uerror0codh mp_ aibufft
.
- -/--
-		
-pagebuf_ioerror(			/* mark/clearrbufft
,error0.c l */m-spageobuf_t		*pb,d/* bufft
0to(mark		*/m-sunsigtod _ar	,errorVd/* error0to(stor  (0 (++_tno)	*/m-{p-spb->pb_error0t error; -	fB_TRACE(pb, "ioerror",t(unsigtod long)errorV;I-}b---4-
-68	pagebuf_iod, rt
- -
-68	pagebuf_iod, rt dn04iaegs.I/OfSF a bufft
,+bas dpon2OH u.c ls suppliBd.d- -	If necessary, ittwilliarrange forr nySdiskfspace,a2_HW]eISF requirA|,
-68	 ndAittwillibe Skfup,OH ur quesS iPrOH ubhem fmappiigs requirA it.d- -	Theupb_iostre rputiie dn2OH ubufft
 suppliBdtwillionly beAca2_e t- -	wHeina2_i_PrOH usubsidiary.I/OfrequesSs, if( ny,nigafRbeou0completA|.
-68dpagebuf_iod, rt ca2_s tHeApagebuf_iodn04iaeg rputiie orp-f*	pagebuf_iorequesS,	_PrOH  formBr rputiie ds+_tyi /homed,0to(st rt
- -	OH uI/OfSF a giveinlow-levelnrequesS.
-68/ -il p-pagebuf_iod, rt(			/* d, rt I/OfSF a bufft
	  */m-spageobuf_t		*pb,d/* bufft
0to(d, rt		  */m-spageobuf_.c ls_t	.c ls)c/* PBF_1+af, PBF_ASYNC, PBF_READ, */m-s,,sd/* PBF_WRITE, PBF_DELWRI,	  */m-s,,sd/* PBF_DONT_B1+af		  */m-{I-E_ar	,	d, rusf=,0;.-m-sfB_TRACE(pb, "iod, rt",t(unsigtod long).c ls/;c-
-sifMS.c ls & PBF_DELWRI) {p-sdpb->pb_.c ls &= ~(PBF_READf|tPBF_WRITEf|tPBF_ASYNC);p-sdpb->pb_.c ls |= .c lst& (PBF_DELWRIf|tPBF_ASYNC);p-sdpagebuf_delw  _queue pb,O1); -sd, dirtyd, rus;c-	}b-
-	pb->pb_.c ls &= ~(PBF_READf|tPBF_WRITEf|tPBF_ASYNCf|tPBF_DELWRIf|t\e-,,,PBF_READ_AHEADf|tPBF_RUN_QUEUES/u -	pb->pb_.c ls |= .c lst& (PBF_READf|tPBF_WRITEf|tPBF_ASYNCf|t\e-,,,PBF_READ_AHEADf|tPBF_RUN_QUEUES/u -
-	BUG_ON4pb->pb_bu0ttmfsin_BUF_DADDR_ct aoLY-
-	/* Fp_ w    sfallow an,alnernate s,*ategy rputiie to preced 
-	f* OH uactuSl.I/OfrequesS (wHich-mayn_tyibe issue ,ayia2_Aiu
-	f* aishutdown situa ISF, for example).
-se*/m-sd, rusf=,S.c ls & PBF_WRITE) ?e-,,pagebuf_iod,*ategy(pb) : pagebuf_iorequesS(pb);m-
- /* Wait,foriI/Ofdf wu>aru nok,an,asyncnrequesS.
-	f* Notn:,asyncnI/OfrequesS completISF willireleas uOHeAbufft
,
-	f* an|ttHatAcan,ale SIy beAdtre0byrOHdonpoinS.  So usiig0OH 
-	f* bufft
0poinSt
 .verShere2SF, afteruasyncnI/O,fdondnval		.
-se*/m-sif (!d, rusf&& !S.c ls & PBF_ASYNC))p-s	s, rusf=,pagebuf_iowait(pb);m-
- , dirtyd, rus;c-}b---
-4-
-68 HelpBr rputiies	mp_ pagebuf_iorequesS (pagebufnI/OfcompletISF)
- -/--
-STATIC __illome__ il p-_pagebuf_iolem ed(m- pageobuf_t		*pb/m-{I-EASSERT(pb->pb_.c ls & (PBF_READ|PBF_WRITE));m-sif (pb->pb_, rget->pbr_bsnit <tfsin_CACHE_SIZE/ -sd, dirtypb->pb_lem ed;m-sif (pb->pb_.c ls & PBF_READ) -sd, dirtypb->pb_lem ed;m-s, dirt Spb->pb_.c ls & _PBF_fsinCACHEV;I-}b---STATIC ead(p-_pagebuf_iostre(m- pageobuf_t		*pb,e-,_ar	,	st_edul /m-{I-E_ar	,	i; - - ifMSatomicndec_and_tesS(&pb->pb_ionrcmainiig) !=,1o -sd, dirt;c-
-cifMS_pagebuf_iolem ed(pb)mt-/emp_ (if=,0; i0< pb->pb_page_c*/in; i++)e-,,,ou12B,_page(pb->pb_pages[i]m;p-spb->pb_lem edb=,0oc-epagebuf_iostre pb,O pb->pb_.c ls & PBF_FS_DATAIOD), st_edul /;I-}b---STATIC ead(p-_Snd_io_pagebuf(I-Ed,* Ok,bufft
loccH	*bh,e-,_ar	,	uptou]eg,e-,_ar	,	dullpage)m-{I-Ed,* Ok,page		*pagei= bh->b_page;p-spageobuf_t		*pb tm(pageobuf_t *)bh->b_priv]eg;c-
-cmark_bufft
luptou]eg(bh, uptou]egm;p-sput_bh(bh/;c-m-sif (!uptou]egm {p-sdSetPageError(page);p-sdpb->pb_error0t EIOff-	}c-
-sif (dullpage)o{p-sduu12B,_bufft
(bh/;c-	d_pagebuf_d/ho_bh(bh/;c-	d= MS!PageError(page))e-,,,SetPageUptou]eg(page);
-	} S_HWo{p-sdd,atic spiu12B,_t pageouptou]eg_l2B,0= SPIN_1+af_UN1+afED;
-	Ed,* Ok,bufft
loccH *bp;m- Eunsigtod long .c ls;.-m- EASSERT(PageLom ed(page))LY-E dpiu_l2B,_irqsave(&pageouptou]eg_l2B,, .c ls/;c-	sclear_bufft
lasync(bh/;c-	duu12B,_bufft
(bh/;c-	dmp_ (bpi= bh->b_OHdo_page; bpi!r bh; bpi= bp->b_OHdo_page)b{p-sds= MSbufft
llem ed(bp))A{p-sdsd= MSbufft
lasync(bp)/t-sdc		be Sk;p-sd,} S_HWo_++ !bufft
luptou]eg(bp)/t-sdc	be Sk;p-sd}Y-E dpiu_ou12B,_irqr stor (&pageouptou]eg_l2B,, .c ls/;c-	s= MSbp0ttmbhf&& !PageError(page))e-,,,SetPageUptou]eg(page);
-	}f-m-s_pagebuf_iostre pb,O1V;I-}b---STATIC ead(p-_pagebuf_Snd_io_completA_pages(m- d,* Ok,bufft
loccH	*bh,e-,_ar	,	uptou]eg)m-{I-E_Snd_io_pagebuf(bh, uptou]eg,O1V;I-}b---STATIC ead(p-_pagebuf_Snd_io_p rtial_pages(m- d,* Ok,bufft
loccH	*bh,e-,_ar	,	uptou]eg)m-{I-E_Snd_io_pagebuf(bh, uptou]eg,O0V;p-}b---
-4-
-68 In04iaeg I/OfSF p rt Sf(  tageiwu>aru inSt
 stod _a
-e*/--STATIC il p-_pagebuf_pageoio(
-,d,* Ok,page		*page,c/* Pageid,* OkureSwe,aru dea2iig0winv2*/m-spb_t rget.t		*pbr,c/* device2p rameSt
s	(bsz, ssz, dev) */m-spageobuf_t		*pb,d/* pagebufnholdiigdit, can,beAct a */m-spageobuf_daddr_t	bn,d/* d, rtiigdbhem fnumbt
2*/m-sdnit.t			pg_offs6e,d/* d, rtiigd_Pfs6e in,page */m-sdnit.t			pg_hengnv,d/* c*/in(of2d]ea to process2*/m-sinr	,	rw,d/* , ad/w     oper]eISF */m-sinr	,	flush)m-{I-Ednit.t			sectp_;I-Ednit.t			bhk_hengnv0tm0;.-dd,* Ok,bufft
loccH	*bh, *occH, *bufft
1ist[MAX_BUF_PER_fsin]LY-E_ar	,	sectp__shift,= pbr->pbr_sshiftLY-E_ar	,	if=,0, cin = 0LY-E_ar	,	public_bh:r 0LY-E_ar	,	multi_ok;c-m-sifMS(pbr->pbr_bsnit <tfsin_CACHE_SIZE/A&&p-sllll!Spb->pb_.c ls & _PBF_fRIVATE_BHV)A{p-sdiar	,cOt_e_ok;c-m-s,cOt_e_ok:r !( pb->pb_.c ls & PBF_FORCEIO)A|| (rw0ttmWRITE));m-s	public_bh:r multi_ok0tm1;p-sdsectp_ tm10<< sectp__shift;.-m- EASSERT(PageLom ed(page))LY-E = MS!page_has_bufft
s(page))e-,,,ce Seg_(mpty_bufft
s(page, pbr->pbr_kdev, sectp_/;c-m-s	if=,sectp_ >> BBSHIFTLY-E bu0-tm(pg_offs6e >> BBSHIFT/;c-m-s	/* Findfbufft
_ocads	belongiig0OoujustiOHdontagebuf0*/m-s,bh:r occH,= pageobufft
s(page)LY-E doA{p-sdE= MSbufft
luptou]eg(bhml&& cOt_e_ok/t-sdc	conninue;p-s	E= MSbhk_hengnv0< pg_offs6e/t-sdc	conninue;p-s	E= MSbhk_hengnv0>= pg_offs6e0+ pg_hengnv/t-sdc	be Sk;p-t-sdc12B,_bufft
(bh/;c-	d	get.bh(bh/;c-	ddbh->b_sniti= sectp_;I-Eddbh->b_bhem n_ tmbn;I-Eddbufft
1ist[cin++]:r bh;p-p-sd} whilea((bu0+= i),
-sds Sbhk_hengnv0+= sectp_),
-sds  Sbhi= bh->b_OHdo_page) !=,hccH/oc-
-sdg fnArequesS;
-	}f-m-s/* CalculaSerOH ubhem foffs6es andAlengnv0we willibeAusiig0*/m-s= MSpg_offs6e/o{p-sddnit.t		b12B,_offs6e;m-m-s,b12B,_offs6e = pg_offs6e0>> sectp__shift;.-s,b12B,_offs6e = pg_offs6e0- (b12B,_offs6e << sectp__shift);.-s,b1k_hengnv0tm(pg_hengnv0+ b12B,_offs6e + pbr->pbr_sread)0>>t-sdc			,	sectp__shift;
-	} S_HWo{p-sdb1k_hengnv0tm(pg_hengnv0+ pbr->pbr_sread)0>> sectp__shift;.-s}f-m-s/* THdonwilliatt-mpttto(makgfafrequesS biggArSOHan0OH usectp_
-	f* snitidf wu>aru wellialigtod.
-se*/m-sdwinch (pb->pb_, rget->pbr_.c ls/o{p-scase 0:p-sdsectp_ tmbhk_hengnv0<< sectp__shift;.-sdb1k_hengnv0tm1;p-sdbe Sk;p-scase PBR_ALIGNED_ONLY:Y-E = MS(pg_offs6e t=,0oA&&a(pglhengnv0t= fsin_CACHE_SIZE/A&&p-sdllllS4(unsigtod _ar)mbn/A& BN_ALIGN_MASK)f==,0oA{p-sdcsectp_ tmbhk_hengnv0<< sectp__shift;.-sddb1k_hengnv0tm1;p-sd	be Sk;p-sd}Y-Ecase PBR_SECTOR_ONLY:Y-E /* Fallthrough,usameAasi /haulte*/m-s /hault:p-sdsectp_ tm10<< sectp__shift;.-s}f-m-s/* If wu>aru doiig0I/Ofl rgerSOHan0OH ubh->b_snitifiBld OH n
-	f* wu>amA|tto(splitiOHdonrequesS up.
-se*/m-swhilea(sectp_ >lS41t a << NBBYf* snitof(bh->b_snitV)A-O1V/o{p-sddectp_ >>tm1;p-sdb1k_hengnv++oc- }c-
-cmulti_ok0tmSbhk_hengnv0!=,1oLY-E_f=,sectp_ >> BBSHIFTLY-
-Emp_ (;mbhk_hengnv0>,0; bu0+= i,mbhk_hengnv--, pg_offs6e0+= sectp_)A{p-sdbh:r kmem_cOt_e_a2_HW(bh_cOt_ep, SLAB_NOFS)LY-E = MS!bhVt-/e	bhf=,_pagebuf_get.prea2_HW_bh()LY-E mems6e(bh, 0, snitof(*bh));.-s,bh->b_bhem n_ tmbn;I-Edbh->b_sniti= sectp_;I-Edbh->b_devi= pbr->pbr_kdev;p-sdsek_bufft
llem ed(bh/;c-	dsek_bh_page(bh, page, pg_offs6eV;p-s =n04_waitqueueloccH(&bh->b_wait);c-sdatomicns6e(&bh->b_c*/in, 1); -sdbufft
1ist[cin++]:r bh;p- }c-
-requesS:m-sifMScin) {p-sdtic 	(*ca2_baB,)(d,* Ok,bufft
loccH *, _ar);c-m-s,cO2_baB,0tmSmulti_ok0&&apublic_bh) ?e-,,,,_pagebuf_Snd_io_p rtial_pages :e-,,,,_pagebuf_Snd_io_completA_pages;c-m-s	/* Acc*/in(forr ddieISFal bufft
s dnntrogress0*/m-s,atomicnadd(cin, &pb->pb_ionrcmainiig);c-m-#if /h RQ_WRITE_ORDEREDY-E = MSflush)m-		dsek_bit(BH_Ordt
 d_Flush, &bufft
1ist[cin-1]->b_st]egm;p-#Snd(+
-c-	dmp_ (if=,0; i0< cin; i++)A{p-sd	bhf=,bufft
1ist[i]LY-E		=n04_bufft
(bh, cO2_baB,, pb/;c-	ddbh->b_rdevi= bh->b_dev;c-	ddbh->b_rsectp_ tmbh->b_bhem n_;m-		dsek_bufft
lmappe (bh/;c-	ddsek_bufft
lasync(bh/;c-	ddsek_bufft
lreq(bh/;c-	ddif (rw0ttmWRITE)e-,,,,sek_bufft
luptou]eg(bhm;c-	d	genericnmakg_requesS(rw, bhV;c-		} -6dr6eirt 0;b-s}c-
-s/*
-	f* We-igafRno0I/Ofto(submit, l6efb/epcV_.Ar know(OHat
-	f* wu>igafRskippe 0tveriOHdontage SntIrely.d-se*/m-sr6eirt 1;I-}b---STATIC ead(p-_pagebuf_pageoapply(m- pageobuf_t		*pb,e-,loff_t		,offs6e,e-,d,* Ok,page		*page,m-sdnit.t			pg_offs6e,m-sdnit.t			pg_hengnv,Y-E_ar	,	last)m-{p-spageobuf_daddr_t	bnt= pb->pb_bn;m-spb_t rget.t		*pbri= pb->pb_, rget;e-,loff_t		,pb_offs6eLY-E_ar	,	d, rus,A12B,iig;c-m-sASSERT(page)LY-EASSERT(pb->pb_.c ls & (PBF_READ|PBF_WRITE));m-m-sifMS(pbr->pbr_bsnit t= fsin_CACHE_SIZE/A&&p-slll (pb->pb_bufft
llengnv0< fsin_CACHE_SIZE/A&&p-slll (pb->pb_.c ls & PBF_READ)A&&apb->pb_lem ed)0{p-sdbu0-tm(pb->pb_offs6ef>> BBSHIFT/;c-		pg_offs6e(= 0ff-o,pglhengnv0t fsin_CACHE_SIZE;m-s} S_HWo{p-sdpb_offs6ef=,offs6e - pb->pb_.ile_offs6eLY-E = MSpb_offs6e/o{p-sd	bu0+= Spb_offs6e0+ BBMASK)f>> BBSHIFTLY-E } -6}b-
-	12B,iigd=,_pagebuf_iolem ed(pb);
-sif (pb->pb_.c ls & PBF_WRITE) {Y-E = MS12B,iigd&& !pb->pb_lem ed)t-sdc12B,_page(page)LY-E s, rusf=,_pagebuf_pageoio(page, pbr, pb, bn,e-,,,,pg_offs6e, pg_hengnv,mWRITE,e-,,,,lasti&&a(pb->pb_.c ls & PBF_FLUSH));
-	} S_HWo{p-sdd,atusf=,_pagebuf_pageoio(page, pbr, pb, bn,e-,,,,pg_offs6e, pg_hengnv,mREAD, 0m;p-s}c-	if (s, rusf&& 12B,iigd&& !(pb->pb_, rget->pbr_bsnit <tfsin_CACHE_SIZE/)t-sdou12B,_page(page)LY-}b---4-
-68	pagebuf_iorequesS
- -
-68	pagebuf_ior quesS is tHeAcor  I/OfrequesS rputiie.d- -	Iyi ssumes OHatAOH ubufft
0is+well-formBd and
-68	mappe 0and , SIy for physical I/O,fuoloke
-68dpagebuf_iod, rt() andApagebuf_iophysio(). ,Thosu
-68	eputiies	ca2_iOHeApagebuf_iodn04iaeg rputiie to(d, rt I/O,
-68	df(it2donpr sete, or e_HWoca2_Apagebuf_iorequesS(Vt- -	dIrectly (++OHeApagebuf_iodn04iaeg rputiie ds+_tyipr sete.d-e*t- -	THdonfuncSISF willibeAresponsible for ensuriigdaccessnto(OH 
-68	pages donred,*ict d whilst-I/Ofdondnntrogress - for hem iig
-68	pagebufs tHeApagebuf hem fdonOH umedi]eor, for non-hem iig
-68	pagebufs tHeApages willibeAlem ed. In OHeA12B,iigdcase w 
-68	amA|tto(us uOHeApagebuf hem fasimultiplepmeta-d]ea bufft
sp-f*	willireft
etc  OH usameApage.
-68/ -il p-pagebuf_iorequesS(			/* d, rt rea2-I/O		*/m-spageobuf_t		*pb/d/* bufft
0to(convey OoSdevice	*/m-{p-sfB_TRACE(pb, "iorequesS",O0V;p-
-sif (pb->pb_.c ls & PBF_DELWRI) {p-sdpagebuf_delw  _queue pb,O1); -sd, dirty0;b-s}c-
-sif (pb->pb_.c ls & PBF_WRITE) {Y-E _pagebuf_wait_oupin(pb);I-E}c-
-spagebuf_hold(pb);m-
- /* S6efb/epc*/in-Oom10in04ially,iOHdonwillistop an-I/O
-	f* completISF ca2_outBwhich-igppenspbeforepwu>igafRs, rtA|p-s * a2_iOHe-I/Of.verSca2_iigdpagebuf_iostre too early.d-se*/m-satomicns6e(&pb->pb_ionrcmainiig,O1); -s_pagebuf_ioapply(pb);I-E_pagebuf_iostre pb,O0V;p-
-spagebuf_r le(pb); -s, dirt 0;b-} -
-4-
-68dpagebuf_iowait
- -
-68	pagebuf_iowait,waits	foriI/Ofto(completApon2OH ubufft
0suppliBd.d- -	It , dirto dmmBdi]egly (++_t-I/Ofdonpendiig. ,In any case, itt, dirto
-68	OH uerror0codh, if( ny,nor00 (++OHere ds+_tuerror.
-68/ -il p-pagebuf_iowait(m-spageobuf_t		*pb/m-{p-sfB_TRACE(pb, "iowait",O0V;p-sifMSatomicnrccH(&pb->pb_ionrcmainiig)mt-/ebhk_run_queues(m;p-sifMS(pb->pb_.c ls & PBF_FS_DATAIOD))p-sdpagebuf_runa2__queues(pagebuf_d]eaiostre_tqm;p-sdown(&pb->pb_iostresBmaV;p-sfB_TRACE(pb, "iowaited",O(long)pb->pb_errorV;I-d, dirtypb->pb_error; -}b---STATIC ead( -
-pagebuf_mapoutllem ed(m-spageobuf_t		*pb/m-{p-stic 			*old_addr,= ct aff-m-sif (pb->pb_.c ls & PBF_MAPPED)b{p-sdif (pb->pb_.c ls & _PBF_ADDR_AL1+CATED)t-sdcold_addr,= pb->pb_addr,- pb->pb_offs6eff-o,pb->pb_addr,= ct aff-o,pb->pb_.c ls &= ~(PBF_MAPPED | _PBF_ADDR_AL1+CATED);I-E}c-
-s, dirtyold_addr;s/* Cal.Ar mustid/ho(OH  addressfspace,e-,,,,f* wu>aru undIS aispiu hem ,ntrobablyt-,,,,f* nok,saf-2to(doAvd/ho(H re
-,,,,f*/ -}b---caddr_t
-pagebuf_offs6e(m- pageobuf_t		*pb,e-,dnit.t			offs6e/t-{e-,d,* Ok,page		*pageff-m-soffs6e0+= pb->pb_offs6eff-m- pagei= pb->pb_pages[offs6ef>> fsin_CACHE_SHIFT];I-d, dirty(caddr_t/ pageoaddress(page) + (offs6e & (Psin_CACHE_SIZEA-O1V/;b-} -
-4-
-68dpagebuf_iomoved-e*t- -	Move2d]ea into(p_ out Sf(  bufft
.
- -/--
-		
-pagebuf_iomove(m- pageobuf_t		*pb,d/* bufft
0to(process		*/m-sdnit.t			b_Pf,d/* d, rtiigdbufft
0offs6e	*/m-sdnit.t			bsnit,c/* lengnv0to(copy		*/m-scaddr_t	,	d]ea,c/* d]ea address			*/m-spageobuf_rw_t	,mode)d/* , ad/w     .c l		*/m-{p-sdnit.t			bend,Icp_Pf,Acdnit;e-,d,* Ok,page		*pageff-m-sbSnd tmb_Pf0+ bdnit;e-,whilea(b_Pf0< bendoA{p-sdpagei= pb->pb_pages[pageobuf_btoct(b_Pf0+ pb->pb_offs6e)]LY-E	cp_Pf,= pageobuf_p_Pf(b_Pf0+ pb->pb_offs6e)LY-E	csniti= min_t(enit.t,
-sds      Psin_CACHE_SIZE-cp_Pf,Apb->pb_c*/in_desirA|-b_Pf);c-m-s,ASSERT(((csniti+Icp_Pf) <= fsin_CACHE_SIZE/);c-m-s,dwinch (mode)A{p-sdcase PBRW_ZERO:e-,,,mems6e(pageoaddress(page) + cp_Pf,A0,Acdnit/;c-	ddbe Sk;p-sdcase PBRW_READ:e-,,,memcpy(d]ea, pageoaddress(page) + cp_Pf,Acdnit/;c-	ddbe Sk;p-sdcase PBRW_WRITE:e-,,,memcpy(pageoaddress(page) + cp_Pf,Ad]ea, cdnit/;c-	d} -p-ssb_Pf0+=Acdnit;e-,	d]ea +=Acdnit;e-,}Y-}
---4-
-68	_pagebuf_ioapplyd-e*t- -	AppliBs _pagebuf_pageoapply0to(eOt_ntage o++OHeApageobuf_t.
-e*/--STATIC ead(p-_pagebuf_ioapply(			/* apply0funcSISF to pages	*/m-spageobuf_t		*pb/d/* bufft
0to(examiie		*/m-{p-s_ar	,	indIx;e-,loff_t		,bufft
loffs6e = pb->pb_.ile_offs6eLY-Ednit.t			bufft
llen = pb->pb_c*/in_desirA|LY-Ednit.t			pageooffs6e, len;m-sdnit.t			curooffs6e, curolen;m-
-	curooffs6e = pb->pb_offs6eLY-Ecurolenf=,bufft
olen;m-
-	if (!pb->pb_lem edb&&p-slll (pb->pb_, rget->pbr_bsnit <tfsin_CACHE_SIZE/)A{p-sdmp_ (indIxB= 0; indIxB< pb->pb_page_c*/in; indIx++)e-,,,12B,_page(pb->pb_pages[indIx]);p-sdpb->pb_lem edb=,1;I-E}c-
-smp_ (indIxB= 0; indIxB< pb->pb_page_c*/in; indIx++)b{p-sdif (curolenf==,0o -sd	be Sk;p-sdifMScurooffs6e >= fsin_CACHE_SIZE/A{p-sd	curooffs6e -t fsin_CACHE_SIZE;m-sc	conninue;p-s	} -p-sspageooffs6eB= curooffs6e;p-sdcurooffs6e = 0;.-m-s	lenf=,Psin_CACHE_SIZEA-Opageooffs6e;p-sdifMSlen >tcurolen)e-,,,1enf=,curolen;m-	Ecurolenf-tmlen;m-Y-E _pagebuf_pageoapply(pb, bufft
loffs6e,e-,,,,pb->pb_pages[indIx], pageooffs6e, len,e-,,,,indIxB+m10== pb->pb_page_c*/in); -sdbufft
_offs6e0+= len;m-	Ebufft
llen -tmlen;m-s}c-
-s/*
-	f* Run OH ubhem fdevice2task queue0H re,pwhileawu>igafp-s * aihold onfb/eppagebuf (importain-OomigafROHatAhold).
-se*/m-sif (pb->pb_.c ls & PBF_RUN_QUEUES/ {p-sdpb->pb_.c ls &= ~PBF_RUN_QUEUES;p-sdifMSatomicnrccH(&pb->pb_ionrcmainiig) >t1mt-/e	bhk_run_queues(m;p-s}Y-}
-----4-
-68 Pagebuf delay d w     bufft
0handliig
-68/--
-STATIC LIST_HEAD(pbd_delw  te_queuem;p-STATIC dpiu12B,_t pbd_delw  te_l2B,0= SPIN_1+af_UN1+afED;
---STATIC ead(p-pagebuf_delw  _queue m- pageobuf_t		*pb,e-,_ar	,	uu12B,/m-{p-sfB_TRACE(pb, "delw  _q",O(long)uu12B,/;m-sdpiu_l2B,(&pbd_delw  te_l2B,/;m-s/* If ale SIy dn2OH uqueue, dequeue0andAplace,an-Oaile*/m-sif (!list_(mpty(&pb->pb_1istV)b{p-sdif (uu12B,/A{p-sdcatomicndec(&pb->pb_hold);c-sd} -6dlist_del(&pb->pb_1istV;m-s}c-
-slist_add_Oail(&pb->pb_1ist, &pbd_delw  te_queuem;p-dpb->pb_.cushbtch = jiffiBs + xfs_ageobufft
;m-sdpiu_ou12B,(&pbd_delw  te_l2B,/;m-
-dif (uu12B,/p-sdpagebuf_ou12B,(pb);I-}
---
-		
-pagebuf_delw  _dequeue(m-spageobuf_t		*pb/m-{p-sfB_TRACE(pb, "delw  _uq",O0V;p-sdpiu_l2B,(&pbd_delw  te_l2B,/;m-slist_del_in04(&pb->pb_1istV;m-spb->pb_.c ls &= ~PBF_DELWRI;m-sdpiu_ou12B,(&pbd_delw  te_l2B,/;m-}
-----4-
-68 T/eppagebuf iostre d]emSFs
-68/--
-STATIC il p-pagebuf_iostre_d]emSF(
-,tic 			*__bind_cpu,e-,consS cha
		*namg,e-,_ar	,	pagebuf_d]emSFs[],e-,d,* Ok,listloccHEpagebuf_iostre_tq[],e-,wait_queueloccH_t	pagebuf_iostre_wait[]/m-{I-E_ar	,	bind_cpu, cpu;m-sDECLARE_WAITQUEUE	(wait, currete);c-
-cbind_cpu,= (iin) (long)__bind_cpuLY-Ecpu,= CPU_TO_DAEMON(cpu_12gical_map(bind_cpuV)2.-p-s/*  S6efup,OH uche SIue*/m-s ]emSFnit()2.-p-s/* Aead( sigtals */m-sdngread_l2B,(V;p-sdigfills6e(&currete->blem edV;p-s_nrccalc_digpendiig(currete);c-sdngread_ou12B,()2.-p-s/* MigraSerOorOH uright CPU */m-smigraSe_to_cpu(cpum;p-#if /h __HAVE_NEW_SCHEDULER
-dif (smp_processor_id()0!=,cpump-sdBUG(m;p-#Slsu
-swhilea(smp_processor_id()0!=,cpump-sdst_edul (m;p-#Snd(+
-c-	spriitf(currete->comm, "%s/%d",Onamg, bind_cpuV;c-sINIT_LIST_HEAD(&pagebuf_iostre_tq[cpu]);p-s=n04_waitqueueloccH(&pagebuf_iostre_wait[cpu]);p-s_ns6e_currete_st]eg(TASK_INTERRUPTIBLE);p-smb()2.-p-spagebuf_d]emSFs[cpu](= 1_b-p-smp_ (;;)A{p-sdadd_wait_queue(&pagebuf_iostre_wait[cpu], &wait)LY-p-sdif (TQ_ACTIVE(pagebuf_iostre_tq[cpu])mt-/e	_ns6e_task_st]eg(currete, TASK_RUNNING)LY-E st_edul (m;p-s	r6move_wait_queue(&pagebuf_iostre_wait[cpu], &wait)LY-s	run_task_queue(&pagebuf_iostre_tq[cpu]);p-ssif (pagebuf_d]emSFs[cpu](==,0o -sd	be Sk;p-sd_ns6e_currete_st]eg(TASK_INTERRUPTIBLE);p-s}.-p-spagebuf_d]emSFs[cpu](= -1;I-Ewakg_up_inSt
ruptible(&pagebuf_iostre_wait[cpu]);p-s, dirt 0;b-} -
-STATIC ead(p-pagebuf_runa2__queues(e-,d,* Ok,listloccHEpagebuf_iostre_tq[]/m-{I-E_ar	pcpu, cpu;m-p-smp_ (cpu,= 0; cpu,< min(smp_num_cpus, MAX_IO_DAEMONS); cpu++)b{p-sdpcpu,= CPU_TO_DAEMON(cpu_12gical_map(cpuV)2.-p-s	run_task_queue(&pagebuf_iostre_tq[pcpu]);p-s}b-} -
-STATIC il p-pagebuf_12giostre_d]emSF(
-,tic 			*__bind_cpu/m-{I-Er6eirt pagebuf_iostre_d]emSF(__bind_cpu, "xfs12gd",tpb_12gio_d]emSFs,e-,,,pagebuf_12giostre_tq,mpagebuf_logiostre_waitV;I-}b---STATIC il p-pagebuf_d]eaiostre_d]emSF(
-,tic 			*__bind_cpu/m-{I-Er6eirt pagebuf_iostre_d]emSF(__bind_cpu, "xfsd]ead",tpb_d]eaio_d]emSFs,e-,,,pagebuf_d]eaiostre_tq,mpagebuf_d]eaiostre_wait/;m-}
-----4- D/homes	mp_ pagebuf d]emSFe*/--STATIC DECLARE_COMPLETION4pagebuf_d]emSF_stre);c-STATIC d,* Ok,task_st* Ok,*pagebuf_d]emSF_task;--STATIC il  pagebuf_d]emSF_active;--STATIC il  forcc_.cush;
---STATIC ead(p-pagebuf_d]emSF_wakgup(ead()m-{p-s.orcc_.cushb=,1;I-Ebarrier(m;p-swakg_up_process4pagebuf_d]emSF_tead);I-}b---STATIC il p-pagebuf_d]emSF(
-,tic 			*d]ea/m-{I-E_ar	,	c*/in;b-	pageobuf_t		*pb;.-Ed,* Ok,listloccHE*curr, *amxe, tmp2.-p-s/*  S6efup,OH uche SIue*/m-s ]emSFnit()2.-p-s/* Mark ittactive */m-spagebuf_d]emSF_teadf=,currete;m-spagebuf_d]emSF_active =,1;I-Ebarrier(m;p-p-s/* Aead( sigtals */m-sdngread_l2B,(V;p-sdigfills6e(&currete->blem edV;p-s_nrccalc_digpendiig(currete);c-sdngread_ou12B,()2.-p-sd,*cpy(currete->comm, "xfsbufd");p-scurrete->.c ls |= PF_MEMAL1+C2.-p-sINIT_LIST_HEAD(&tmpm;p-sdoo{p-sddee_currete_st]eg(TASK_INTERRUPTIBLE);p-s st_edul _btchout(xfs_.cush_inSt
va.m;c-m-s,dpiu_l2B,(&pbd_delw  te_l2B,/;m-m-	Ec*/in = 0ff-o,listl.or_eOt__saf-(curr, amxe, &pbd_delw  te_queuem {p-sdcpbf=,list_(ntry(curr, pageobuf_t,tpb_1istV;m-p-sdcfB_TRACE(pb, "walkq1",O(long)pagebuf_ispin(pb)V;m-p-sdcifMS(pb->pb_.c ls & PBF_DELWRI) &&p-sds     !pagebuf_ispin(pb)d&& !pagebuf_cond_12B,(pb)) {p-sdcsif (!.orcc_.cushb&&p-sdss    btch_before(jiffiBs,Apb->pb_.cushbtch)) {p-sdcscpagebuf_ou12B,(pb);I-EEsd	be Sk;p-sds	} -p-sssdpb->pb_.c ls &= ~PBF_DELWRI;m-sssdpb->pb_.c ls |= PBF_WRITE;m-sssdlist_move(&pb->pb_1ist, &tmpm;p-s	,	c*/in++oc- sd} -6d}c-m-s,dpiu_ou12B,(&pbd_delw  te_l2B,/;m-	swhilea(!list_(mpty(&tmpmm {p-sdcpbf=,list_(ntry(tmp.amxe, pageobuf_t,tpb_1istV;m-	dslist_del_in04(&pb->pb_1istV;m-p-sdcpagebuf_iod,*ategy(pb);p-s	} -p-ssifMSas_1ist_len >t0/c-sdcpurgeoaddresses(m;p-s	ifMSc*/in)
-/e	bhk_run_queues(m;p-
-sdmp_cc_.cushb=,0;b-s} whilea(pagebuf_d]emSF_activem;p-
-scompletA_and_ex04(&pagebuf_d]emSF_stre,O0V;p-}b---
-		
-pagebuf_delw  _.cush(m-spb_t rget.t		*t rget,c-su_12ng			.c ls,I-E_ar	,	*piuptrVm-{p-spageobuf_t		*pb;c-Ed,* Ok,listloccHE*curr, *amxe, tmp2.-,_ar	,	pinc*/in = 0ff-oinr	,	flush_cin = 0LY-m-spagebuf_runa2__queues(pagebuf_d]eaiostre_tqm;p-spagebuf_runa2__queues(pagebuf_12giostre_tq)2.-p-sdpiu_l2B,(&pbd_delw  te_l2B,/;m-sINIT_LIST_HEAD(&tmpm;p-m-slist_.or_eOt__saf-(curr, amxe, &pbd_delw  te_queuem {p-sdpbf=,list_(ntry(curr, pageobuf_t,tpb_1istV;m-p-sd/*p-sd * Skip oOH rnc rgets,Amarkt
s andndnntrogress bufft
sp-,,f*/ -p-s	ifMS(pb->pb_.c ls ==,0oA|| (pb->pb_t rget,!=,t rget) ||p-ssllll!Spb->pb_.c ls & PBF_DELWRI)/A{p-sd	conninue;p-s	} -p-ssfB_TRACE(pb, "walkq2",O(long)pagebuf_ispin(pb)V;m-ssif (pagebuf_ispin(pb)V {p-sdcpinc*/in++oc- sdconninue;p-s	} -p-sspb->pb_.c ls &= ~PBF_DELWRI;m-sspb->pb_.c ls |= PBF_WRITE;m-sslist_move(&pb->pb_1ist, &tmpm;p-p-s}b-	p-s/* ok foundAa2_iOHe- temsttHatAcan,be work dpon2
-s sydrop OH nhem fandAprocess2OH Spriv]eg,list */m-sdpiu_ou12B,(&pbd_delw  te_l2B,/;m-	m-slist_.or_eOt__saf-(curr, amxe, &tmpm {p-sdpbf=,list_(ntry(curr, pageobuf_t,tpb_1istV;m-		m-ssif (.c ls & PBDF_WAIT/c-sdcpb->pb_.c ls &= ~PBF_ASYNC;p-sdSlsu
-sdslist_del_in04(currV;m-p-sdpagebuf_12B,(pb);I-EEpagebuf_iod,*ategy(pb);p-m-ssif (++flush_cin > 32/o{p-sd	bhk_run_queues(m;p-s		flush_cin = 0LY-E } -6}b-
-	bhk_run_queues(m;p-
-s/* mustirun,list OH usecon|tttch eveinif PBDF_WAIT isn't
-	f* fnAres6e0a2_iOHeApb_1ist poinSt
s	
-se*/m-swhilea(!list_(mpty(&tmpmm {p-sdpbf=,list_(ntry(tmp.amxe, pageobuf_t,tpb_1istV;m-m-sslist_del_in04(&pb->pb_1istV;m-s	I-EEpagebuf_iowait(pb);m-sdif (!pb->pb_rS_HW/c-sdcpagebuf_ou12B,(pb);I-EEpagebuf_r le(pb); -s}Y-
-sif (piuptrVm-,	*piuptr = pinc*/in;I-}b---STATIC il p-pagebuf_d]emSF_d, rt(ead()m-{p-siar	,cpu, pcpu;m-p-skt
nel_che SI(pagebuf_d]emSF, ct a, CLONE_FS|CLONE_FILES|CLONE_VM);m-p-smp_ (cpu,= 0; cpu,< min(smp_num_cpus, MAX_IO_DAEMONS); cpu++)b{p-sdpcpu,= CPU_TO_DAEMON(cpu_12gical_map(cpuV)2.-p-s	if (kt
nel_che SI(pagebuf_12giostre_d]emSF,e-,,,,(ead( *)(long) cpu,e-,,,,CLONE_FS|CLONE_FILES|CLONE_VM),< 0oA{p-sdcpriitk("pagebuf_12giostre d]emSFe.ailed to(d, rt\n");p-ss} S_HWo{p-sdewhilea(!pb_12gio_d]emSFs[pcpu])e-,,,,yiBld()LY-E } -6}b-smp_ (cpu,= 0; cpu,< min(smp_num_cpus, MAX_IO_DAEMONS); cpu++)b{p-sdpcpu,= CPU_TO_DAEMON(cpu_12gical_map(cpuV)2.-p-s	if (kt
nel_che SI(pagebuf_d]eaiostre_d]emSF,e-,,,,(ead( *)(long) cpu,e-,,,,CLONE_FS|CLONE_FILES|CLONE_VM),< 0oA{p-sdcpriitk("pagebuf_d]eaiostre d]emSFe.ailed to(d, rt\n");p-ss} S_HWo{p-sdewhilea(!pb_d]eaio_d]emSFs[pcpu])e-,,,,yiBld()LY-E } -6}b-s, dirt 0;b-} -
-4-
-68 pagebuf_d]emSF_stopd-e*t- - Notn:,do+_tyimarkfasi__ex04,(it2donca2_e ,.verSpagebuf_St
minate.
-e*/--STATIC ead(p-pagebuf_d]emSF_stop(ead()m-{p-siar	,cpu, pcpu;m-p-spagebuf_d]emSF_active =,0;I-Ebarrier(m;p-swait_.or_completISF(&pagebuf_d]emSF_stre);m-p-smp_ (pcpu,= 0; pcpu,< min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++)b{p-sdcpu,= CPU_TO_DAEMON(cpu_12gical_map(pcpuV)2.-p-s	pb_12gio_d]emSFs[cpu](= 0LY-E wakg_up(&pagebuf_logiostre_wait[cpu]);p-sswait_eveit_inSt
ruptible(pagebuf_logiostre_wait[cpu],e-,,,,pb_12gio_d]emSFs[cpu](== -1)2.-p-s	pb_d]eaio_d]emSFs[cpu](= 0LY-E wakg_up(&pagebuf_d]eaiostre_wait[cpu]);p-sswait_eveit_inSt
ruptible(pagebuf_d]eaiostre_wait[cpu],e-,,,,pb_d]eaio_d]emSFs[cpu](== -1)2.-s}Y-}
-----STATIC il p-pagebuf_shakgr(iinfnumbt
,fuosigtod _ar read)m-{p-spagebuf_d]emSF_wakgup();p-s, dirt 0;b-} -
---4-
-68	In04ialni]eISF andATt
minatISF
-68/--
-_ar __in04p-pagebuf_in04(ead()m-{p-siar	,	i; - - pagebuf_cOt_e:r kmem_cOt_e_ce Seg("pageobuf_t", snitof(pageobuf_t),A0,e-,,,SLAB_HWCACHE_ALIGN, ct a, ct aoLY-sif (pagebuf_cOt_e:r= ct a)b{p-sdpriitk("pagebuf:pc*/ldn't0in04 pagebuf cOt_e\n");p-sspagebuf_St
minate(m;p-s	r6dirt -ENOMEM; -s}Y-
-sif (_pagebuf_prea2_HW_bh(NR_RESERVED_BHV,< NR_RESERVED_BHV,{p-sdpriitk("pagebuf:pc*/ldn't0pre-a2_HW]eg %d bufft
0hcads\n",e-,,,NR_RESERVED_BHV;p-sspagebuf_St
minate(m;p-s	r6dirt -ENOMEM; -s}Y-
-sin04_waitqueueloccH(&pb_rSsv_bh_wait)LY-p-smp_ (if=,0; i0< NHASH; i++)A{p-sddpiu_l2B,_in04(&pbhash[i].pb_hash_12B,V;c-sdINIT_LIST_HEAD(&pbhash[i].pb_hash); -s}Y-
-#if /h PsinBUF_TRACE - pagebuf_,*aceobuf:r k,*aceoa2_HW(PsinBUF_TRACE_SIZE, KM_SLEEPm;p-#Snd(+
-c-	pagebuf_d]emSF_d, rt(); -skmem_shakg_rSgister(pagebuf_shakgr);p-s, dirt 0;b-} -
-4-
-68dpagebuf_St
minate.
-e*
-68	Notn:,do+_tyimarkfasi__ex04,(OHdondsfalsonca2_e ,.verSOHeA__in040codh.
- -/--
-		
-pagebuf_St
minate(ead()m-{p-spagebuf_d]emSF_stop()LY-p-#if /h PsinBUF_TRACE - k,*aceod/ho(pagebuf_,*aceobufm;p-#Snd(+
-c-	kmem_cOt_e_ded,*oy(pagebuf_cOt_e); -skmem_shakg_dt
 gister(pagebuf_shakgr);p-}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsobuf.h linux-2.4.27-rc4/fs/xfs/linux/xfsobuf.h
--- linux-2.4.26/fs/xfs/linux/xfsobuf.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsobuf.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,665 +0,0 @@
-4-
-68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-4-
-68 W   ten}byrStmve Lord, Jim Mostek, RusselliCatt-lan,at SGI
- -/--
-#ifn /h __XFS_BUF_H__
-# /home __XFS_BUF_H__
-
-#include <linux/versISF.h>
-#include <linux/config.h>
-#include <linux/1ist.h>
-#include <linux/types.h>
-#include <linux/dpiu12B,.h>
-#include <asm/dystem.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/uio.h>
---4- npt_Apanch changes wher  OH usngread_l2B,ndsfd/homed -/--#if /h CLONE_SIGNAL /* d,2B,n-/--# /home dngread_l2B,(VE dpiu_l2B,_irq(&currete->dngread_l2B,m;p-# /home dngread_ou12B,() dpiu_ou12B,_irq(&currete->dngread_l2B,m;p-# /home _nrccalc_digpendiig(x)	rccalc_digpendiig(x)p-#Slsu 4- npt_A-/--# /home dngread_l2B,(VE dpiu_l2B,_irq(&currete->dnghand->dngl2B,m;p-# /home dngread_ou12B,() dpiu_ou12B,_irq(&currete->dnghand->dngl2B,m;p-# /home _nrccalc_digpendiig(x)	rccalc_digpendiig()p-#Snd(+
-4-
-68dBas uOypes
- -/--
-4- daddr mustibe dngmed sitc  -1ndsfuse }mp_ bmapsttHatAaru nok,y6e0a2_HW]egd -/--Oype /h loff_t pageobuf_daddr_tLY-p-# /home fsin_BUF_DADDR_ct aMS(pageobuf_daddr_t) (-1 a))Y-p-# /home pageobuf_ctob(pp)	((pp)68 Psin_CACHE_SIZE/ -# /home pageobuf_btoc(dd)	(((dd) +,Psin_CACHE_SIZEA-O1)f>> fsin_CACHE_SHIFT/ -# /home pageobuf_btoct(dd)	((dd) >> fsin_CACHE_SHIFT/ -# /home pageobuf_p_Pf(aa)	((aa) & ~fsin_CACHE_MASK)Y-p-Oype /h enum pageobuf_rw_Wo{p-sPBRW_READ =,1,			/* ,*ansft
,iuOorO rget,memory */m-sPBRW_WRITE =,2,			/* ,*ansft
,.verSO rget,memory */m-sPBRW_ZERO =,3			/* ZerorO rget,memory */m-} pageobuf_rw_tLY-p-p-Oype /h enum pageobuf_.c ls_Wo{		/* pb_.c ls values */m-sPBF_READ =,(10<< 0),d/* bufft
0inStnde }mp_ e SIiigd.verSdevice2*/m-sPBF_WRITE =,(10<< 1),d/* bufft
0inStnde }mp_ w   iig0Ooudevice2 2*/m-sPBF_MAPPED =,(10<< 2),  /* bufft
0mappe 0(pb_addr,val		)           */m-sPBF_fsRTIALt=,(10<< 3), /* bufft
0p rtially e SIueeeeeeeeeeeeeeeeee*/m-sPBF_ASYNCf=,(10<< 4),   /* dn04iaep_ willi_tyiwait,foricompletISF e*/m-sPBF_NONEf=,(10<< 5),    /* bufft
0_tyie SIuayia2_Aeeeeeeeeeeeeeeeee*/m-sPBF_DELWRIf=,(10<< 6),  /* bufft
0hasi irtyApages eeeeeeeeeeeeeeeee*/m-sPBF_STALE =,(10<< 10),d/* bufft
0hasibeou0staled, do+_tyifindAitte*/m-sPBF_FS_MANsinD =,(10<< 11), /* .iledystem connrolsfd/hoiig0memory e*/m-sPBF_FS_DATAIOD =,(10<< 12), /* st_edul  IOfcompletISFpon2fsAd]eaIue*/m-
-s/* .c ls us dponly,asfargumSntsnto(accessneputiies	*/m-sPBF_1+af =,(10<< 13),d/* 12B,pr quesSeddss   */m-sPBF_TRY1+af =,(10<< 14), /* 12B,pr quesSed, but do+_tyiwaits   */m-sPBF_DONT_B1+af =,(10<< 15), /* do+_tyibhem fin,currete che SIs   */m-
-s/* .c ls us dponly,inSt
nally */m-s_PBF_fsinCACHE =,(10<< 16),d/* bam edbby pagecOt_ess   */m-s_PBF_fRIVATE_BH =,(10<< 17), /* do+_tyius upublic bufft
0hcadss   */m-s_PBF_ALL_fsinS_MAPPED =,(10<< 18), /* a2_Apageondnnrange mappe s   */m-s_PBF_ADDR_AL1+CATED =,(10<< 19), /* pb_addr,space,was0a2_HW]egds   */m-s_PBF_MEM_AL1+CATED =,(10<< 20), /* undISlyiigdpagesraru a2_HW]egd  */m-s_PBF_MEM_SLAB =,(10<< 21), /* undISlyiigdpagesraru slab a2_HW]egd  */m-m-sPBF_FORCEIO =,(10<< 22), /* ngmorepany cat_e:st]egss   */m-sPBF_FLUSH =,(10<< 23),d/* .cushbdiskfw     cOt_ess   */m-sPBF_READ_AHEADf=,(10<< 24), /* asynchronousie SI-aoccHEs   */m-sPBF_RUN_QUEUESf=,(10<< 25), /* run,bhem fdevice2task queues   */m-sPBF_DIRECTIO =,(10<< 26), /* use }mp_ a direct IOfmappiigs   */m-
-} pageobuf_.c ls_tLY-p-# /home fBF_UPDATE (PBF_READf|tPBF_WRITE)p-# /home fBF_NOT_DONE(pb)d(S(pb)->pb_.c ls & (PBF_fsRTIAL|PBF_NONE/)0!=,0)p-# /home fBF_DONE(pb)d(S(pb)->pb_.c ls & (PBF_fsRTIAL|PBF_NONE/)0==,0o -p-# /home fBR_SECTOR_ONLY	1s/* only,us usectp_ snit bufft
0hcadsA-/--# /home PBR_ALIGNED_ONLY 2s/* only,us ualigtod-I/Of*/m-
-Oype /h d,* Ok,pb_t rget,{p-siar	,	pbr_.c ls; -sdev_r	,	pbr_dev;c-	kdev_r	,	pbr_kdev;p-sd,* Ok,b12B,_device	*pbr_bdev;p-sd,* Ok,address_space	*pbr_mappiig;p-sunsigtod _ar	,pbr_bsnit;p-sunsigtod _ar	,pbr_sshiftLY-Ednit.t			pbr_sread;
-} pb_t rget.t; -
-4-
-68dpageobuf_t:  Bufft
0s,* OkureSmp_ page cOt_e-bas dpbufft
sp-f*
-68 T/donbufft
0s,* OkureSdsfuse }byrOH upage cOt_e bufft
0managemSntneputiies
-68 fnAreft
0to(an,assembly o++pagesrformiigdanlogical bufft
. ,Th uactuSl
-68 I/OfdonperformBd winv2bufft
loccH p_ bio0s,* Okures,,asfrequirA|}byrdrivers,
- - mp_ driversBwhich-do+_tyiundISst]n|ttHdons,* Okure. ,Th ubufft
0s,* OkureSds
- - us dpon2Oemporary.basis only, andAdiscard d whenireleas d.d- -
-68 T/e rea2-d]ea storage donrecord d inrOH upage cOt_e. ,MeeaI]ea is
- - hashed to(OHe- nodh mp_ OH ubhem fdevice2SF which-OH  fileadystem resides.
-68 FileaI]ea is hashed to(OHe- nodh mp_ OH u.ile.  Pages which-are2SFlyd-e*0p rtially fillBd winv2I]ea igafRbits	s6e in,OH ir,b12B,_map (ntry
-68 fnAindiW]eg which-diskfb12B,s inrOH upage aru nok,val		.
-f*/m-
-d,* Ok,pageobuf_s; -Oype /h ead( (*pageobuf_iostre_t)(d,* Ok,pageobuf_s *m;p-s		/* call-baB,0funcSISF onnI/OfcompletISF -/--Oype /h ead( (*pageobuf_rS_HW_t)(d,* Ok,pageobuf_s *m;p-s		/* call-baB,0funcSISF onnI/OfcompletISF -/--Oype /h _ar (*pageobuf_bdd,*at_t)(d,* Ok,pageobuf_s *m;p---# /home PB_fsinS	4m-
-Oype /h d,* Ok,pageobuf_s {p-sd,* Ok,sBmaphore,pb_sBma;s/* sBmaphore for hem ables e*/m-sunsigtod 12ng		pb_.cushbtch;s/* ttch fnA.cushbpagebuf    */m-satomicnr	,pb_piu_c*/in;s/* piu c*/inssllll*/m-swait_queueloccH_t	pb_waitt
s;s/* oupin waitt
ssllll*/m-sd,* Ok,listloccHEpb_1ist;p-spageobuf_.c ls_t	pb_.c ls;d/* d, rusf.c ls */m-sd,* Ok,listloccHEpb_hash_1ist;p-sd,* Ok,pb_t rget	*pb_, rget;d/* 12gical objece */m-satomicnr	,pb_hold;d/* , ft
etc  c*/in */m-spageobuf_daddr_t	pb_bn;		/* bhem fnumbt
2foriI/Of*/m-sloff_t		,pb_.ile_offs6eLs/* oPfs6e in,filea*/m-sdnit.t			pb_bufft
llengnv; /* snit o++bufft
0in}bytesa*/m-sdnit.t			pb_c*/in_desirA|L /* desirA| ,*ansft
,snit */m-stic 			*pb_addrLs/* virtuSl.addressfo++bufft
0*/m-sd,* Ok,tq_st* Ok	pb_iostre_st_ed;m-satomicnr	,pb_ionrcmainiig;/* #putst]n|iig0I/OfrequesSs */m-spageobuf_iostre_t	pb_iostreLs/* I/OfcompletISF funcSISF */m-spageobuf_rS_HW_t	pb_rS_HW;d/* , leasiigd.uncSISF */m-spageobuf_bdd,*at_t,pb_s,*at;s/* pre-w     .uncSISF */m-sd,* Ok,sBmaphore,pb_iostresBma; /* S6maphore for I/Ofwaitt
s */m-stic 			*pb_fspriv;p-stic 			*pb_fspriv2;p-stic 			*pb_fspriv3;p-sunsigtod shorr	,pb_error;d/* error0codh onnI/Of*/m-sunsigtod shorr	,pb_pageoc*/in;s/* snit o++page arrayf*/m-sunsigtod shorr	,pb_offs6eLs/* page oPfs6e in,first,page */m-sunsigtod cha
		pb_lem edLs/* page arrayfis lem edb*/m-sunsigtod cha
		pb_hash_indIx;s/* hash2table indIx	*/m-sd,* Ok,page		**pb_pages;s/* arrayfo++page poinSt
s	*/m-sd,* Ok,page		*pb_pageoarray[PB_fsinS]; /* dnlome pages -/--#if /h PsinBUF_1+af_TRACKINGp-siar	,	pb_last_holdt
;m-#Snd(+
-} pageobuf_tLY-p-p-/* FindiigdandAR SIiigdBufft
s */m-
-exSt
n pageobuf_t,*pagebuf_find(d/* .indfbufft
}mp_ bhem fif	*/m-s,,sd/* OH ubhem fdondnnmemory	*/m-s,d,* Ok,pb_t rget,*,d/*  nodh mp_ bhem 		*/m-ssloff_t,			/* d, rtiigd_Pfs6e o++range	*/m-s,dnit.t,			/* lengnv0o++range		*/m-s,pageobuf_.c ls_t);c/* PBF_1+af			*/m-
-exSt
n pageobuf_t,*pagebuf_get(		/* a2_HW]eg a bufft
		*/m-s,d,* Ok,pb_t rget,*,d/*  nodh mp_ bufft
		*/m-s,loff_t,			/* d, rtiigd_Pfs6e o++rangeeeeee*/m-s,dnit.t,			/* lengnv0o++rangeeeeeeeeeeeeeee*/m-s,pageobuf_.c ls_t);c/* PBF_1+af, PBF_READ,		*/m-s,,sd/* PBF_ASYNC			*/m-
-exSt
n pageobuf_t,*pagebuf_lookup(m-s,d,* Ok,pb_t rget,*,m-ssloff_t,			/* d, rtiigd_Pfs6e o++range	*/m-s,dnit.t,			/* lengnv0o++range		*/m-s,pageobuf_.c ls_t);c/* PBF_READ, PBF_WRITE,		*/m-s,,sd/* PBF_FORCEIO, 		*/m-
-exSt
n pageobuf_t,*pagebuf_get_(mpty(	/* a2_HW]eg pagebuf d,* Ok,winv	*/m-s,,sd/* +_tumemory p_ diskfaddress	*/m-s,dnit.t len,e-,,d,* Ok,pb_t rget,*);c/* m*/in poinS "fake"  nodh	*/m-
-exSt
n pageobuf_t,*pagebuf_get_no_daddr(/* a2_HW]eg pagebuf d,* Ok	*/m-s,,sd/* winvout diskfaddress		*/m-s,dnit.t len,e-,,d,* Ok,pb_t rget,*);c/* m*/in poinS "fake"  nodh	*/m-
-exSt
n il  pagebuf_associ]eg_memory(m-s,pageobuf_t,*,m-ssead( *,m-s,dnit.tm;p---exSt
n ead( pagebuf_hold(	d/*  ncremSntne ft
etc  c*/in	*/m-s,pageobuf_t,*);cd/* bufft
0to(hold		*/m-
-exSt
n ead( pagebuf_e SIaoccH(	d/* e SIuaoccH iuOorcOt_es*/m-s,d,* Ok,pb_t rget,,*,d/* t rget,mp_ bufft
 (p_ ct a)	*/m-s,loff_t,			/* d, rtiigd_Pfs6e o++rangeeeeee*/m-s,dnit.t,			/* lengnv0o++rangeeeeeeeeeeeeeee*/m-s,pageobuf_.c ls_t);c/*  ddieISFal e SIu.c ls	-/--
-4- R leasiigdBufft
s */m-
-exSt
n ead( pagebuf_d/ho(	c/* dea2_HW]eg a bufft
		*/m-s,pageobuf_t,*);cd/* bufft
0to(dea2_HW]eg		*/m-
-exSt
n ead( pagebuf_e le(	d/* e leas uhold onfa bufft
	*/m-s,pageobuf_t,*);cd/* bufft
0to(e leas 		-/--
-4- L2B,iigdandAUn12B,iigdBufft
s */m-
-exSt
n il  pagebuf_cond_12B,(	d/* 12B,pbufft
,+(++_ty lem ed	*/m-s,,sd/* (, dirto -nBUSY+(++lem edV	*/m-s,pageobuf_t,*);cd/* bufft
0to(hem 		*/m-
-exSt
n il  pagebuf_12B,_value(	d/* e dirt c*/in(on hem 		*/m-sspageobuf_t,*);eeeeeeeeee/* bufft
0to(cheB,peeeeeeeeeeeee*/m-
-exSt
n il  pagebuf_12B,(	d/* 12B,pbufft
 eeeeeeeeeeeeeeeee*/m-sspageobuf_t,*);eeeeeeeeee/* bufft
0to(12B,ppeeeeeeeeeeeee*/m-
-exSt
n ead( pagebuf_ou12B,(	s/* ou12B,pbufft
		*/m-s,pageobuf_t,*);cd/* bufft
0to(ou12B,		-/--
-4- Bufft
0R SIuandAW     Rputiies	*/m-
-exSt
n ead( pagebuf_iostre cd/* markfbufft
0I/Ofcomplete	*/m-s,pageobuf_t,*,cd/* bufft
0to(mark		*/m-s,il ,			/* us uI]ea/12g helpIS OHe SI.	*/m-s,il );cd	/* run,completISF _HW]lly,ior _a
-s,,sd * aihelpIS OHe SI.		*/m-
-exSt
n ead( pagebuf_ioerror cd/* markfbufft
0dnnerror	(or not)e*/m-sspageobuf_t,*,cd/* bufft
0to(mark		*/m-s,unsigtod _ar);cd/* error0to(d,ore (0+(++_tne)	*/m-
-exSt
n il  pagebuf_iod, rt(		/* d, rt I/OfSF a bufft
	*/m-s,pageobuf_t,*,cd/* bufft
0to(d, rt		*/m-s,pageobuf_.c ls_t);c/* PBF_1+af, PBF_ASYNC,		*/m-s,,sd/* PBF_READ, PBF_WRITE,		*/m-s,,sd/* PBF_DELWRI			*/m-
-exSt
n il  pagebuf_iorequesS(		/* d, rt rea2-I/O		*/m-s,pageobuf_t,*);cd/* bufft
0to(convey OoSdevice	*/m-
-exSt
n il  pagebuf_iowait(sd/* wait,foribufft
0I/Ofstre	*/m-s,pageobuf_t,*);cd/* bufft
0to(wait,on		*/m-
-exSt
n ead( pagebuf_iomove(cd/* move2d]ea in/out Sf(pagebuf	*/m-s,pageobuf_t,*,cd/* bufft
0to(manipulaSe		*/m-s,dnit.t,			/* d, rtiigdbufft
0offs6e	*/m-s,dnit.t,			/* lengnv0in}bufft
		*/m-s,caddr_t,cd/* d]ea poinSt
			*/m-s,pageobuf_rw_t);cd/* direction			*/m-
-d,atic dnlome il  pagebuf_iod,*ategy(pageobuf_t,*pb/m-{I-Er6eirt pb->pb_d,*at ? pb->pb_d,*at(pb)d: pagebuf_iorequesS(pb);I-}
---d,atic dnlome il  pagebuf_geSt
ror(pageobuf_t,*pb/m-{I-Er6eirt pb ? pb->pb_error0: ENOMEM; -}--
-4- Bufft
0Utility Rputiies	*/m-
-exSt
n caddr_t pagebuf_offs6e(		/* poinSt
uayioPfs6e in,bufft
	*/m-s,pageobuf_t,*,cd/* bufft
0to(oPfs6e into	*/m-s,dnit.t);cd/* offs6e			-/--
-4- PinniigdBufft
 Storage dn Memory */m-
-exSt
n ead( pagebuf_pin(	s/* piu bufft
0dnnmemory		*/m-s,pageobuf_t,*);cd/* bufft
0to(piu		*/m-
-exSt
n ead( pagebuf_oupin(	s/* oupin bufft
od d]ea		*/m-s,pageobuf_t,*);cd/* bufft
0to(oupiu		*/m-
-exSt
n il  pagebuf_ispin(	s/* cheB,pi++bufft
0is(piuned	*/m-s,pageobuf_t,*);cd/* bufft
0to(cheB,		-/--
-4- Delay d W     Bufft
0Rputiies	*/m-
-# /home PBDF_WAIT    0x01
-exSt
n ead( pagebuf_delw  _.cush(m-sspb_t rget.t *,m-s,unsigtod 12ng,m-s,il  *m;p---exSt
n ead( pagebuf_delw  _dequeue(m-s,pageobuf_t,*);--
-4- Bufft
0D]emSFeS6eip Rputiies	*/m-
-exSt
n il  pagebuf_in04(ead();--exSt
n ead( pagebuf_St
minate(ead()LY-p-p-#if /h PsinBUF_TRACE -exSt
n k,*aceot,*pagebuf_,*aceobuf;--exSt
n ead( pagebuf_S*ace(m-s,pageobuf_t,*,cd/* bufft
0boiig0S*aced		*/m-s,char,*,cdc/* descripSISF of oper]eISF	*/m-s,ead( *,cdc/* arbitrary.diagnod,ic value	*/m-s,ead( *);cd/* r6eirt address		*/m-#Slsu
-#  /home pagebuf_S*ace(pb, id, pt
,+ra)sdoo{ } whilea(0)p-#Snd(+
- -# /home pagebuf_S rget.namg(t rget)	bdevnamg((t rget)->pbr_kdev)--
-4-
-68 Kt
nel+versISF comp]eIbility macros
- -/--
-# /home pageobufft
s(page)	S(page)->bufft
s/ -# /home pageohas_bufft
s(page)	S(page)->bufft
s/ -# /home PageUptou]eg(x)		Page_Uptou]eg(x)
-4-
-68 macro ,*icks0to(exp]n|ttH usek_bufft
lfoo() andAclear_bufft
lfoo()
- - muncSISFs.
-f*/m-# /home BUFFER_FNS(b04,(namg)s,,sd	\--d,atic dnlome ead( sek_bufft
l##namg(d,* Ok,bufft
loccH *bh)d	\--{									\m-sdek_bit(BH_##b04,(&(bhm->b_st]egm;				\m-}									\m-d,atic dnlome ead( clear_bufft
l##namg(d,* Ok,bufft
loccH *bh)d	\--{									\m-sclear_bit(BH_##b04,(&(bhm->b_st]egm;				\m-}									\m-
-4-
-68 EmitAOH ubufft
0b04ops muncSISFs.   Notn OHatAOH reraru a2so muncSISFsp-f* o++OHeAform "mark_bufft
lfoo()". ,Th seraru higH r-level+muncSISFs whichp-f* doosomethiigdin  ddieISF0to(dettiigdanb_st]eg0b04.
-f*/m-BUFFER_FNS(Uptou]eg, uptou]eg)m-BUFFER_FNS(Dirty,i irty)m-BUFFER_FNS(Lem ,nlem ed)t-BUFFER_FNS(Req,freq)t-BUFFER_FNS(Mappe , mappe )t-BUFFER_FNS(New, new)t-BUFFER_FNS(Async, async)t-BUFFER_FNS(Wait_IO, wait_io)m-BUFFER_FNS(LaundIS,nlaundIS)m-BUFFER_FNS(Sync, sync)t-BUFFER_FNS(Delay, delayo -p-# /home get.secon|s(VE CURRENT_TIMEp-# /home bhk_run_queues(m	run_task_queue(&tq_disk/ -# /home i_snitnrccH( nodh)	S( nodh)->i_snit/ -# /home i_snitnw    ( nodh, sz)	S( nodh)->i_snit =,(sz))--
-4-,Th seraru justidor0xfsosyncsub...Aittdets an,inSt
nal variable
-68 fhenipassesAittto(VOP_FLUSH_fsinS orr dds2OH S.c ls to(a newly go ten}buf_S
-f*/m-# /home XFS_B_ASYNC		PBF_ASYNCm-# /home XFS_B_DELWRI		PBF_DELWRIm-# /home XFS_B_READ	sPBF_READm-# /home XFS_B_WRITE	sPBF_WRITEm-# /home XFS_B_STALE	sPBF_STALE -p-# /home XFS_BUF_TRY1+af	sPBF_TRY1+afp-# /home XFS_INCORE_TRY1+af	PBF_TRY1+afp-# /home XFS_BUF_1+af	sPBF_1+afp-# /home XFS_BUF_MAPPED	sPBF_MAPPED -p-# /home BUF_BUSY	sPBF_DONT_B1+af -p-# /home XFS_BUF_BFLAGS(x)	((x)->pb_.c ls)p-# /home XFS_BUF_ZEROFLAGS(x)	\m-s((x)->pb_.c ls &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI)/ -p-# /home XFS_BUF_STALE(x)	((x)->pb_.c ls |= XFS_B_STALE)p-# /home XFS_BUF_UNSTALE(x)	((x)->pb_.c ls &= ~XFS_B_STALE)p-# /home XFS_BUF_ISSTALE(x)	((x)->pb_.c ls & XFS_B_STALE)p-# /home XFS_BUF_SUPER_STALE(x)	doo{				\m-sssssXFS_BUF_STALE(x);	\m-sssssxfsobuf_undIlay(x);	\m-sssssXFS_BUF_DONE(x);	\m-ssss} whilea(0)p-p-# /home XFS_BUF_MANsin	sPBF_FS_MANsinDp-# /home XFS_BUF_UNMANsin(x)	((x)->pb_.c ls &= ~PBF_FS_MANsinD)
---d,atic dnlome ead( xfsobuf_undIlay(pageobuf_t,*pb/m-{I-Eif (pb->pb_.c ls & PBF_DELWRI) {p-sdif (pb->pb_1ist.amxe0!=,&pb->pb_1istVA{p-sdcpagebuf_delw  _dequeue(pb);I-EEspagebuf_e le(pb);p-s	} S_HWo{p-sdepb->pb_.c ls &= ~PBF_DELWRI;m-ss} -6}b-}p-p-# /home XFS_BUF_DELAYWRITE(x)	 ((x)->pb_.c ls |= PBF_DELWRI)p-# /home XFS_BUF_UNDELAYWRITE(x)	 xfsobuf_undIlay(x)p-# /home XFS_BUF_ISDELAYWRITE(x)	 ((x)->pb_.c ls & PBF_DELWRI)p-p-# /home XFS_BUF_ERROR(x,no)	 pagebuf_ioerror x,no)p-# /home XFS_BUF_GETERROR(x)	 pagebuf_geSt
ror(x)p-# /home XFS_BUF_ISERROR(x)	 (pagebuf_geSt
ror(x)?1:0)p-p-# /home XFS_BUF_DONE(x)		 ((x)->pb_.c ls &= ~(PBF_fsRTIAL|PBF_NONE/)p-# /home XFS_BUF_UNDONE(x)	 ((x)->pb_.c ls |= PBF_fsRTIAL|PBF_NONE/p-# /home XFS_BUF_ISDONE(x)	 (!(fBF_NOT_DONE(x))/ -p-# /home XFS_BUF_BUSY(x)		 ((x)->pb_.c ls |= PBF_FORCEIO)p-# /home XFS_BUF_UNBUSY(x)	 ((x)->pb_.c ls &= ~PBF_FORCEIO)p-# /home XFS_BUF_ISBUSY(x)	 (1/ -p-# /home XFS_BUF_ASYNC(x)	 ((x)->pb_.c ls |= PBF_ASYNC)p-# /home XFS_BUF_UNASYNC(x)	 ((x)->pb_.c ls &= ~PBF_ASYNC)p-# /home XFS_BUF_ISASYNC(x)	 ((x)->pb_.c ls & PBF_ASYNC)p-p-# /home XFS_BUF_FLUSH(x)	 ((x)->pb_.c ls |= PBF_FLUSH)p-# /home XFS_BUF_UNFLUSH(x)	 ((x)->pb_.c ls &= ~PBF_FLUSH)p-# /home XFS_BUF_ISFLUSH(x)	 ((x)->pb_.c ls & PBF_FLUSH)p-p-# /home XFS_BUF_SHUT(x)		 priitk("XFS_BUF_SHUT+_ty  mplemSnted,y6e\n")p-# /home XFS_BUF_UNSHUT(x)	 priitk("XFS_BUF_UNSHUT+_ty  mplemSnted,y6e\n")p-# /home XFS_BUF_ISSHUT(x)	 (0)p-p-# /home XFS_BUF_HOLD(x)		pagebuf_hold(x)p-# /home XFS_BUF_READ(x)		((x)->pb_.c ls |= PBF_READ)p-# /home XFS_BUF_UNREAD(x)	((x)->pb_.c ls &= ~PBF_READ)p-# /home XFS_BUF_ISREAD(x)	((x)->pb_.c ls & PBF_READ)p-p-# /home XFS_BUF_WRITE(x)	((x)->pb_.c ls |= PBF_WRITE)p-# /home XFS_BUF_UNWRITE(x)	((x)->pb_.c ls &= ~PBF_WRITE)p-# /home XFS_BUF_ISWRITE(x)	((x)->pb_.c ls & PBF_WRITE)p-p-# /home XFS_BUF_ISUNINITIAL(x)	 (0)p-# /home XFS_BUF_UNUNINITIAL(x)	 (0)p-p-# /home XFS_BUF_BP_ISMAPPED(bp)	 1m-
-Oype /h d,* Ok,pageobuf_s xfsobuf_t;p-# /home xfsobuf,pageobuf_sm-
-Oype /h d,* Ok,pb_t rget,xfsobuft rg_t;p-# /home xfsobuft rg,pb_t rgetp-p-# /home XFS_BUF_DATAIO(x)	((x)->pb_.c ls |= PBF_FS_DATAIOD)p-# /home XFS_BUF_UNDATAIO(x)	((x)->pb_.c ls &= ~PBF_FS_DATAIOD)p-p-# /home XFS_BUF_IODONE_FUNC(buf)	(buf)->pb_iostrep-# /home XFS_BUF_SET_IODONE_FUNC(buf,+munc)	\m-sss(buf)->pb_iostre =,(munc)p-# /home XFS_BUF_CLR_IODONE_FUNC(buf)		\m-sss(buf)->pb_iostre =,ct ap-# /home XFS_BUF_SET_BDSTRAT_FUNC(buf,+munc)	\m-sss(buf)->pb_d,*at =,(munc)p-# /home XFS_BUF_CLR_BDSTRAT_FUNC(buf)		\m-sss(buf)->pb_d,*at =,ct ap-p-# /home XFS_BUF_FSfRIVATE(buf,+Oype)		\m-sss((Oype)(buf)->pb_fspriv)p-# /home XFS_BUF_SET_FSfRIVATE(buf,+value)	\m-sss(buf)->pb_fspriv =,(ead( *)(value)p-# /home XFS_BUF_FSfRIVATE2(buf,+Oype)		\m-sss((Oype)(buf)->pb_fspriv2)p-# /home XFS_BUF_SET_FSfRIVATE2(buf,+value)	\m-sss(buf)->pb_fspriv2 =,(ead( *)(value)p-# /home XFS_BUF_FSfRIVATE3(buf,+Oype)		\m-sss((Oype)(buf)->pb_fspriv3)p-# /home XFS_BUF_SET_FSfRIVATE3(buf,+value)	\m-sss(buf)->pb_fspriv3  =,(ead( *)(value)p-# /home XFS_BUF_SET_START(buf)p-p-# /home XFS_BUF_SET_BRELSE_FUNC(buf,+value) \m-sss(buf)->pb_rS_HW =,(ealue)p-p-# /home XFS_BUF_PTR(bp)		(xfs_caddr_t/((bp)->pb_addr)m-
-exSt
n illome xfsocaddr_t xfsobuf_offs6e(pageobuf_t,*bp, snit_yioPfs6e/m-{I-Eif (bp->pb_.c ls & PBF_MAPPED)
-s	r6dirt XFS_BUF_PTR(bp) + offs6e;p-s, dirty(xfs_caddr_t/ pagebuf_offs6e(bp, offs6e)LY-}p-p-# /home XFS_BUF_SET_PTR(bp,+val, c*/in)		\m-sss	pagebuf_associ]eg_memory(bp,+val, c*/in)p-# /home XFS_BUF_ADDR(bp)	((bp)->pb_bn)p-# /home XFS_BUF_SET_ADDR(bp, bhk)		\m-sss((bp)->pb_bn =,(pageobuf_daddr_t)(bhk))p-# /home XFS_BUF_OFFSET(bp)	((bp)->pb_.ile_offs6e)p-# /home XFS_BUF_SET_OFFSET(bp, off)		\m-sss((bp)->pb_.ile_offs6e =,(off))p-# /home XFS_BUF_COUNT(bp)	((bp)->pb_c*/in_desirA|)p-# /home XFS_BUF_SET_COUNT(bp, cin)		\m-sss((bp)->pb_c*/in_desirA| =,(cin))p-# /home XFS_BUF_SIZE(bp)	((bp)->pb_bufft
llengnv)p-# /home XFS_BUF_SET_SIZE(bp, cin)		\m-sss((bp)->pb_bufft
llengnv =,(cin))p-# /home XFS_BUF_SET_VTYPE_REF(bp, Oype,fref)p-# /home XFS_BUF_SET_VTYPE(bp, Oype)p-# /home XFS_BUF_SET_REF(bp, ref)p-p-# /home XFS_BUF_ISPINNED(bp)	pagebuf_ispin(bp)p-p-# /home XFS_BUF_VALUSEMA(bp)	pagebuf_12B,_value(bp)p-# /home XFS_BUF_CPSEMA(bp)	(pagebuf_cond_12B,(bp) ==,0)p-# /home XFS_BUF_VSEMA(bp)	pagebuf_ou12B,(bp)p-# /home XFS_BUF_PSEMA(bp,x)	pagebuf_12B,(bp)p-# /home XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iostresBma);--
-4- s6eip OH ubufft
0t rget,mverSa buft rg,s,* OkureS*/m-# /home XFS_BUF_SET_TARGET(bp, t rget)	\m-ss(bp)->pb_t rget,=,(t rget)p-# /home XFS_BUF_TARGET(bp)	((bp)->pb_t rget)p-# /home XFS_BUFTARG_NAME(t rget)	\m-sspagebuf_S rget.namg(t rget)p-p-# /home XFS_BUF_SET_VTYPE_REF(bp, Oype,fref)p-# /home XFS_BUF_SET_VTYPE(bp, Oype)p-# /home XFS_BUF_SET_REF(bp, ref)p-p-# /home xfsobuf_rccH(t rget, bhkno, len,S.c ls) \m-sspagebuf_get((t rget), (bhkno), (len), \m-sssPBF_1+af | PBF_READ | PBF_MAPPED)
-# /home xfsobuf_get(t rget, bhkno, len,S.c ls) \m-sspagebuf_get((t rget), (bhkno), (len), \m-sssPBF_1+af | PBF_MAPPED)
-p-# /home xfsobuf_rccH_.c ls(t rget, bhkno, len,S.c ls) \m-sspagebuf_get((t rget), (bhkno), (len), PBF_READ | (.c ls))
-# /home xfsobuf_get_.c ls(t rget, bhkno, len,S.c ls) \m-sspagebuf_get((t rget), (bhkno), (len), (.c ls))
---d,atic dnlome il sxfsobaw    (ead( *mp, pageobuf_t,*bp/m-{I-Ebp->pb_.spriv3 = mp2.-,bp->pb_d,*at =,xfsobdd,*at_cb;c-Exfsobuf_undIlay(bp);p-s, dirt pagebuf_iod, rt(bp, PBF_WRITE | PBF_ASYNC | PBF_RUN_QUEUES/;I-}
---d,atic dnlome tic 	xfsobuf_rc_HW(pageobuf_t,*bp/m-{I-Eif (!bp->pb_rS_HW/c-sdpagebuf_ou12B,(bp);p-spagebuf_e le(bp);p-}
-p-# /home xfsobpin(bp)sdpagebuf_pin(bp)p-# /home xfsobunpin(bp)sdpagebuf_unpin(bp)
-p-# /home xfsobufS*ace(id, bp)s\m-s    pagebuf_S*ace(bp, id, ct a, (ead( *)_obuiltin_, dirtoaddress(0))
-p-# /home xfsobiostre pb/ds    \m-s    pagebuf_iostre pb, (pb->pb_.c ls & PBF_FS_DATAIOD),,0o -p-# /home xfsoinc*re(buft rg,bhkno,len,12B,it) \m-s    pagebuf_find(buft rg, bhkno ,len, 12B,it)Y-p-p-# /home xfsobiomove(pb, off, len,Sd]ea, rw) \m-s    pagebuf_iomove( pb/,,(off), (len), (d]ea/, \m-ss((rw) == XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ)
-p-# /home xfsobiozero(pb, off, len) \m-s    pagebuf_iomove( pb/,,(off), (len), ct a, PBRW_ZERO)Y-p-p-d,atic dnlome il sXFS_bw    (pageobuf_t,*pb/m-{I-Eil siowait =,(pb->pb_.c ls & PBF_ASYNC) ==,0;I-Eil serror0= 0LY-m-sif (!iowait/c-sdpb->pb_.c ls |= PBF_RUN_QUEUES;p-c-Exfsobuf_undIlay(pb);p-spagebuf_iod,*ategy(pboLY-sif (iowait/o{p-sderror0= pagebuf_iowait(pb);p-s	xfsobuf_rc_HW(pb); -s}Y-s, dirt error;Y-}p-p-# /home XFS_bdw    (pb/ds     \m-s    pagebuf_iod, rt(pb, PBF_DELWRIf| PBF_ASYNC)p-p-d,atic dnlome il  xfsobdw    (ead( *mp, pageobuf_t,*bp/m-{I-Ebp->pb_d,*at =,xfsobdd,*at_cb;c-Ebp->pb_.spriv3 = mp2.-p-s, dirt pagebuf_iod, rt(bp, PBF_DELWRIf| PBF_ASYNC);Y-}p-p-# /home XFS_bdd,*at(bp) pagebuf_iorequesS(bp)
-p-# /home xfsoiowait(pb)Epagebuf_iowait(pb)Y-p-p-/*
-68 Go(OHrough a2_Ainc*repbufft
s, andAe leas ubufft
sp-f*pi++OH y be12ng to(OHe-giveindevice. T/dondsfuse }in
- - miledystem error0handliig0to(pres6rvB(OHe-consistencyp-f* o++its	meeaI]ea.
- -/--
-# /home xfsobinval(buft rg)	xfs_.cush_buft rg(buft rg)p-p-# /home XFS_b.cush(buft rg)	xfs_.cush_buft rg(buft rg)p-p-# /home xfsoinc*re_rc_HW(buft rg,delw  _only,wait/s\m-sxfsorS_HW_buft rg(buft rg)p-p-# /home xfsobarccH(t rget, rabhkno, ralen)  \m-spagebuf_e SIaoccH((t rget), (rabhkno), (ralen), PBF_DONT_B1+af)
-p-# /home xfsobuf_get_(mpty(len,St rget)	pagebuf_get_(mpty((len), (t rget))
-# /home xfsobuf_get_noaddr(len,St rget)	pagebuf_get_no_daddr((len), (t rget))
-# /home xfsobuf_d/ho(bp)sdpagebuf_d/ho(bp)
-p-#Snd(+d/* __XFS_BUF_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsocrA|.h linux-2.4.27-rc4/fs/xfs/linux/xfsocrA|.h
--- linux-2.4.26/fs/xfs/linux/xfsocrA|.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsocrA|.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,50 +0,0 @@
-4-
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifn /h __XFS_CRED_H__
-# /home __XFS_CRED_H__
-
-4-
-68 Credentials
- -/--Oype /h d,* Ok,crA|o{p-s/* EMPTY(-/--},crA|_tLY-p-exSt
n d,* Ok,crA|o*dysocrA|;--
-4- OHdondsfa igck..MSassums dysocrA|ndsfOH uonly crA|_t dn2OH udystem)e*/m-d,atic __inlome il  capableocrA|(crA|_t *c
,+(l  cd()m-{p-s, dirty(cr ==,dysocrA|) ? 1 : capable(cd()LY-}
-p-#Snd(+ee/* __XFS_CRED_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfso.ile.c linux-2.4.27-rc4/fs/xfs/linux/xfso.ile.c
--- linux-2.4.26/fs/xfs/linux/xfso.ile.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfso.ile.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,438 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_sb.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_,*ans.h"
-#include "xfs_dmapi.h"
-#include "xfs_m*/in.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_a2_HW_btree.h"
-#include "xfs_ia2_HW_btree.h"
-#include "xfs_a2_HW.h"
-#include "xfs_btree.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinodh.h"
-#include "xfs_inodh.h"
-#include "xfs_error.h"
-#include "xfs_rw.h"
-#include <linux/iobuf.h>
-
-#include <linux/dcOt_e.h>
-#include <linux/mmaF.h> /* .or0PROT_WRITE */m-
-d,atic d,* Ok,vm_oper]eISFs_d,* Ok,linvfso.ile_vm_ops;--
-STATIC illome ssnit_y
-__linvfsorccH(
-sd,* Ok,.ile	*.ile,m-scha
		*buf,I-Eil s	io.c ls,I-Ednit.t		dnit,I-Eloff_t		*oPfs6e/m-{I-Ed,* Ok, nodh	* nodh =,.ile->f_dentry->d_inodh;p-stnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Ednit.t		rvalLY-m-sif (unlokely(.ile->f_.c ls & O_DIRECTmm {p-sdio.c ls |= IO_ISDIRECT;p-s	downorccH(& nodh->i_a2_HW_sem);p-s	VOP_READ(vp,,.ile, buf, snit, offs6e,n(o.c ls, ct a, rval);p-s	uporccH(& nodh->i_a2_HW_sem);p-s} S_HWo{p-sdVOP_READ(vp,,.ile, buf, snit, offs6e,n(o.c ls, ct a, rval);p-s}.-p-s, dirt rvalLY-}b---STATIC ssnit_y
-linvfsorccH(
-sd,* Ok,.ile	*.ile,m-scha
		*buf,I-Ednit.t		dnit,I-Eloff_t		*oPfs6e/m-{I-E, dirt __linvfsorccH(.ile, buf, 0, snit, offs6e)LY-}b---STATIC ssnit_y
-linvfsorccH_invis(
-sd,* Ok,.ile	*.ile,m-scha
		*buf,I-Ednit.t		dnit,I-Eloff_t		*oPfs6e/m-{I-E, dirt __linvfsorccH(.ile, buf, IO_INVIS, snit, offs6e)LY-}b---
-STATIC illome ssnit_y
-__linvfsow    (
-sd,* Ok,.ile	*.ile,m-scSFst cha
	*buf,I-Eil s	io.c ls,I-Ednit.t		c*/in,I-Eloff_t		*ppos/m-{I-Ed,* Ok, nodh	* nodh =,.ile->f_dentry->d_inodh;p-stnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Eloff_t		posLY-Eddnit.t		rvalLs/* UHWonegative errors inrOHdsfd'n */m-m-sif ((ddnit.t) c*/in(<,0o -s	r6dirt -EINVALLY-m-sif (!access_ok(VERIFY_READ, buf, c*/in)o -s	r6dirt -EFAULT; - - pos =,*pposLY-sif (pos <,0o -s	r6dirt -EINVALLY-m-srval =,.ile->f_error;Y-sif (rval)o{p-sd.ile->f_error(= 0LY-E , dirt rvalLY-s}.-p-s/* Wu a2_Hw multiple direct w    rs in,AOH rerdon_t
-	f* potential call0to(vm,* nW]eg inrOHak,path.
-se*/m-sif (unlokely(.ile->f_.c ls & O_DIRECTmm {p-sdio.c ls |= IO_ISDIRECT;p-s	downorccH(& nodh->i_a2_HW_sem);p-s	VOP_WRITE(vp,,.ile, buf, c*/in, &pos,n(o.c ls, ct a, rval);p-s	*ppos0= posLY-s	uporccH(& nodh->i_a2_HW_sem);p-s} S_HWo{p-sddown(& nodh->i_sem);p-s	VOP_WRITE(vp,,.ile, buf, c*/in, &pos,n(o.c ls, ct a, rval);p-s	*ppos0= posLY-s	up(& nodh->i_sem);p-s}.-p-s, dirt rvalLY-}b---STATIC illome ssnit_y
-linvfsow    (
-sd,* Ok,.ile	*.ile,m-scSFst cha
	*buf,I-Ednit.t		c*/in,I-Eloff_t		*ppos/m-{I-E, dirt __linvfsow    (.ile, buf, 0, c*/in, ppos/LY-}b---STATIC illome ssnit_y
-linvfsow    _invis(
-sd,* Ok,.ile	*.ile,m-scSFst cha
	*buf,I-Ednit.t		c*/in,I-Eloff_t		*ppos/m-{I-E, dirt __linvfsow    (.ile, buf, IO_INVIS, c*/in, ppos/LY-}b---STATIC ily
-linvfsoopen(
-sd,* Ok, nodh	* nodh,
-sd,* Ok,.ile	*.ilp/m-{I-Etnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Eil s	error;Y-m-sif (!(.ilp->f_.c ls & O_LARGEFILE) && i_snitnrccH( nodh) > MAX_NON_LFSo -s	r6dirt -EFBIG;Y-m-sASSERT(vp)LY-EVOP_OPEN(vp,,ct a, error);p-s, dirt -error;Y-}p-p---STATIC ily
-linvfsoe leas (
-sd,* Ok, nodh	* nodh,
-sd,* Ok,.ile	*.ilp/m-{I-Etnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Eil s	error0= 0LY-m-sif (vp)p-sdVOP_RELEASE(vp,,error);p-s, dirt -error;Y-}p-p---STATIC ily
-linvfsofsync(
-sd,* Ok,.ile	*.ilp,
-sd,* Ok,dentry	*dentry,I-Eil s	I]easync)t-{I-Ed,* Ok, nodh	* nodh =,dentry->d_inodh;p-stnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Eil s	error;Y-Eil s	.c ls = FSYNC_WAITLY-m-sif (I]easync)t-s	.c ls |= FSYNC_DATA;Y-m-sASSERT(vp)LY-EVOP_FSYNC(vp,,.c ls, ct a, (xfs_off_t)0, (xfs_off_t)-1,,error);p-s, dirt -error;Y-}p-p-4-
-68 linvfsorccHdir mapstto(VOP_READDIR().
-68 WWoneed to(buildAa(uio, crA|, ...
- -/--
-# /home amxedp(dp)      ((d,* Ok,xfs_direl  *m((char,*)(dp) + (dp)->d_reclen))p---STATIC ily
-linvfsoe cHdir(
-sd,* Ok,.ile	*.ilp,
-stic 		*direl ,
-sfilldir_tsfilldir/m-{I-Eil s	error0= 0LY-stnodh_t		*vp;p-suio_t		uio;Y-Eiovecnr	,iovLY-Eil s	eof0= 0LY-scaddr_ts	r6cH_buf;--Eil s	namglen,Ssnit =,0LY-Ednit.t		rlen =,Psin_CACHE_SIZE;c-Exfsooff_t	d, rt_offs6e,ncurr_offs6e;p-sxfs_direl _t	*dbp =,ct a;Y-m-svp =,LINVFS_GET_VP(.ilp->f_dentry->d_inodh);p-sASSERT(vp)LY-p-s/* Try fairly hard to(get,memory */m-sdoo{
-sdif ((r6cH_buf =,(caddr_t)kma2_HW(rlen,SGFP_KERNEL))o -s		br6ckLY-E ,len >>= 1;p-s} whilea(,len >= 1024)LY-m-sif (r6cH_buf == ct a) -s	r6dirt -ENOMEM; -p-suio.uio_iov =,&iovLY-Euio.uio_segflg =,UIO_SYSSPACE;c-Ecurr_offs6e =,.ilp->f_posLY-sif (.ilp->f_pos0!=,0x7fffffff) -s	uio.uio_offs6e =,.ilp->f_posLY-sSlsu
-s	uio.uio_offs6e =,0xffffffff; -p-swhilea(!eofm {p-sduio.uio_resid =,iov.iov_len =,,len;p-sdiov.iov_bas  =,,6cH_buf;--Esuio.uio_iovcne =,1; -p-s	d, rt_offs6e =,uio.uio_offs6e; -p-s	VOP_READDIR(vp,,&uio, ct a, &eof,,error);p-sdif ((uio.uio_offs6e == d, rt_offs6e) ||,error)o{p-sdesnit =,0LY-E		br6ckLY-E } -p-s	dnit =,,len - uio.uio_resid;p-s	dbp =,(xfs_direl _t,*),6cH_buf;--Eswhilea(dnit >,0oo{p-sdenamglen = d,,len(dbp->d.namg)LY-m-s	sif (.illdir(direl , dbp->d.namg,(namglen,e-,,sss(loff_t)ncurr_offs6e & 0x7fffffff,e-,,sss(ino_t)ndbp->d.ino,e-,,sssDT_UNKNOWNmm {p-sd		goOoSdtreLp-sd	}p-sdesnit -=ndbp->d.reclenLp-sd	curr_offs6e =,(loff_t)dbp->d.off /* & 0x7fffffff */Lp-sd	dbp =,amxedp(dbp);p-ss} -6}b-dtre:m-sif (!error)o{p-sdif (dnit ==,0o -s		.ilp->f_pos0=,uio.uio_offs6e & 0x7fffffff;p-ssS_HWoif (Ibpo -s		.ilp->f_pos0=,curr_offs6e;p-s} -p-skd/ho(,6cH_buf);p-s, dirt -error;Y-}p-p-STATIC ily
-linvfsofile_mmap(
-sd,* Ok,.ile	*.ilp,
-sd,* Ok,vm_arcc_d,* Ok,*vma)t-{I-Ed,* Ok, nodh	* p =,.ilp->f_dentry->d_inodh;p-stnodh_t		*vp =,LINVFS_GET_VP( p);p-svattr_t		va =,{ .va_read = XFS_AT_UPDATIME }LY-Eil s	error;Y-m-sif ((vp->v_Oype ==,VREG) && (vp->v_vfsp->vfs_.cag & VFS_DMImm {p-sdxfs_m*/in_t	*mp = XFS_VFSTOM(vp->v_vfsp)LY-m-s	error0= -XFS_SEND_MMAP(mp, vma,,0o;p-sdif (error) -s		, dirt error;Y-s} -p-svma->vm_ops =,&linvfso.ile_vm_ops;--
-	VOP_SETATTR(vp,,&va,,XFS_AT_UPDATIME,,ct a, error);p-s, dirt 0;Y-}p-p---STATIC ily
-linvfsoioctl(
-sd,* Ok, nodh	* nodh,
-sd,* Ok,.ile	*.ilp,
-sunsigtod _ar	cmd,
-sunsigtod 12ng	 rg)p-{Y-Eil s	error;Y-stnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-m-sASSERT(vp)LY-EVOP_IOCTL(vp,, nodh, .ilp, 0, cmd,  rg, error);p-sVMODIFY(vp)LY-p-s/* NOTE: osome o++OHeAioctl's r6eirt positive #'s as0a
-se*	 }byte c*/in(indiW]eiigdsuccess,dsuchAas
-se*	 },6cHlink_by_handle.  So weSdtr't "sigt,.cip"
-se*	 }loke most oOH rneputiies. ,This	meansttrue
-se*	 }errors need to(be r6eirtedAas(a negative value.
-se*/m-s, dirt error;Y-}p-p-STATIC ily
-linvfsoioctl_invis(
-sd,* Ok, nodh	* nodh,
-sd,* Ok,.ile	*.ilp,
-sunsigtod _ar	cmd,
-sunsigtod 12ng	 rg)p-{Y-Eil s	error;Y-stnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-m-sASSERT(vp)LY-EVOP_IOCTL(vp,, nodh, .ilp, IO_INVIS, cmd,  rg, error);p-sVMODIFY(vp)LY-p-s/* NOTE: osome o++OHeAioctl's r6eirt positive #'s as0a
-se*	 }byte c*/in(indiW]eiigdsuccess,dsuchAas
-se*	 },6cHlink_by_handle.  So weSdtr't "sigt,.cip"
-se*	 }loke most oOH rneputiies. ,This	meansttrue
-se*	 }errors need to(be r6eirtedAas(a negative value.
-se*/m-s, dirt error;Y-}p-p-#if /h HAVE_VMOP_MPROTECTp-STATIC ily
-linvfsomprotect(
-sd,* Ok,vm_arcc_d,* Ok,*vma,
-sunsigtod _ar	new.c ls)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP(vma->vm_.ile->f_dentry->d_inodh)LY-Eil s	error0= 0LY-m-sif ((vp->v_Oype ==,VREG) && (vp->v_vfsp->vfs_.cag & VFS_DMImm {p-sdif ((vma->vm_.c ls & VM_MAYSHARE) &&p-sd    (new.c ls & PROT_WRITE) && !(vma->vm_.c ls & PROT_WRITE)m {p-sd	xfs_m*/in_t	*mp = XFS_VFSTOM(vp->v_vfsp)LY-m-s		error0= XFS_SEND_MMAP(mp, vma,,VM_WRITE);p-sd    } -6}b-s, dirt error;Y-}p-#Snd(+e/* HAVE_VMOP_MPROTECT -/--
-
-d,* Ok,.ile_oper]eISFs,linvfso.ile_oper]eISFs,= {p-s.l_HWek		=(generico.ile_l_HWek,
-s.e SIs	=(linvfsoe cH,
-s.w    s	=(linvfsow    ,
-s.ioctls	=(linvfsoioctl,
-s.mmaps	=(linvfsofile_mmap,
-s.opens	=(linvfsoopen,
-s.e leas 	=(linvfsoe leas ,
-s.fsyncs	=(linvfsofsync,Y-};
-
-d,* Ok,.ile_oper]eISFs,linvfsoinviso.ile_oper]eISFs,= {p-s.l_HWek		=(generico.ile_l_HWek,
-s.e SIs	=(linvfsoe cHoinvis,
-s.w    s	=(linvfsow    oinvis,
-s.ioctls	=(linvfsoioctloinvis,
-s.mmaps	=(linvfsofile_mmap,
-s.opens	=(linvfsoopen,
-s.e leas 	=(linvfsoe leas ,
-s.fsyncs	=(linvfsofsync,Y-};
-
-
-d,* Ok,.ile_oper]eISFs,linvfsodir_oper]eISFs,= {p-s.e SIs	=(genericoe cHodir,
-s.e SIdir	=(linvfsoe cHdir,
-s.ioctls	=(linvfsoioctl,
-s.fsyncs	=(linvfsofsync,Y-};
-
-d,atic d,* Ok,vm_oper]eISFs_d,* Ok,linvfso.ile_vm_ops,= {p-s.nopages	=(.ilemap_nopage,p-#if /h HAVE_VMOP_MPROTECTp-s.mprotect	=(linvfsomprotect,
-#Snd(+
-};-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfso.s_dubr.c linux-2.4.27-rc4/fs/xfs/linux/xfso.s_dubr.c
--- linux-2.4.26/fs/xfs/linux/xfso.s_dubr.c	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfso.s_dubr.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,126 +0,0 @@
-4-
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-
-4-
-68 Stub .or0no-op tnodh oper]eISFs,OHatA, dirt error d, rus.
- -/--ily
-.s_noerr(/m-{I-E, dirt 0;Y-}p-p-4-
-68 Oper]eISF unsupported undIS OHdsfdileadystem.
- -/--ily
-.s_nodys(/m-{I-E, dirt ENOSYS;Y-}p-p-4-
-68 Stub .or0inactive, d,*ategy, andAe ad/w     12B,/ou12B,.  Doeon_tyhiig.
- -/--/* ARGSUSED -/--tic 
-.s_noval(/m-{I-}p-p-4-
-68 tnodh pcOt_e lay 
}mp_ tnodh_tosspages.
-68 'last'0p rameSt
 unuse }but lefe in,for IRIX comp]eIbility
- -/--tic 
-.s_tosspages(
-sbhv_descnr	*bdp,
-sxfsooff_t	first,
-sxfsooff_t	last,I-Eil s	fiopt)p-{I-Etnodh_t		*vp =,BHV_TO_VNODE(bdp)LY-Ed,* Ok, nodh	* p =,LINVFS_GET_IP(vp)LY-p-sif (VN_CACHED(vp)o -s	,* nW]eg_inodh_pages(ip->i_mappiig,,first)LY-}b---
-4-
-68 tnodh pcOt_e lay 
}mp_ tnodh_.cushinval_pages.
-68 'last'0p rameSt
 unuse }but lefe in,for IRIX comp]eIbility
- -/--tic 
-.s_.cushinval_pages(
-sbhv_descnr	*bdp,
-sxfsooff_t	first,
-sxfsooff_t	last,I-Eil s	fiopt)p-{I-Etnodh_t		*vp =,BHV_TO_VNODE(bdp)LY-Ed,* Ok, nodh	* p =,LINVFS_GET_IP(vp)LY-p-sif (VN_CACHED(vp)oo{p-sd.ilemap_fI]easync(ip->i_mappiig);p-sdfsync_inodh_I]ea_bufft
s( p);p-sd.ilemap_fI]eawait(ip->i_mappiig);p- -s	,* nW]eg_inodh_pages(ip->i_mappiig,,first)LY-6}b-}p-p-4-
-68 tnodh pcOt_e lay 
}mp_ tnodh_.cush_pages.
-68 'last'0p rameSt
 unuse }but lefe in,for IRIX comp]eIbility
- -/--ily
-.s_.cush_pages(
-sbhv_descnr	*bdp,
-sxfsooff_t	first,
-sxfsooff_t	last,I-Euily64_t	fc ls,I-Eil s	fiopt)p-{I-Etnodh_t		*vp =,BHV_TO_VNODE(bdp)LY-Ed,* Ok, nodh	* p =,LINVFS_GET_IP(vp)LY-p-sif (VN_CACHED(vp)oo{p-sd.ilemap_fI]easync(ip->i_mappiig);p-sdfsync_inodh_I]ea_bufft
s( p);p-sd.ilemap_fI]eawait(ip->i_mappiig);p-s}.-p-s, dirt 0;Y-}pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfso.s_dubr.h linux-2.4.27-rc4/fs/xfs/linux/xfso.s_dubr.h
--- linux-2.4.26/fs/xfs/linux/xfso.s_dubr.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfso.s_dubr.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,49 +0,0 @@
-4-
-68 Copyright (c) 2000, 2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifn /h	__XFS_SUBR_H__
-# /home __XFS_SUBR_H__
-
-4-
-68 UtilitiBs sharA|nam2ng dileadystem  mplemSntaSISFs.
-f*/m-
-d,* Ok,crA|;--
-exSt
n il 	.s_noerr(ead();--exSt
n il 	.s_nodys(ead();--exSt
n il 	.s_nodev(ead();--exSt
n ead(	.s_noval(ead();--exSt
n ead(	.s_tosspages(bhv_descnr *, xfsooff_t, xfsooff_t, _ar);--exSt
n ead(	.s_.cushinval_pages(bhv_descnr *, xfsooff_t, xfsooff_t, _ar);--exSt
n il 	.s_.cush_pages(bhv_descnr *, xfsooff_t, xfsooff_t, uily64_t, _ar);--p-#Snd(+d/* __XFS_FS_SUBR_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsoglobals.c linux-2.4.27-rc4/fs/xfs/linux/xfsoglobals.c
--- linux-2.4.26/fs/xfs/linux/xfsoglobals.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsoglobals.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,75 +0,0 @@
-4-
-68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-/-
-68 T/dondileacoinains globals neede }byrXFS OHatAw rernormally0 /homed
-68 somewH rerS_HWoin IRIX.
- -/--
-#include "xfs.h"
-#include "xfs_crA|.h"
-#include "xfs_sysctl.h"
-#include "xfs_refcOt_e.h"
-
-4-
-68 System memory snit -fuse }to(dcaleacernain,d]ea s,* Okures inrXFS.
- -/--unsigtod 12ng xfsophysmem;--
-/-
-68 TunablerXFS p rameSt
s. ,xfsop ramondsfrequirA| eveinwheniCONFIG_SYSCTL=n,p-f* oOH rnXFS codh usesAth servalues.
-f*/m-
-xfsop ram_t xfsop ramon= {p-sd	ee/*	MIN	DFLT	MAX	*/m-s.refcOt_e_snit	= {	0,	128,sXFS_REFCACHE_SIZE_MAX },m-s.refcOt_e_purgt	= {	0,	32,sXFS_REFCACHE_SIZE_MAX },m-s.red,*ict_chown	= {	0,	1,	1	},m-s.sgiHoinH rit	= {	0,	0,	1	},m-s.symlink_modh	= {	0,	0,	1	},m-s.panic_read	= {	0,	0,	127	},m-s.error_level	= {	0,	3,	11	},m-s.sync_inSt
val	= {	HZ,	30*HZ,	60*HZ	},m-s.staSs_clear	= {	0,	0,	1	},m-s.inH ritosync	= {	0,	1,	1	},m-s.inH ritonodump	= {	0,	1,	1	},m-s.inH ritonoaSIm = {	0,	1,	1	},m-s..cush_inSt
val	= {	HZ/2,sHZ,	30*HZ	},m-s.ageobufft
	= {	1*HZ,	15*HZ,	300*HZ	},m-};--
-/-
-68 Globaladystem credential s,* Okure.
-f*/m-crA|_t dysocrA|_val, *dysocrA| =,&dysocrA|_val;--
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsoglobals.h linux-2.4.27-rc4/fs/xfs/linux/xfsoglobals.h
--- linux-2.4.26/fs/xfs/linux/xfsoglobals.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsoglobals.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,44 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifn /h __XFS_GLOBALS_H__
-# /home __XFS_GLOBALS_H__
-
-/-
-68 T/dondileadeclares globals neede }byrXFS OHatAw rernormally0 /homed
-68 somewH rerS_HWoin IRIX.
- -/--
-exSt
n uily64_t	xfsop nic_read;		4- s6e0to(cause more panics -/--exSt
n unsigtod 12ng xfsophysmem;--exSt
n d,* Ok,crA|o*dysocrA|;--
-#Snd(+d/* __XFS_GLOBALS_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsoioctl.c linux-2.4.27-rc4/fs/xfs/linux/xfsoioctl.c
--- linux-2.4.26/fs/xfs/linux/xfsoioctl.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsoioctl.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,1237 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-
-#include "xfs_fs.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_,*ans.h"
-#include "xfs_sb.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_a2_HW.h"
-#include "xfs_dmapi.h"
-#include "xfs_m*/in.h"
-#include "xfs_a2_HW_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ia2_HW_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ia2_HW.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinodh.h"
-#include "xfs_inodh.h"
-#include "xfs_bmap.h"
-#include "xfs_bin.h"
-#include "xfs_rta2_HW.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_maW.h"
-#include "xfs_attr.h"
-#include "xfs_buf_item.h"
-#include "xfs_utils.h"
-#include "xfs_dfrag.h"
-#include "xfs_fsops.h"
-
-#include <linux/dcOt_e.h>
-#include <linux/iobuf.h>
-
-4-
-68 ioctl(commands,OHatAare use }by Linux miledystems
- -/--# /home XFS_IOC_GETXFLAGS	_IOR('f', 1, 12ng)--# /home XFS_IOC_SETXFLAGS	_IOW('f', 2, 12ng)--# /home XFS_IOC_GETVERSION	_IOR('v', 1, 12ng)--
-
-4-
-68 xfso.ind_handle mapstmverSuserspace,xfs_fsop_handlereq,s,* OkureSto
-68( ndileaor0.s handle.
- -
-68 XFS_IOC_PATH_TO_FSHANDLE
-68   A, dirts0.s handle,for a m*/in po(l  or path winvinrOHak,m*/in po(l 
-68 XFS_IOC_FD_TO_HANDLE
-68   A, dirts0.u2_ihandle,for a FD opetod _aSuser space
-68 XFS_IOC_PATH_TO_HANDLE
-68   A, dirts0.u2_ihandle,for a path
- -/--STATIC ily
-xfso.ind_handle(
-sunsigtod _ar		cmd,
-sunsigtod 12ng		 rg)p-{Y-Eil s		hsnit;p-sxfs_handle_t		handle;p-sxfs_fsop_handlereq_t	hreqLY-Ed,* Ok, nodh		* nodhLY-Ed,* Ok,vnodh		*vpLY-p-sif (copy_mver_user(&hreq, (xfs_fsop_handlereq_t *) rg, snitof(hreq))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-smems6e((char,*)&handle, 0, snitof(handle))LY-p-sswinch (cmdoo{p-scas  XFS_IOC_PATH_TO_FSHANDLE:p-scas  XFS_IOC_PATH_TO_HANDLE: {p-sdd,* Ok,namgid]ea	nd;p-s	il s		error;Y-m-s	error0= user_path_walk_link(hreq.path, &ndo;p-sdif (error) -s		, dirt error;Y- -s	ASSERT(nd.dentryo;p-sdASSERT(nd.dentry->d_inodh)LY-E	 nodh =,igrab(nd.dentry->d_inodh)LY-E	path_e leas (&ndo;p-sdbr6ckLY-E}.-p-scas  XFS_IOC_FD_TO_HANDLE: {p-sdd,* Ok,.ile	*.ile;Y- -s	dilea= fget(hreq.fdo;p-sdif (!dile)p-sd    r6dirt -EBADF;Y- -s	ASSERT(.ile->f_dentryo;p-sdASSERT(.ile->f_dentry->d_inodh)LY-E	 nodh =,igrab(.ile->f_dentry->d_inodh)LY-E	fput(.ileo;p-sdbr6ckLY-E}.-p-s /hault:p-sdASSERT(0o;p-sdr6dirt -XFS_ERROR(EINVAL);p-s}.-p-sif (inodh->i_sb->s_magic != XFS_SB_MAGICoo{p-sd/8 we'rernot inrXFS0 nymore, ToOoS*/m-s	iput(inodh)LY-E	r6dirt -XFS_ERROR(EINVAL);p-s}.-p-s/8 we need tH utnodh */m-svp =,LINVFS_GET_VP( nodh)LY-Eif (vp->v_Oype !=,VREG && vp->v_Oype !=,VDIR && vp->v_Oype !=,VLNKm {p-sdiput(inodh)LY-E	r6dirt -XFS_ERROR(EBADF);p-s}.-p-s/8 now we can,grab tH ufsid */m-smemcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, snitof(xfs_fsid_t))LY-	hsnit = dnitof(xfs_fsid_t)LY-p-sif (cmd != XFS_IOC_PATH_TO_FSHANDLEm {p-sdxfs_inodh_t	*ip;p-sdbhv_descnr	*bhv;p-s	il s	12B,_modhLY-p-sd/8 need to(get,access to(OHe-xfs_inodh to(e ad(OHe-generaSISF */m-s	bhv = vn_bhv_lookup_ou12B,ed(VN_BHV_HEAD(vp), &xfs_tnodhopso;p-sdASSERT(bhv)LY-E	 p = XFS_BHVTOI(bhv)LY-E	ASSERT( p);p-sd12B,_modh =,xfsoi12B,_map_sharA|( p);p-p-sd/8 .ill in,fid seceISF o++handle,fverSinodh */m-s	handle.ha_fid.xfso.id_len =,dnitof(xfs_fid_t) -m-s		sd    snitof(handle.ha_fid.xfso.id_len);p-sdhandle.ha_fid.xfso.id_pad =,0LY-E	handle.ha_fid.xfso.id_gen =,ip->i_d.di_genLY-E	handle.ha_fid.xfso.id_ino =,ip->i_ino;p-p-sdxfsoiou12B,_map_sharA|( p, 12B,_modh);p-p-sdhsnit = XFS_HSIZE(handle);p-s}.-p-s/8 now copy our+handle,il o(OHe-user bufft
0& w     out OH udnit */m-sif (copy_to_user((xfs_handle_t,*)hreq.ohandle, &handle, hsnit) ||
-s    copy_to_user(hreq.ohandlen, &hsnit, snitof(__s32))m {p-sdiput(inodh)LY-E	r6dirt -XFS_ERROR(EFAULT)LY-s}.-p-siput(inodh)LY-E, dirt 0;Y-}p-p---4-
-68 ConvertSuserspace,handle,d]ea il o(tnodh (andAinodh).
-68 WWo[ab]use tH ufactdOHatAall0tH ufsop_handlereq,ioctl(calls
-68 igafRa,d]ea s,* Okure  rgumSnt whose,first componSnt dsfalways
-68( nxfs_fsop_handlereq_t, so we can,case0to(andAfverSOHdonOype.
-68 T/dona2_Hwsfus0to(optimisB(OHe-copy_mver_user(calls(andAgives
-68( nhandy, sharA|neputiie.
- -
-68 I++_t error,(caller(mustfalways VN_RELE+OHeAr6eirtedAvp.
- -/--STATIC ily
-xfsovget_.sop_handlereq(p-sxfs_m*/in_t		*mp,
-sd,* Ok, nodh		*par nodh,s/8 parSnt dnodh poinSt
    */m-sil s		cap,sd/8 capability level,for op */m-sunsigtod 12ng		 rg,sd/8 userspace,d]ea poinSt
  */m-sunsigtod 12ng		snit,		4- snit o++expeceod d,* Ok,*/p-s/8 putput argumSnts -/--sxfs_fsop_handlereq_t	*hreq,I-Etnodh_t			**vp,
-sd,* Ok, nodh		** nodh)p-{I-Etic 			*hanp;p-sdnit.t			hlenLp-sxfs_fid_t		*xfid;p-sxfs_handle_t		*handlep;p-sxfs_handle_t		handle;p-sxfs_inodh_t		*ip;p-sd,* Ok, nodh		* nodhp;I-Etnodh_t			*vpp;p-sxfs_inonr	,ino;p-	__u32s	sigenLY-Eil s		error;Y-m-sif (!capable(cap)o -s	r6dirt XFS_ERROR(EPERM)LY-p-s/*
-	f* Only a2_Hw handle,opets undIS a directory.
-se*/m-sif (!S_ISDIR(par nodh->i_modh)o -s	r6dirt XFS_ERROR(ENOTDIR)LY-p-s/*
-	f* Copy2OH uhandle,downAfverSOHe-user andAvalid]ee
-se* OHatAit,looks to(be dn2OH ucorrect formaS.
-se*/m-sif (copy_mver_user(hreq, (d,* Ok,xfs_fsop_handlereq,*) rg, snit)o -s	r6dirt XFS_ERROR(EFAULT)LY-p-shanp = hreq->ihandle;p-shlen =,hreq->ihandlenLY-Ehandlep =,&handle;p-m-sif (hlen < snitof(handlep->ha_fsid) ||,hlen > snitof(*handlep)o -s	r6dirt XFS_ERROR(EINVAL);p-sif (copy_mver_user(handlep,uhanp,uhlen))p-s	r6dirt XFS_ERROR(EFAULT)LY-sif (hlen < snitof(*handlep)o -s	mems6e(((char,*)handlep) +uhlen, 0, snitof(*handlep) -uhlen)LY-sif (hlen > snitof(handlep->ha_fsid)m {p-sdif (handlep->ha_fid.xfso.id_len !=m-s		s(hlen - snitof(handlep->ha_fsid)m-s		sd- snitof(handlep->ha_fid.xfso.id_len))p-sd    ||,handlep->ha_fid.xfso.id_pad) -s		, dirt XFS_ERROR(EINVAL);p-s}.-p-s/8
-	f* Crack2OH uhandle, obnain,OHe- nodh #0& generaSISF #
-se*/m-sxfid =,(d,* Ok,xfs_fd( *)&handlep->ha_fidLY-sif (xfid->xfso.id_len ==,dnitof(*xfid) - snitof(xfid->xfso.id_len)m {p-sdi_t  =,xfid->xfso.id_ino;p-	sigen =,xfid->xfso.id_genLY-E} S_HWo{p-sd, dirt XFS_ERROR(EINVAL);p-s}.-p-s/8
-	f* Get OH uXFS0 nodh, buildiigda(tnodh to(go winv2iS.
-se*/m-serror0= xfs_iget(mp,,ct a, ino, XFS_I1+af_SHARED, & p, 0)LY-sif (error) -s	, dirt error;Y-sif (ip == ct a) -s	r6dirt XFS_ERROR(EIOoLY-sif (ip->i_d.di_modh ==,0 ||,ip->i_d.di_gen != igenm {p-sdxfs_iput_new( p, XFS_I1+af_SHARED)LY-E	r6dirt XFS_ERROR(ENOENT)LY-s}.-p-svpp = XFS_ITOV( p);p-s nodhp =,LINVFS_GET_IP(vpp);p-sxfsoiou12B,( p, XFS_I1+af_SHARED)LY-p-s*vp =,vpp;p-s* nodh =, nodhp;I-E, dirt 0;Y-}p-p-STATIC ily
-xfsoopet_by_handle(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg,
-sd,* Ok,.ile		*par.ilp,
-sd,* Ok, nodh		*par nodh)p-{Y-Eil s		error;Y-Eil s		new_fd;Y-Eil s		permfc l;
-sd,* Ok,.ile		*.ilpLY-Ed,* Ok, nodh		* nodhLY-Ed,* Ok,dentry		*dentry;I-Etnodh_t			*vp;p-sxfs_fsop_handlereq_t	hreqLY-m-serror0= xfs_vget_.sop_handlereq(mp, par nodh, CAP_SYS_ADMIN,  rg,m-s		sddnitof(xfs_fsop_handlereq_t),m-s		sd&hreq, &vp,,& nodh)LY-Eif (error) -s	, dirt -error;Y-m-s/8 Red,*ict xfsoopet_by_handle to(directoriBs & regular,miled.e*/m-sif (!(S_ISREG( nodh->i_modh) ||,S_ISDIR( nodh->i_modh)om {p-sdiput(inodh)LY-E	r6dirt -XFS_ERROR(EINVAL);p-s}.-p-#if BITS_PER_LONG != 32Y-Ehreq.o.c ls |= O_LARGEFILE;
-#Snd(+
-s/8 Put opet permissISF in,namgi formaS.e*/m-spermfc l =,hreq.o.c lsLY-Eif ((permfc l+1) & O_ACCMODE) -s	permfc l++LY-Eif (permfc l & O_TRUNC) -s	permfc l |= 2;p-m-sif ((!(permfc l & O_APPEND) ||,(permfc l & O_TRUNC)) &&p-s    (permfc l & FMODE_WRITE) && IS_APPEND(inodh)m {p-sdiput(inodh)LY-E	r6dirt -XFS_ERROR(EPERM)LY-s}.-p-sif ((permfc l & FMODE_WRITE) && IS_IMMUTABLE(inodh)m {p-sdiput(inodh)LY-E	r6dirt -XFS_ERROR(EACCES);p-s}.-p-s/8 Car't w     directoriBs.e*/m-sif (,S_ISDIR( nodh->i_modh) && (permfc l & FMODE_WRITE)m {p-sdiput(inodh)LY-E	r6dirt -XFS_ERROR(EISDIR)LY-s}.-p-sif ((new_fd =(get_unuse _fd()m <,0oo{p-sdiput(inodh)LY-E	r6dirt new_fd;Y-E}.-p-s /ntry =,d_a2_HW_anon( nodh)LY-Eif ( /ntry == ct a)o{p-sdiput(inodh)LY-E	put_unuse _fd(new_fd)LY-E	r6dirt -XFS_ERROR(ENOMEM);p-s}.-p-s/8 Ensure um*/in , dirts0EBUSY SF um*/ins whileaOHdsfdileadsfopet.e*/m-smntget(par.ilp->f_vfsmar);--p-s/8 Cre]eg dileapoinSt
.e*/m-s.ilp =,dentryoopen(dentry, par.ilp->f_vfsmar,,hreq.o.c ls)LY-Eif (IS_ERR(.ilp)m {p-sdput_unuse _fd(new_fd)LY-E	r6dirt -XFS_ERROR(-PTR_ERR(.ilp)m;p-s}.-sif (inodh->i_modh &,S_IFREG)
-		.ilp->f_op =,&linvfsoinviso.ile_oper]eISFs;--p-sfd_insta2_(new_fd, .ilp)LY-E, dirt new_fd;Y-}p-p-STATIC ily
-xfso,6cHlink_by_handle(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg,
-sd,* Ok,.ile		*par.ilp,
-sd,* Ok, nodh		*par nodh)p-{Y-Eil s		error;Y-Ed,* Ok, ovec		 iovLY-Ed,* Ok,uio		 uio;Y-Ed,* Ok, nodh		* nodhLY-Exfs_fsop_handlereq_t	hreqLY-Etnodh_t			*vp;p-s__u32s	solenLY-m-serror0= xfs_vget_.sop_handlereq(mp, par nodh, CAP_SYS_ADMIN,  rg,m-s		sddnitof(xfs_fsop_handlereq_t),m-s		sd&hreq, &vp,,& nodh)LY-Eif (error) -s	, dirt -error;Y-m-s/8 Red,*ict OHdsfhandle,operaSISF to(dymlinks only.e*/m-sif (vp->v_Oype !=,VLNKm {p-sdVN_RELE(vp)LY-Edr6dirt -XFS_ERROR(EINVAL);p-s}.-p-sif (copy_mver_user(&olen, hreq.ohandlen, snitof(__u32))m {p-sdVN_RELE(vp)LY-Edr6dirt -XFS_ERROR(EFAULT)LY-s}.-	 iov.iov_len	= olenLY-	 iov.iov_bas 	=(hreq.ohandle;Y-m-sauio.uio_iov	=(& iovLY-Eauio.uio_iovcne	= 1;p-sauio.uio_offs6e	=,0LY-Eauio.uio_segflg	=,UIO_USERSPACE;c-Eauio.uio_resid	= olenLY-
-	VOP_READLINK(vp,,&auio, IO_INVIS, ct a, error);p-
-	VN_RELE(vp)LY-E, dirty(olen - auio.uio_resid/LY-}b---STATIC ily
-xfs_fss6edm_by_handle(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg,
-sd,* Ok,.ile		*par.ilp,
-sd,* Ok, nodh		*par nodh)p-{Y-Eil s		error;Y-Ed,* Ok,fsdmid]ea	fsdLY-Exfs_fsop_s6edm_handlereq_t dmhreqLY-Ed,* Ok, nodh		* nodhLY-Ebhv_descnr		*bdpLY-Etnodh_t			*vp;p-m-serror0= xfs_vget_.sop_handlereq(mp, par nodh, CAP_MKNOD,  rg,m-s		sddnitof(xfs_fsop_s6edm_handlereq_t),m-s		sd(xfs_fsop_handlereq_t *)&dmhreq,m-s		sd&vp,,& nodh)LY-Eif (error) -s	, dirt -error;Y-m-sif (IS_IMMUTABLE(inodh) ||,IS_APPEND(inodh)m {p-sdVN_RELE(vp)LY-Edr6dirt -XFS_ERROR(EPERM)LY-s}.-p-sif (copy_mver_user(&fsd, dmhreq.d]ea, snitof(fsd))m {p-sdVN_RELE(vp)LY-Edr6dirt -XFS_ERROR(EFAULT)LY-s}.-Y-Ebdp =,bhv_bas _ou12B,ed(VN_BHV_HEAD(vp))LY-serror0= xfs_s6e_dmattrs(bdp,,fsd.fsd_dmevread,,fsd.fsd_dmstaSe, ct a);p-
-	VN_RELE(vp)LY-Eif (error) -s	, dirt -error;Y-E, dirt 0;Y-}p-p-STATIC ily
-xfsoattrlist_by_handle(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg,
-sd,* Ok,.ile		*par.ilp,
-sd,* Ok, nodh		*par nodh)p-{Y-Eil s		error;Y-Eattrlist_cursor_kern_t	*cursorLY-Exfs_fsop_attrlist_handlereq_t al_hreqLY-Ed,* Ok, nodh		* nodhLY-Etnodh_t			*vp;p-m-serror0= xfs_vget_.sop_handlereq(mp, par nodh, CAP_SYS_ADMIN,  rg,m-s		sddnitof(xfs_fsop_attrlist_handlereq_t),m-s		sd(xfs_fsop_handlereq_t *)&al_hreq,m-s		sd&vp,,& nodh)LY-Eif (error) -s	, dirt -error;Y-m-scursor =,(attrlist_cursor_kern_t *)&al_hreq.posLY-sVOP_ATTR_LIST(vp,,al_hreq.bufft
,,al_hreq.buflen, al_hreq.fc ls,I-E	scursor,,ct a, error);p-sVN_RELE(vp)LY-Eif (error) -s	, dirt -error;Y-E, dirt 0;Y-}p-p-STATIC ily
-xfsoattrmulti_by_handle(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg,
-sd,* Ok,.ile		*par.ilp,
-sd,* Ok, nodh		*par nodh)p-{Y-Eil s		error;Y-Exfs_attr_multiop_t	*ops;--Exfs_fsop_attrmulti_handlereq_t am_hreqLY-Ed,* Ok, nodh		* nodhLY-Etnodh_t			*vp;p-Eil s		i, snit;p-m-serror0= xfs_vget_.sop_handlereq(mp, par nodh, CAP_SYS_ADMIN,  rg,m-s		sddnitof(xfs_fsop_attrmulti_handlereq_t),m-s		sd(xfs_fsop_handlereq_t *)&am_hreq,m-s		sd&vp,,& nodh)LY-Eif (error) -s	, dirt -error;Y-m-ssnit = am_hreq.opc*/in(* snitof(attr_multiop_t)LY-Eops,= (xfs_attr_multiop_t *)kma2_HW(snit, GFP_KERNEL)LY-Eif (!opso {p-sdVN_RELE(vp)LY-Edr6dirt -XFS_ERROR(ENOMEM);p-s}.-p-sif (copy_mver_user(ops, am_hreq.ops, snit)o {p-sdkd/ho(opso;p-sdVN_RELE(vp)LY-Edr6dirt -XFS_ERROR(EFAULT)LY-s}.-Y-Efor (i =,0L i <,am_hreq.opc*/inL i++o {p-sdswinch(ops[i].am_opcodh) {p-sdcas  ATTR_OP_GET:p-sdsVOP_ATTR_GET(vp,ops[i].am_attrnamg,(ops[i].am_attrvalue,m-s		sd&ops[i].am_length, ops[i].am_fc ls,I-E	s		ct a, ops[i].am_error);p-sd	br6ckLY-E cas  ATTR_OP_SET:p-sdsif (IS_IMMUTABLE(inodh) ||,IS_APPEND(inodh)m {p-sd		ops[i].am_error =,EPERM;p-sd		br6ckLY-E 	}p-sdeVOP_ATTR_SET(vp,ops[i].am_attrnamg,(ops[i].am_attrvalue,m-s		sdops[i].am_length, ops[i].am_fc ls,I-E	s		ct a, ops[i].am_error);p-sd	br6ckLY-E cas  ATTR_OP_REMOVE:p-sdsif (IS_IMMUTABLE(inodh) ||,IS_APPEND(inodh)m {p-sd		ops[i].am_error =,EPERM;p-sd		br6ckLY-E 	}p-sdeVOP_ATTR_REMOVE(vp,,ops[i].am_attrnamg,(ops[i].am_fc ls,I-E	s		ct a, ops[i].am_error);p-sd	br6ckLY-E  /hault:p-sd	ops[i].am_error =,EINVALLY-ss} -6}b-p-sif (copy_to_user(am_hreq.ops, ops, snit)oY-sserror0= -XFS_ERROR(EFAULT)LY-p-skd/ho(opso;p-sVN_RELE(vp)LY-E, dirtyerror;Y-}p-p-4-nprotoOypes,for a few o++OHeAstack-hungry,cases,OHatAigaf
-68 OHeir ownAfuncSISFs.  FuncSISFsAare  /homed aftIS OH ir use
-68 so gcc doesr't get,fancy andAinlome OH mnwinv -03 -/--
-STATIC ily
-xfsoiHW_space(
-sbhv_descnr		*bdp,
-stnodh_t			*vp,
-sd,* Ok,.ile		*.ilp,
-sil s		fc ls,I-Eunsigtod _ar		cmd,
-sunsigtod 12ng		 rg);--
-STATIC ily
-xfsoiHW_bulkstaS(p-sxfs_m*/in_t		*mp,
-sunsigtod _ar		cmd,
-sunsigtod 12ng		 rg);--
-STATIC ily
-xfsoiHW_fsgeometryov1(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg);--
-STATIC ily
-xfsoiHW_fsgeometry(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg);--
-STATIC ily
-xfsoiHW_xattr(
-stnodh_t			*vp,
-sxfs_inodh_t		*ip,
-sd,* Ok,.ile		*.ilp,
-sunsigtod _ar		cmd,
-sunsigtod 12ng		 rg);--
-STATIC ily
-xfsoiHW_getbmap(
-sbhv_descnr		*bdp,
-sd,* Ok,.ile		*.ilp,
-sil s		fc ls,I-Eunsigtod _ar		cmd,
-sunsigtod 12ng		 rg);--
-STATIC ily
-xfsoiHW_getbmapx(
-sbhv_descnr		*bdp,
-sunsigtod 12ng		 rg);--
-ily
-xfsoiHWtl(
-sbhv_descnr		*bdp,
-sd,* Ok, nodh		* nodh,
-sd,* Ok,.ile		*.ilp,
-sil s		(o.c ls,I-Eunsigtod _ar		cmd,
-sunsigtod 12ng		 rg)p-{Y-Eil s		error;Y-Etnodh_t			*vp;p-sxfs_inodh_t		*ip;p-sxfs_m*/in_t		*mp;.-p-svp =,LINVFS_GET_VP( nodh)LY-m-svn_,*ace_entry(vp,,"xfsoiHWtl", (ins _t,*)__, dirt_address)LY-p-sip = XFS_BHVTOI(bdp)LY-Emp = ip->i_m*/inLY-p-sswinch (cmdoo{p-
-scas  XFS_IOC_ALLOCSP:p-scas  XFS_IOC_FREESP:p-scas  XFS_IOC_RESVSP:p-scas  XFS_IOC_UNRESVSP:p-scas  XFS_IOC_ALLOCSP64:p-scas  XFS_IOC_FREESP64:p-scas  XFS_IOC_RESVSP64:p-scas  XFS_IOC_UNRESVSP64:p-ss/8
-		f* Only a2_Hw OHeAsysAadmin to(e s6rvB space ou1ess
-		f* unw   tetyextSnts are enabled.d-		S*/m-s	if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&p-sd    !capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Edr6dirt xfsoiHW_space(bdp,,vp,,.ilp, (o.c ls, cmd,  rg)LY-p-scas  XFS_IOC_DIOINFO: {p-sdd,* Ok,dioattr	da;p-Y-Edda.d_miniosz = mp->m_sb.sb_b12B,snit;p-sdda.d_mem = mp->m_sb.sb_b12B,snit;p-p-ss/8
-		f* OHdsfonly r6clly0needs to(be BBSIZE.d-		S*Ait,is s6e0to(tH ufileadystem b12B, snit to
-		S*Aatic AigaiigdOoSdt b12B, zeroiigdonAdeGrt w    s.d-		S*/m-s	da.d_maxiosz = XFS_FSB_TO_B(mp,
-ssssXFS_B_TO_FSBT(mp, KIO_MAX_ATOMIC_IO << 10))LY-p-ssif (copy_to_user((d,* Ok,dioattr,*) rg, &da, snitof(da))) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_FSBULKSTAT_SINGLE:p-scas  XFS_IOC_FSBULKSTAT:p-scas  XFS_IOC_FSINUMBERS:Y-Edr6dirt xfsoiHW_bulkstaS(mp, cmd,  rg)LY-p-scas  XFS_IOC_FSGEOMETRY_V1:Y-Edr6dirt xfsoiHW_fsgeometryov1(mp,  rg)LY-p-scas  XFS_IOC_FSGEOMETRY:Y-Edr6dirt xfsoiHW_fsgeometry(mp,  rg)LY-p-scas  XFS_IOC_GETVERSION:p-scas  XFS_IOC_GETXFLAGS:p-scas  XFS_IOC_SETXFLAGS:p-scas  XFS_IOC_FSGETXATTR:p-scas  XFS_IOC_FSSETXATTR:p-scas  XFS_IOC_FSGETXATTRA:Y-Edr6dirt xfsoiHW_xattr(vp,, p,,.ilp, cmd,  rg)LY-p-scas  XFS_IOC_FSSETDM: {p-sdd,* Ok,.sdmid]ea	dmiLY-p-ssif (copy_mver_user(&dmi, (d,* Ok,.sdmid]ea *) rg, snitof(dmi))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sserror0= xfs_s6e_dmattrs(bdp,,dmi.fsd_dmevread,,dmi.fsd_dmstaSe,I-E	s				ct a)LY-Edr6dirt -error;Y-s} -p-scas  XFS_IOC_GETBMAP:p-scas  XFS_IOC_GETBMAPA:Y-Edr6dirt xfsoiHW_getbmap(bdp,,filp, (o.c ls, cmd,  rg)LY-p-scas  XFS_IOC_GETBMAPX:Y-Edr6dirt xfsoiHW_getbmapx(bdp,, rg)LY-p-scas  XFS_IOC_FD_TO_HANDLE:p-scas  XFS_IOC_PATH_TO_HANDLE:p-scas  XFS_IOC_PATH_TO_FSHANDLE:p-sdr6dirt xfso.ind_handle(cmd,  rg)LY-p-scas  XFS_IOC_OPEN_BY_HANDLE:p-sdr6dirt xfsoopet_by_handle(mp,  rg,,filp, (nodh)LY-m-scas  XFS_IOC_FSSETDM_BY_HANDLE:p-sdr6dirt xfsofss6edm_by_handle(mp,  rg,,filp, (nodh)LY-m-scas  XFS_IOC_READLINK_BY_HANDLE:p-sdr6dirt xfso,6cHlink_by_handle(mp,  rg,,filp, (nodh)LY-m-scas  XFS_IOC_ATTRLIST_BY_HANDLE:p-sdr6dirt xfsoattrlist_by_handle(mp,  rg,,filp, (nodh)LY-m-scas  XFS_IOC_ATTRMULTI_BY_HANDLE:p-sdr6dirt xfsoattrmulti_by_handle(mp,  rg,,filp, (nodh)LY-m-scas  XFS_IOC_SWAPEXT: {p-sderror0= xfs_swapext((d,* Ok,xfs_swapext *) rg)LY-Edr6dirt -error;Y-s} -p-scas  XFS_IOC_FSCOUNTS: {p-sdxfs_fsop_c*/ins_t,outLY-Y-sserror0= xfs_fs_c*/ins(mp, &outo;p-sdif (error) -s		, dirt -error;Y-m-ssif (copy_to_user((char,*) rg, &out, snitof(outo)) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_SET_RESBLKS: {p-sdxfs_fsop_e sblks_k, noutLY-	s__uily64_t	   in;Y-m-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Edif (copy_mver_user(& nout, (char,*) rg, snitof( nout))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-ss/*Ainput p rameSt
 donpassod _aSe sblks,field o++s,* Okure */m-s	in =, nout.e sblks;Y-sserror0= xfs_e s6rvB_b12B,s(mp, &in, & nouto;p-sdif (error) -s		, dirt -error;Y-m-ssif (copy_to_user((char,*) rg, & nout, snitof( nout))) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_GET_RESBLKS: {p-sdxfs_fsop_e sblks_k,outLY-Y-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Ederror0= xfs_e s6rvB_b12B,s(mp, ct a, &outo;p-sdif (error) -s		, dirt -error;Y-m-ssif (copy_to_user((char,*) rg, &out, snitof(outo)) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_FSGROWFSDATA: {p-sdxfs_growfs_d]ea_t in;Y-m-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Edif (copy_mver_user(& n, (char,*) rg, snitof( n))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sserror0= xfs_growfs_d]ea(mp, &in)LY-Edr6dirt -error;Y-s} -p-scas  XFS_IOC_FSGROWFSLOG: {p-sdxfs_growfs_log_t in;Y-m-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Edif (copy_mver_user(& n, (char,*) rg, snitof( n))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sserror0= xfs_growfs_log(mp, &in)LY-Edr6dirt -error;Y-s} -p-scas  XFS_IOC_FSGROWFSRT: {p-sdxfs_growfs_rt_t in;Y-m-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Edif (copy_mver_user(& n, (char,*) rg, snitof( n))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sserror0= xfs_growfs_rt(mp, &in)LY-Edr6dirt -error;Y-s} -p-scas  XFS_IOC_FREEZE:p-sdif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-sdxfs_fs_d/hoze(mp)LY-sE, dirt 0;Y-p-scas  XFS_IOC_THAW:p-sdif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-sdxfs_fs_thaw(mp)LY-sE, dirt 0;Y-p-scas  XFS_IOC_GOINGDOWN: {p-sd__uily32_t in;Y-m-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-Edif (get_user( n, (__uily32_t *) rg)) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sserror0= xfs_fs_goiigdown(mp, in)LY-Edr6dirt -error;Y-s} -p-scas  XFS_IOC_ERROR_INJECTION: {p-sdxfs_error_injeceISF_t in;Y-m-ssif (!capable(CAP_SYS_ADMIN)) -s		, dirt EPERM;p-Y-Edif (copy_mver_user(& n, (char,*) rg, snitof( n))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-sserror0= xfs_errortag_add( n.errtag, mp)LY-sE, dirt -error;Y-s} -p-scas  XFS_IOC_ERROR_CLEARALL:p-sdif (!capable(CAP_SYS_ADMIN)) -s		, dirt -EPERM;p-Y-sserror0= xfs_errortag_cleara2_(mp)LY-sE, dirt -error;Y-
-s /hault:p-sd, dirt -ENOTTY;Y-s} -}p-p-STATIC ily
-xfsoiHW_space(
-sbhv_descnr		*bdp,
-stnodh_t			*vp,
-sd,* Ok,.ile		*.ilp,
-sil s		(o.c ls,I-Eunsigtod _ar		cmd,
-sunsigtod 12ng		 rg)p-{Y-Exfs_f12B,64_t		bf;
-sil s		attr_.c ls =,0LY-Eil s		error;Y-m-sif (vp->v_inodh.i_.c ls & (S_IMMUTABLE|S_APPEND)o -s	r6dirt -XFS_ERROR(EPERM)LY-p-sif (!(.ilp->f_.c ls & FMODE_WRITE)m -s	r6dirt -XFS_ERROR(EBADF);p-
-sif (vp->v_Oype !=,VREG)
-		r6dirt -XFS_ERROR(EINVAL);p-
-sif (copy_mver_user(&bf, (xfs_f12B,64_t,*) rg, snitof(bf))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-sif (.ilp->f_.c ls & (O_NDELAY|O_NONB1+af)o -s	attr_.c ls |= ATTR_NONB1+af;p-sif ((o.c ls & IO_INVISo -s	attr_.c ls |= ATTR_DMI;p-m-serror0= xfs_changeo.ile_space(bdp,,cmd, &bf, .ilp->f_pos,I-E	s		      ct a, attr_.c ls)LY-E, dirty-error;Y-}p-p-STATIC ily
-xfsoiHW_bulkstaS(p-sxfs_m*/in_t		*mp,
-sunsigtod _ar		cmd,
-sunsigtod 12ng		 rg)p-{Y-Exfs_fsop_bulkreq_t	bulkreqLY-Eil s		c*/inLs/*A# o++recordsAr6eirtedA-/--sxfs_inonr	,inlastLs/*Alast- nodh numbt
 */m-sil s		doneLY-Eil s		error;Y-m-s/*Adone0= 1+(++tH rerare more staSs to(get,andAif bulkstaS,*/p-s/8 deGuld be(called again,(unuse }H re, but use }in,dmapi) -/--
-dif (!capable(CAP_SYS_ADMIN)) -s	, dirt -EPERM;p-Y-sif (XFS_FORCED_SHUTDOWN(mp))
-		r6dirt -XFS_ERROR(EIO);p-
-sif (copy_mver_user(&bulkreq, (xfs_fsop_bulkreq_t,*) rg,I-E	s		dnitof(xfs_fsop_bulkreq_t))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-sif (copy_mver_user(& nlast, (__s64,*)bulkreq.lastip,I-E	s			snitof(__s64))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-sif ((c*/in(= bulkreq.ic*/in) <=,0)
-		r6dirt -XFS_ERROR(EINVAL);p-
-sif (cmd == XFS_IOC_FSINUMBERSoY-sserror0= xfs_inumbt
s(mp, ct a, & nlast, &c*/in,I-E	s			bulkreq.ubufft
)LY-se_HWoif (cmd == XFS_IOC_FSBULKSTAT_SINGLEoY-sserror0= xfs_bulkstaS_siigle(mp, & nlast,I-E	s			bulkreq.ubufft
, &done)LY-se_HWo{s/8 XFS_IOC_FSBULKSTATS*/m-s	if (c*/in(== 1+&&  nlast !=,0oo{p-sd,inlast++LY-Esserror0= xfs_bulkstaS_siigle(mp, & nlast,I-E	s		bulkreq.ubufft
, &done)LY-sE} S_HWo{p-sdserror0= xfs_bulkstaS(mp, ct a, & nlast, &c*/in,I-E	s	(bulkstaS_one_pf)xfs_bulkstaS_one, ct a,I-E	s	dnitof(xfs_bstaS_t), bulkreq.ubufft
,I-E	s	BULKSTAT_FG_QUICK, &done)LY-sE}
-6}b-p-sif (error) -s	, dirt -error;Y-m-sif (bulkreq.oc*/in(!= ct a)o{p-sdif (copy_to_user((xfs_inonr,*)bulkreq.lastip, & nlast,I-E	s			dnitof(xfs_inonr))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-ssif (copy_to_user((__s32,*)bulkreq.oc*/in, &c*/in,I-E	s			dnitof(c*/in))) -s		, dirt -XFS_ERROR(EFAULT)LY-s}.-p-s, dirt 0;Y-}p-
-STATIC ily
-xfsoiHW_fsgeometryov1(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg)p-{Y-Exfs_fsop_geomov1_t	fsgeoLY-Eil s		error;Y-m-serror0= xfs_fs_geometry(mp, (xfs_fsop_geomot *)&fsgeo, 3)LY-Eif (error) -s	, dirt -error;Y-m-sif (copy_to_user((xfs_fsop_geomot *) rg, &fsgeo, snitof(fsgeo))o -s	r6dirt -XFS_ERROR(EFAULT)LY-s, dirt 0;Y-}p-
-STATIC ily
-xfsoiHW_fsgeometry(p-sxfs_m*/in_t		*mp,
-sunsigtod 12ng		 rg)p-{Y-Exfs_fsop_geomo s	fsgeoLY-Eil s		error;Y-m-serror0= xfs_fs_geometry(mp, &fsgeo, 4)LY-Eif (error) -s	, dirt -error;Y-m-sif (copy_to_user((xfs_fsop_geomot *) rg, &fsgeo, snitof(fsgeo))o -s	r6dirt -XFS_ERROR(EFAULT)LY-s, dirt 0;Y-}p-
-4-
-68 Linux extSndedAinodh .c ls inSt
face.
- -/--# /home LINUX_XFLAG_SYNC	0x00000008 /8 Synchronous upd]ees -/--# /home LINUX_XFLAG_IMMUTABLE	0x00000010 /8 Immutableufilea-/--# /home LINUX_XFLAG_APPEND	0x00000020 /8 w    s to(fileamayfonly appSnda-/--# /home LINUX_XFLAG_NODUMP	0x00000040 /8 do+_tyidumpufilea-/--# /home LINUX_XFLAG_NOATIME	0x00000080 /8 do+_tyiupd]ee aSIme -/--
-STATIC unsigtod _ar
-xfsomergeoiHW_x.c ls(
-sunsigtod _ar	.c ls,I-Eunsigtod _ar	start)p-{I-Eunsigtod _ar	x.c ls =,startLY-p-sif (.c ls & LINUX_XFLAG_IMMUTABLE)p-sdxfc ls |= XFS_XFLAG_IMMUTABLELY-se_HWp-sdxfc ls &= ~XFS_XFLAG_IMMUTABLELY-sif (.c ls & LINUX_XFLAG_APPEND)p-sdxfc ls |= XFS_XFLAG_APPENDLY-se_HWp-sdxfc ls &= ~XFS_XFLAG_APPENDLY-sif (.c ls & LINUX_XFLAG_SYNC)p-sdxfc ls |= XFS_XFLAG_SYNCLY-se_HWp-sdxfc ls &= ~XFS_XFLAG_SYNCLY-sif (.c ls & LINUX_XFLAG_NOATIME)p-sdxfc ls |= XFS_XFLAG_NOATIMELY-se_HWp-sdxfc ls &= ~XFS_XFLAG_NOATIMELY-sif (.c ls & LINUX_XFLAG_NODUMP)p-sdxfc ls |= XFS_XFLAG_NODUMPLY-se_HWp-sdxfc ls &= ~XFS_XFLAG_NODUMPLY-Y-s, dirt x.c lsLY-}p-
-STATIC ily
-xfsoiHW_xattr(
-stnodh_t			*vp,
-sxfs_inodh_t		*ip,
-sd,* Ok,.ile		*.ilp,
-sunsigtod _ar		cmd,
-sunsigtod 12ng		 rg)p-{I-Ed,* Ok,.sxattrs	fa;p-	vattr_t			vaLY-Eil s		error;Y-sil s		attr_.c ls;
-sunsigtod _ar		.c ls;
-
-sswinch (cmdoo{p-scas  XFS_IOC_FSGETXATTR:o{p-sdva.va_read = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTSLY-sEVOP_GETATTR(vp,,&va, 0, ct a, error);p-sdif (error) -s		, dirt -error;Y-m-ssfa..sx_x.c ls	= va.va_x.c lsLY-ssfa..sx_extsnit	= va.va_extsnitLY-ssfa..sx_nextSnts = va.va_nextSntsLY-Y-ssif (copy_to_user((d,* Ok,.sxattr *) rg, &fa, snitof(fa))) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_FSSETXATTR:o{p-sdif (copy_mver_user(&fa, (d,* Ok,.sxattr *) rg, snitof(fa))) -s		, dirt -XFS_ERROR(EFAULT)LY- -s	attr_.c ls =,0LY-E	if (.ilp->f_.c ls & (O_NDELAY|O_NONB1+af)o -s		attr_.c ls |= ATTR_NONB1+af;p-p-sdva.va_read = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;p-sdva.va_xfc ls a= fa..sx_x.c ls;p-sdva.va_extsnita= fa..sx_extsnitLY-Y-sEVOP_SETATTR(vp,,&va, attr_.c ls, ct a, error);p-sdif (!error) -s		vn_revalid]ee(vp)Ld/8 upd]ee Linux inodh .c ls */m-s	r6dirt -error;Y-s} -p-scas  XFS_IOC_FSGETXATTRA:o{p-sdva.va_read = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTSLY-sEVOP_GETATTR(vp,,&va, 0, ct a, error);p-sdif (error) -s		, dirt -error;Y-m-ssfa..sx_x.c ls	= va.va_x.c lsLY-ssfa..sx_extsnit	= va.va_extsnitLY-ssfa..sx_nextSnts = va.va_anextSntsLY-Y-ssif (copy_to_user((d,* Ok,.sxattr *) rg, &fa, snitof(fa))) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_GETXFLAGS:o{p-sd.c ls =,0LY-E	if (ip->i_d.di_.c ls & XFS_XFLAG_IMMUTABLE) -s		.c ls |= LINUX_XFLAG_IMMUTABLELY-E	if (ip->i_d.di_.c ls & XFS_XFLAG_APPEND)p-sd	.c ls |= LINUX_XFLAG_APPENDLY-s	if (ip->i_d.di_.c ls & XFS_XFLAG_SYNC)p-sd	.c ls |= LINUX_XFLAG_SYNCLY-s	if (ip->i_d.di_.c ls & XFS_XFLAG_NOATIME)p-sd	.c ls |= LINUX_XFLAG_NOATIMELY-s	if (ip->i_d.di_.c ls & XFS_XFLAG_NODUMP)p-sd	.c ls |= LINUX_XFLAG_NODUMPLY-ssif (copy_to_user((unsigtod _ar *) rg, &fc ls, snitof(fc ls))) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-scas  XFS_IOC_SETXFLAGS:o{p-sdif (copy_mver_user(&fc ls, (unsigtod _ar *) rg, snitof(fc ls))) -s		, dirt -XFS_ERROR(EFAULT)LY-Y-E	if (.c ls & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ -s		      LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ -s		      LINUX_XFLAG_SYNC)) -s		, dirt -XFS_ERROR(EOPNOTSUPP)LY- -s	attr_.c ls =,0LY-E	if (.ilp->f_.c ls & (O_NDELAY|O_NONB1+af)o -s		attr_.c ls |= ATTR_NONB1+af;p-p-sdva.va_read = XFS_AT_XFLAGS;p-sdva.va_xfc ls = xfs_mergeoiHW_x.c ls(fc ls, ip->i_d.di_.c ls)LY-Y-sEVOP_SETATTR(vp,,&va, attr_.c ls, ct a, error);p-sdif (!error) -s		vn_revalid]ee(vp)Ld/8 upd]ee Linux inodh .c ls */m-s	r6dirt -error;Y-s} -p-scas  XFS_IOC_GETVERSION:o{p-sd.c ls =,LINVFS_GET_IP(vp)->i_generaSISFLY-ssif (copy_to_user((unsigtod _ar *) rg, &fc ls, snitof(fc ls))) -s		, dirt -XFS_ERROR(EFAULT)LY-sE, dirt 0;Y-E}.-p-s /hault:p-sd, dirt -ENOTTY;Y-s} -}p-p-STATIC ily
-xfsoiHW_getbmap(
-sbhv_descnr		*bdp,
-sd,* Ok,.ile		*.ilp,
-sil s		(o.c ls,I-Eunsigtod _ar		cmd,
-sunsigtod 12ng		 rg)p-{Y-Ed,* Ok,getbmap		bm;Y-sil s		i.c lsLY-Eil s		error;Y-m-sif (copy_mver_user(&bm, (d,* Ok,getbmap,*) rg, snitof(bm))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-sif (bm.bmv_c*/in < 2)
-		r6dirt -XFS_ERROR(EINVAL);p-
-sifc ls =,(cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0)LY-sif ((o.c ls & IO_INVISo -s	i.c ls |= BMV_IF_NO_DMAPI_READ;Y-m-serror0= xfs_getbmap(bdp,,&bm, (d,* Ok,getbmap,*) rg+1,n(+c ls)LY-Eif (error) -s	, dirt -error;Y-m-sif (copy_to_user((d,* Ok,getbmap,*) rg, &bm, snitof(bm))o -s	r6dirt -XFS_ERROR(EFAULT)LY-s, dirt 0;Y-}p-
-STATIC ily
-xfsoiHW_getbmapx(
-sbhv_descnr		*bdp,
-sunsigtod 12ng		 rg)p-{Y-Ed,* Ok,getbmapx		bmx;Y-Ed,* Ok,getbmap		bm;Y-sil s		i.c lsLY-Eil s		error;Y-m-sif (copy_mver_user(&bmx, (d,* Ok,getbmapx,*) rg, snitof(bmx))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-sif (bmx.bmv_c*/in < 2)
-		r6dirt -XFS_ERROR(EINVAL);p-
-s/8
-	f* Map,input getbmapx,s,* OkureSto a getbmap
-	f* s,* OkureSfor xfs_getbmap.
-se*/m-sGETBMAP_CONVERT(bmx, bm);p-
-sifc ls =,bmx.bmv_i.c lsLY-Y-sif ((.c ls & (~BMV_IF_VALID)o -s	r6dirt -XFS_ERROR(EINVAL);p-
-sifc ls |= BMV_IF_EXTENDED;Y-m-serror0= xfs_getbmap(bdp,,&bm, (d,* Ok,getbmapx,*) rg+1,n(+c ls)LY-Eif (error) -s	, dirt -error;Y-m-sGETBMAP_CONVERT(bm, bmx)LY-p-sif (copy_to_user((d,* Ok,getbmapx,*) rg, &bmx, snitof(bmx))o -s	r6dirt -XFS_ERROR(EFAULT)LY-p-s, dirt 0;Y-}pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsoiops.c linux-2.4.27-rc4/fs/xfs/linux/xfsoiops.c
--- linux-2.4.26/fs/xfs/linux/xfsoiops.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsoiops.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,690 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_,*ans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_a2_HW.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_m*/in.h"
-#include "xfs_a2_HW_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ia2_HW_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ia2_HW.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinodh.h"
-#include "xfs_inodh.h"
-#include "xfs_bmap.h"
-#include "xfs_bin.h"
-#include "xfs_rta2_HW.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_maW.h"
-#include "xfs_attr.h"
-#include "xfs_buf_item.h"
-#include "xfs_utils.h"
-
-#include <linux/xattr.h>
-
-
-4-
-68 Pull0tH ulink c*/in andAsnitaupAfverSOHe-xfs inodh to(tH ulinux inodh
- -/--STATIC tic 
-valid]ee_fields(
-sd,* Ok, nodh	*ip)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP( p)LY-svattr_t		vaLY-Eil s	error;Y-m-sva.va_read = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NB1+afS;p-sVOP_GETATTR(vp,,&va, ATTR_LAZY, ct a, error);p-sip->i_nlink = va.va_nlink;p-sip->i_snita= va.va_snitLY-sip->i_b12B,s = va.va_nb12B,s;Y-}p-
-#ifdef CONFIG_XFS_POSIX_ACL
-4-
-68 DeSt
mome wheOH rnanprocess hasda(talid fs_s,* Ok,(kernel daemSFs
-68 loke knfsdAdon't igafRan fs_s,* Ok).
- -/--STATIC ilyAinlome
-has_fs_s,* Ok(d,* Ok,tead_s,* Ok,*tead)p-{I-E, dirty(tead->fs != init_tead.fs/LY-}b-#Snd(+
-
-STATIC ily
-linvfsomknod(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry,
-sil s	modh,
-sil s	rdev)p-{Y-Ed,* Ok, nodh	*ipLY-svattr_t		vaLY-Etnodh_t		*vp =,ct a, *dvp =,LINVFS_GET_VP(dir);p-sxfs_acl_t	* /hault_acl =,ct a;p-sattrexid,s_,	test_ /hault_acl =,_ACL_DEFAULT_EXISTSLY-sil s	error;Y-m-sif (test_ /hault_acl && test_ /hault_acl(dvp)m {p-sdif (!_ACL_ALLOC( /hault_acl)) -s		, dirt -ENOMEM;p-sdif (!_ACL_GET_DEFAULT(dvp,  /hault_acl))o{p-sds_ACL_FREE( /hault_acl);p-sd	 /hault_acl =,ct a;p-sE}
-6}b-p-#ifdef CONFIG_XFS_POSIX_ACL
-s/*
-	f* Cond(SISFclly0compiled so OHatAtH uACL bas  kernel changesAcan,be
-se* splik,out il o(sep ra   patchesA- remove OHdsfonce,MS_POSIXACL is
-	S*Aaccepted,nor0someroOH rnway0to( mplemSnt OHdsfexid,s.
-se*/m-sif (IS_POSIXACL(dir) && ! /hault_acl && has_fs_s,* Ok(currSnt)o -s	modh &= ~currSnt->fs->uread;b-#Snd(+
-
-	mems6e(&va, 0, snitof(va))LY-sva.va_read = XFS_AT_TYPE|XFS_AT_MODELY-sva.va_Oype = IFTOVT(modh);p-sva.va_rodh =,modhLY-p-sswinch (modh &,S_IFMToo{p-scas  S_IFCHR: cas  S_IFBLK: cas  S_IFIFO: cas  S_IFS+af:p-sdva.va_rdev = XFS_MKDEV(MAJOR(rdev), MINOR(rdev));p-sdva.va_read |= XFS_AT_RDEV;p-sd/*FALLTHROUGH*/m-scas  S_IFREG:Y-sEVOP_CREATE(dvp,  /ntry, &va, &vp,,ct a, error);p-sdbr6ckLY-Ecas  S_IFDIR:Y-sEVOP_MKDIR(dvp,  /ntry, &va, &vp,,ct a, error);p-sdbr6ckLY-E /hault:p-sderror =,EINVALLY-ssbr6ckLY-E}.-p-sif ( /hault_acl) {p-sdif (!error)o{p-sdserror0= _ACL_INHERIT(vp,,&va,  /hault_acl);p-sd	if (!error)o{p-sds	VMODIFY(vp)LY-EdE} S_HWo{p-sdssd,* Ok,dentry	teardownA= {}LY-EdEsil s	err2;p-m-s	ss/*AOh,2OH uhorror.m-s	ss68 I++we can't addAtH uACL we mustfback2out.m-s	ss68 ENOSPCAcan,hiO}H re, amSFgroOH rnnvings.m-s	ss68/m-s	ssteardown.d_inodh = ip =,LINVFS_GET_IP(vp);m-s	ssteardown.d_namg =,dentry->d_namg;m-s	ssremove_inodh_hash( p);p-sds	make_bad_inodh( p);p-sds	if (S_ISDIR(modh)o -s		sEVOP_RMDIR(dvp, &teardown,,ct a, err2);p-sds	e_HWp-sd	sEVOP_REMOVE(dvp, &teardown,,ct a, err2);p-sds	VN_RELE(vp)LY-Ed	}p-sd}p-sd_ACL_FREE( /hault_acl);p-s}.-p-sif (!error)o{p-sdASSERT(vp)LY-Edip =,LINVFS_GET_IP(vp);m-p-sdif (S_ISCHR(modh) ||,S_ISBLK(modh)o -s		ip->i_rdev = to_kdev_t(rdev)LY-Ede_HWoif (S_ISDIR(modh)o -s		valid]ee_fields( p);p-sdd_instanti]ee( /ntry,  p);p-sdvalid]ee_fields(dir);p-s}
-E, dirty-error;Y-}p-p-STATIC ily
-linvfsocre]eg(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry,
-sil s	modh)p-{I-E, dirtylinvfsomknod(dir,  /ntry, modh, 0)LY-}p-p-STATIC ily
-linvfsomkdir(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry,
-sil s	modh)p-{I-E, dirtylinvfsomknod(dir,  /ntry, modh|S_IFDIR, 0)LY-}p-p-STATIC d,* Ok,dentry -
-linvfsolookup(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry)p-{Y-Ed,* Ok, nodh	*ip =,ct a;p-stnodh_t		*vp, *cvp =,ct a;p-sil s	error;Y-m-sif (dentry->d_namg.len >= MAXNAMELENo -s	r6dirt ERR_PTR(-ENAMETOOLONG)LY-m-svp =,LINVFS_GET_VP(dir);p-sVOP_LOOKUP(vp,  /ntry, &cvp, 0, ct a, ct a, error);p-sif (!error)o{p-sdASSERT(cvp)LY-Edip =,LINVFS_GET_IP(cvp)LY-Edif (! p)o{p-sdsVN_RELE(cvp)LY-Ed	r6dirt ERR_PTR(-EACCES);p-sE}
-6}b-Eif (error && (error != ENOENT)o -s	r6dirt ERR_PTR(-error);p-sd_add( /ntry,  p);s/*ANegative entry goes inoif ip dsfct a68/m-sr6dirt ct a;p-}p-p-STATIC ily
-linvfsolink(
-sd,* Ok,dentry	*old_dentry,
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry)p-{Y-Ed,* Ok, nodh	*ip;s/*Ainodh of guy,beiigdlinked to(*/m-svnodh_t		*tdvp;s/*Atarget,directorySfor new,namg/link */m-svnodh_t		*vp;s/*Avp of namg beiigdlinked */m-sil s	error;Y-m-sip =,old_dentry->d_inodh;s/*Ainodh beiigdlinked to(*/m-sif (S_ISDIR(ip->i_m*dh)o -s	r6dirt -EPERM;p-Y-stdvp =,LINVFS_GET_VP(dir);p-svp =,LINVFS_GET_VP( p)LY-p-sVOP_LINK(tdvp, vp,  /ntry, ct a, error);p-sif (!error)o{p-sdVMODIFY(tdvp);p-sEVN_HOLD(vp)LY-Edvalid]ee_fields( p);p-sdd_instanti]ee( /ntry,  p);p-s}
-E, dirty-error;Y-}p-p-STATIC ily
-linvfsounlink(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry)p-{Y-Ed,* Ok, nodh	*inodhLY-Etnodh_t		*dvp;s/*AdirectoryScoinainiigdnamg to(e move */m-sil s	error;Y-m-sinodh = dentry->d_inodh;p-sdvp =,LINVFS_GET_VP(dir);p-
-EVOP_REMOVE(dvp,  /ntry, ct a, error);p-sif (!error)o{p-sdvalid]ee_fields(dir);s/*AFor0snit only 8/m-s	valid]ee_fields( nodh)LY-E}.-p-s, dirt -error;Y-}p-p-STATIC ily
-linvfsodymlink(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry,
-scoist char	*dymnamg)p-{Y-Ed,* Ok, nodh	*ipLY-svattr_t		vaLY-Etnodh_t		*dvp;s/*AdirectoryScoinainiigdnamg to(e move */m-stnodh_t		*cvp;s/*Ause }to(lookup(dymlink}to(put il,dentry -/m-sil s	error;Y-m-sdvp =,LINVFS_GET_VP(dir);p-scvp =,ct a;p-
-	mems6e(&va, 0, snitof(va))LY-sva.va_Oype = VLNK;p-sva.va_rodh =,irixodymlink_rodh ? 0777 & ~currSnt->fs->uread :,S_IRWXUGOLY-sva.va_read = XFS_AT_TYPE|XFS_AT_MODELY-
-serror0= 0;p-sVOP_SYMLINK(dvp,  /ntry, &va, (char,*)dymnamg, &cvp, ct a, error);p-sif (!error && cvp)o{p-sdASSERT(cvp->v_Oype ==,VLNKmLY-Edip =,LINVFS_GET_IP(cvp)LY-Edd_instanti]ee( /ntry,  p);p-sdvalid]ee_fields(dir);p-sdvalid]ee_fields( p); 4- snit needs upd]ee -/m-s}
-E, dirty-error;Y-}p-p-STATIC ily
-linvfsormdir(
-sd,* Ok, nodh	*dir,
-sd,* Ok,dentry	*dentry)p-{Y-Ed,* Ok, nodh	*inodh = dentry->d_inodh;p-stnodh_t		*dvp =,LINVFS_GET_VP(dir);p-sil s	error;Y-m-sVOP_RMDIR(dvp,  /ntry, ct a, error);p-sif (!error)o{p-sdvalid]ee_fields(inodh)LY-E	valid]ee_fields(dir);p-s}
-E, dirty-error;Y-}p-p-STATIC ily
-linvfsorSnamg(
-sd,* Ok, nodh	*odir,
-sd,* Ok,dentry	*odentry,
-sd,* Ok, nodh	*ndir,
-sd,* Ok,dentry	*ndentry)p-{Y-Ed,* Ok, nodh	*new_inodh = ndentry->d_inodh;p-stnodh_t		*fvp;s/*AfverSdirectoryS*/m-svnodh_t		*tvp;s/*Atarget,directoryS-/m-sil s	error;Y-m-sfvp =,LINVFS_GET_VP(odir);p-stvp =,LINVFS_GET_VP(ndir);p-
-EVOP_RENAME(fvp,,o /ntry, tvp,,n /ntry, ct a, error);p-sif (error) -s	, dirt -error;Y-m-sif (new_inodh)Y-E	valid]ee_fields(new_inodh)LY-m-svalid]ee_fields(odir);p-sif (ndir != odir)Y-E	valid]ee_fields(ndir);p-s, dirt 0;Y-}p-
-STATIC ily
-linvfsorScHlink(
-sd,* Ok,dentry	*dentry,
-schar		*buf,
-sil s	snit)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP(dentry->d_inodh);p-suio_t		uio;Y-E ovecnr	,iovLY-Eil s	error;Y-m-siov.iov_bas (= buf;m-siov.iov_len =,snitLY-Y-suio.uio_iov =,&iovLY-Euio.uio_offs6e0= 0;p-suio.uio_segflg =,UIO_USERSPACE;c-Euio.uio_resid =,snitLY-	uio.uio_iovcne = 1;p-
-	VOP_READLINK(vp,,&uio, 0, ct a, error);p-sif (error) -s	, dirt -error;Y-m-s, dirty(snit - uio.uio_resid/LY-}b---4-
-68 careful}H re - OHdsfduncSISFAcan,get,called recursively, so
-68 wt need to(be very,careful}about how muchAstack wt use.
- - uio dsfkma2_HWed foS OHisAr6ason...
- -/--STATIC ily
-linvfsofo2_Hwolink(
-sd,* Ok,dentry		*dentry,
-sd,* Ok,namgid]ea	*nd)p-{I-Etnodh_t			*vp;p-suio_t			*uio;Y-E ovecnr	,,iovLY-Eil s		error;Y-schar			*link;p-Y-sASSERT(dentry);Y-sASSERT(nd)LY-m-slink = (char,*)kma2_HW(MAXNAMELEN+1,nGFP_KERNEL)LY-Eif (!linko -s	r6dirt -ENOMEM;p-p-suio = (uio_t *)kma2_HW(snitof(uio_t),nGFP_KERNEL)LY-Eif (!uioo {p-sdkd/ho(linko; -s	r6dirt -ENOMEM;p-s}.-p-svp =,LINVFS_GET_VP(dentry->d_inodh);p-m-siov.iov_bas (= link;p-siov.iov_len =,MAXNAMELEN;p-p-suio->uio_iov =,&iovLY-Euio->uio_offs6e0= 0;p-suio->uio_segflg =,UIO_SYSSPACE;c-Euio->uio_resid =,MAXNAMELEN;p-suio->uio_iovcne = 1;p-
-	VOP_READLINK(vp,,uio, 0, ct a, error);p-sif (error) {p-sdkd/ho(uioo;p-sdkd/ho(linko; -s	r6dirt -error;Y-s} -p-slink[MAXNAMELEN - uio->uio_resid] = '\0';Y-skd/ho(uioo;p-
-s/8 vfsofo2_Hwolink , dirts0(-) errorse*/m-serror0= vfsofo2_Hwolink(nd, linko; -skd/ho(linko; -s, dirtyerror;Y-}p-p-STATIC ily
-linvfsopermissISF(
-sd,* Ok, nodh	*inodh,
-sil s	modh)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Eil s	error;Y-m-srodh <<= 6;ss/*AcoivertAfverSlinux to(tnodh access bitse*/m-sVOP_ACCESS(vp,,modh, ct a, error);p-s, dirty-error;Y-}p-p-STATIC ily
-linvfsorSvalid]ee(
-sd,* Ok,dentry	*dentry)p-{Y-Etnodh_t		*vp =,LINVFS_GET_VP(dentry->d_inodh);p-p-sif (unlikely(vp->v_fc l & VMODIFIED)o -s	r6dirt vn_revalid]ee(vp)Lp-s, dirt 0;Y-}p-
-STATIC ily
-linvfsos6eattr(
-sd,* Ok,dentry	*dentry,
-sd,* Ok, attrs*attr)p-{Y-Ed,* Ok, nodh	*inodh = dentry->d_inodh;p-sunsigtod _ar	ia_talid = attr->ia_talid;I-Etnodh_t		*vp =,LINVFS_GET_VP( nodh)LY-Evattr_t		vattrLY-Eil s	.c ls =,0LY-Eil s	error;Y-m-srems6e(&vattr, 0, snitof(vattr_t))LY-sif ((a_talid & ATTR_UID)o{p-sdvattr.va_read |= XFS_AT_UID;p-sdvattr.va_uid = attr->ia_uid;Y-E}.-sif ((a_talid & ATTR_GID)o{p-sdvattr.va_read |= XFS_AT_GID;p-sdvattr.va_gid = attr->ia_gid;Y-E}.-sif ((a_talid & ATTR_SIZE)o{p-sdvattr.va_read |= XFS_AT_SIZE;p-sdvattr.va_snit = attr->ia_snitLY-	}.-sif ((a_talid & ATTR_ATIME)o{p-sdvattr.va_read |= XFS_AT_ATIMELY-s	vattr.va_aSIme.tvos6c = attr->ia_aSImeLY-s	vattr.va_aSIme.tvons6c = 0LY-	}.-sif ((a_talid & ATTR_MTIME)o{p-sdvattr.va_read |= XFS_AT_MTIMELY-s	vattr.va_mSIme.tvos6c = attr->ia_mSImeLY-s	vattr.va_mSIme.tvons6c = 0LY-	}.-sif ((a_talid & ATTR_CTIME)o{p-sdvattr.va_read |= XFS_AT_CTIMELY-s	vattr.va_cSIme.tvos6c = attr->ia_cSImeLY-s	vattr.va_cSIme.tvons6c = 0LY-	}.-sif ((a_talid & ATTR_MODE)o{p-sdvattr.va_read |= XFS_AT_MODELY-sdvattr.va_rodh = attr->ia_modh;p-sdif (! n_group_p(inodh->i_gid) && !capable(CAP_FSETID)o -s		inodh->i_modh &= ~S_ISGID;p-s}.-p-sif ((a_talid & (ATTR_MTIME_SET | ATTR_ATIME_SET)o -s	.c ls =,ATTR_UTIMELY-m-sVOP_SETATTR(vp,,&vattr, .c ls, ct a, error);p-sif (error) -s	, dirt(-error);s/*APositive error0upAfverSXFS(*/m-sif ((a_talid & ATTR_SIZE)o{p-sderror0= vm,* nc]ee( nodh, attr->ia_snit);p-s}.-p-sif (!error)o{p-sdvn_revalid]ee(vp)Lp-s}
-E, dirtyerror;Y-}p-p-STATIC tic 
-linvfso,* nc]ee(Y-Ed,* Ok, nodh	*inodh)p-{Y-Eb12B,o,* nc]ee_page(inodh->i_mapping, (nodh->i_snit,ylinvfsoget_b12B,)LY-}p-p-STATIC ily
-linvfsos6exattr(
-sd,* Ok,dentry	*dentry,
-scoist char	*namg,Y-Evic 		*d]ea,
-ssnit_ s	snit,
-sil s	+c ls)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP(dentry->d_inodh);p-schar		*attr = (char,*)namg;m-sattrnamgs_,	*namgsp;p-Eil s	x.c ls =,0LY-Eil s	error;Y-m-snamgsp = attrolookup_namgspace(attr, attronamgspaces, ATTR_NAMECOUNT)LY-Eif (!namgspo -s	r6dirt -EOPNOTSUPP;m-sattr += namgsp->attronamglenLY-	error0= namgsp->attrocapable(vp, ct a);p-sif (error) -s	, dirt error;Y-m-s/*ACoivertALinux syscall to(XFS(inSt
nal ATTR .c ls */m-sif (.c ls & XATTR_CREATE)p-sdxfc ls |= ATTR_CREATE;m-sif (.c ls & XATTR_REPLACE)p-sdxfc ls |= ATTR_REPLACE;m-sxfc ls |= namgsp->attrofc lLp-s, dirt namgsp->attros6e(vp,,attr, (tic A*)d]ea, snit, x.c ls)LY-}p-p-STATIC dsnit_ 
-linvfsog6exattr(
-sd,* Ok,dentry	*dentry,
-scoist char	*namg,Y-Evic 		*d]ea,
-ssnit_ s	snit)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP(dentry->d_inodh);p-schar		*attr = (char,*)namg;m-sattrnamgs_,	*namgsp;p-Eil s	x.c ls =,0LY-Essnit_ s	error;Y-m-snamgsp = attrolookup_namgspace(attr, attronamgspaces, ATTR_NAMECOUNT)LY-Eif (!namgspo -s	r6dirt -EOPNOTSUPP;m-sattr += namgsp->attronamglenLY-	error0= namgsp->attrocapable(vp, ct a);p-sif (error) -s	, dirt error;Y-m-s/*ACoivertALinux syscall to(XFS(inSt
nal ATTR .c ls */m-sif (!snit) {p-sdxfc ls |= ATTR_KERNOVALLY-ssd]ea =,ct a;p-s}m-sxfc ls |= namgsp->attrofc lLp-s, dirt namgsp->attrog6e(vp,,attr, (tic A*)d]ea, snit, x.c ls)LY-}p-p-STATIC dsnit_ 
-linvfsolistxattr(
-sd,* Ok,dentry		*dentry,
-schar			*d]ea,
-ssnit_ s		snit)p-{I-Etnodh_t			*vp =,LINVFS_GET_VP(dentry->d_inodh);p-sil s		error, x.c ls = ATTR_KERNAMELSLY-Essnit_ s	s, sultLY-p-sif (!snit)p-sdxfc ls |= ATTR_KERNOVALLY-sxfc ls |= capable(CAP_SYS_ADMIN) ? ATTR_KERNFt aS : ATTR_KERNORMALSLY-Y-	error0= attrog6nericolist(vp,  ]ea, snit, x.c ls,,&, sult);p-sif (error <,0)
-		r6dirt error;Y-sr6dirt , sultLY-}p-p-STATIC ily
-linvfsorSmovexattr(
-sd,* Ok,dentry	*dentry,
-scoist char	*namg)p-{I-Etnodh_t		*vp =,LINVFS_GET_VP(dentry->d_inodh);p-schar		*attr = (char,*)namg;m-sattrnamgs_,	*namgsp;p-Eil s	x.c ls =,0LY-Eil s	error;Y-m-snamgsp = attrolookup_namgspace(attr, attronamgspaces, ATTR_NAMECOUNT)LY-Eif (!namgspo -s	r6dirt -EOPNOTSUPP;m-sattr += namgsp->attronamglenLY-	error0= namgsp->attrocapable(vp, ct a);p-sif (error) -s	, dirt error;Y-sxfc ls |= namgsp->attrofc lLp-s, dirt namgsp->attrorSmove(vp,,attr, x.c ls)LY-}p-p-
-d,* Ok, nodhooperatISFs(linvfsofile_ nodhooperatISFs(= {p-s.permissISF		= linvfsopermissISF,
-s.,* nc]ee		= linvfso,* nc]ee,
-s.revalid]ee		= linvfsorevalid]ee,
-s.s6eattr		= linvfsos6eattr,
-s.s6exattr		= linvfsos6exattr,
-s.g6exattr		= linvfsog6exattr,
-s.listxattr		= linvfsolistxattr,
-s.removexattr		= linvfsoremovexattr,
-};p-
-d,* Ok, nodhooperatISFs(linvfsodir_ nodhooperatISFs(= {p-s.cre]eg			= linvfsocre]eg,
-s.lookup			= linvfsolookup,
-s.link			= linvfsolink,
-s.unlink			= linvfsounlink,
-s.symlink		= linvfsosymlink,
-s.mkdir			= linvfsomkdir,
-s.rmdir			= linvfsormdir,
-s.mknod			= linvfsomknod,
-s.renamg			= linvfsorenamg,Y-E.permissISF		= linvfsopermissISF,
-s.revalid]ee		= linvfsorevalid]ee,
-s.s6eattr		= linvfsos6eattr,
-s.s6exattr		= linvfsos6exattr,
-s.g6exattr		= linvfsog6exattr,
-s.listxattr		= linvfsolistxattr,
-s.removexattr		= linvfsoremovexattr,
-};p-
-d,* Ok, nodhooperatISFs(linvfsodymlink_ nodhooperatISFs(= {p-s.rScHlink		= linvfsorecHlink,
-s.fo2_Hwolink		= linvfsofo2_Hwolink,Y-E.permissISF		= linvfsopermissISF,
-s.revalid]ee		= linvfsorevalid]ee,
-s.s6eattr		= linvfsos6eattr,
-s.s6exattr		= linvfsos6exattr,
-s.g6exattr		= linvfsog6exattr,
-s.listxattr		= linvfsolistxattr,
-s.removexattr		= linvfsoremovexattr,
-};pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsoiops.h linux-2.4.27-rc4/fs/xfs/linux/xfsoiops.h
--- linux-2.4.26/fs/xfs/linux/xfsoiops.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsoiops.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,51 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifndef __XFS_IOPS_H__--# /home __XFS_IOPS_H__--
-extSrt d,* Ok, nodhooperatISFs(linvfsofile_ nodhooperatISFs;
-extSrt d,* Ok, nodhooperatISFs(linvfsodir_ nodhooperatISFs;
-extSrt d,* Ok, nodhooperatISFs(linvfsodymlink_ nodhooperatISFs;--
-extSrt d,* Ok,file_operatISFs(linvfsofile_operatISFs;
-extSrt d,* Ok,file_operatISFs(linvfsoinvisofile_operatISFs;
-extSrt d,* Ok,file_operatISFs(linvfsodir_operatISFs;--
-extSrt d,* Ok,address_space_operatISFs(linvfsoaops;--
-extSrt intrlinvfsoget_b12B,(d,* Ok, nodh *, 12ng, d,* Ok,bufft
_H ad *, int);
-extSrt tic Alinvfsounw   tet_done(d,* Ok,bufft
_H ad *, int);
-
-extSrt intrxfsoiHWtl(d,* Ok,bhv_desc *, d,* Ok, nodh *, d,* Ok,file *,
-                        iin, unsigtod _ar, unsigtod 12ng);
-
-#Snd(+ 4- __XFS_IOPS_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsolinux.h linux-2.4.27-rc4/fs/xfs/linux/xfsolinux.h
--- linux-2.4.26/fs/xfs/linux/xfsolinux.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsolinux.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,380 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifndef __XFS_LINUX__--# /home __XFS_LINUX__--
-#include <linux/Oypes.h>
-#include <linux/config.h>
-
-4-
-68 SomerOypesrare cond(SISFcl depSndiigdoinOHe-target,system.
-68 XFS_BIG_BLKNOS needs b12B, lay rddidk,address s to(ben64 bits.
-68 XFS_BIG_INUMS needs OHe-VFS(inodh numbt
 to(ben64 bits, as well
-68( sAr6quiriig XFS_BIG_BLKNOS to(benset.
- -/--# /home XFS_BIG_BLKNOS	0--# /home XFS_BIG_INUMS	0--
-#include <xfs_,ypes.h>
-#include <xfs_arch.h>
-
-#include <kmem.h>
-#include <mr12B,.h>
-#include <spin.h>
-#include <sv.h>
-#include <mutex.h>
-#include <sema.h>
-#include <SIme.h>
-
-#include <support/qsort.h>
-#include <support/ktrace.h>
-#include <support/debug.h>
-#include <support/move.h>
-#include <support/uuid.h>
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/.ile.h>
-#include <linux/swap.h>
-#include <linux/errno.h>
-#include <linux/12B,s.h>
-#include <linux/sche .h>
-#include <linux/bitops.h>
-#include <linux/major.h>
-#include <linux/pagemap.h>
-#include <linux/seq_.ile.h>
-#include <linux/init.h>
-#include <linux/prHW_fs.h>
-
-#include <asm/page.h>
-#include <asm/div64.h>
-#include <asm/p ram.h>
-#include <asm/uaccess.h>
-#include <asm/byteordIS.h>
-#include <asm/uFcligtod.h>
-
-#include <xfs_beigaior.h>
-#include <xfs_vfs.h>
-#include <xfs_cre .h>
-#include <xfs_vnodh.h>
-#include <xfs_staSs.h>
-#include <xfs_sysWtl.h>
-#include <xfs_iops.h>
-#include <xfs_supIS.h>
-#include <xfs_globals.h>
-#include <xfs_fs_subS.h>
-#include <xfs_lrw.h>
-#include <xfs_buf.h>
-
-4-
-68 F atureSmacros (didable/enable)
- -/--# /home HAVE_REFCACHEs/*A2.4nusesda(NFS(reft
ence,cache;A2.6+,doeon_ty -/--#undef  HAVE_SENDFILEs/*AsSnd.ile(2)ndsfaA2.6+,system,call,n_ty in,2.4n-/--
-#ifndef EVMS_MAJOR--# /home EVMS_MAJOR 117b-#Snd(+
-
-4-
-68 St]ee fc l foS unw   tet extSnk,bufft
s.p- -
-68 Wt need to(be ableuto(did,iiguish(betweeinOHeseAand delay d
-68( 2_HW]ee bufft
s winvin,XFS.  THe-g6neric IO path code doeo
-68(_ty need to(did,iiguish(- wt use OHe-BH_Delay fc l foS bonvp-f* dela2_HWAand OHeseAond(sk-uniniticlise }bufft
s.p- -/--# /home BH_Unw   tet		BH_Priv]eeStart--# /home bufft
_unw   tet(bh)	__bufft
_staSe(bh, Unw   tet)
-d,aSIcAinlome tic Aset_bufft
_unw   tet_io(d,* Ok,bufft
_H ad *bh)p-{Y-Ebh->b_Snd_io = linvfsounw   tet_doneLY-}p-BUFFER_FNS(Unw   tet, unw   tet)--
-# /home xfs_refcache_snitsxfs_p rams.refcache_snit.val
-# /home xfs_refcache_purgeoc*/in xfs_p rams.refcache_purge.val
-# /home res,*icted_chownsxfs_p rams.res,*ict_chown.val
-# /home irixodgid_inH ritsxfs_p rams.dgid_inH rit.val
-# /home irixodymlink_rodhsxfs_p rams.dymlink_rodh.val
-# /home xfs_panic_read	sxfs_p rams.panic_read.val
-# /home xfs_error_lmvel	sxfs_p rams.error_lmvel.val
-# /home xfs_syncd_inct
valsxfs_p rams.dync_inct
val.val
-# /home xfs_staSs_clear	sxfs_p rams.staSs_clear.val
-# /home xfs_inH rit_syncsxfs_p rams.inH rit_sync.val
-# /home xfs_inH rit_nodumpsxfs_p rams.inH rit_nodump.val
-# /home xfs_inH rit_noaSImesxfs_p rams.inH rit_noaSIm.val
-# /home xfs_flush_inct
valsxfs_p rams.flush_inct
val.val
-# /home xfs_age_bufft
	sxfs_p rams.age_bufft
.val
-
-# /home currSnt_cpu()		smp_processor_id()
-# /home currSnt_pid()		(currSnt->pid)
-# /home currSnt_fsuid(cre )	(currSnt->fsuid)
-# /home currSnt_fsgid(cre )	(currSnt->fsgid)
-
-# /home NBPP		PAGE_SIZE
-# /home DPPSHFT		(PAGE_SHIFT(- 9)
-# /home NDPP		(1 << (PAGE_SHIFT(- 9))
-# /home dtop(DD)	(((DD) + NDPP(- 1) >> DPPSHFT)
-# /home dtopt(DD)	((DD) >> DPPSHFT)
-# /home dpoff(DD)	((DD) & (NDPP-1))
-
-# /home NBBY		8ss/*Anumbt
 o++bitsepIS byte -/--# /home	NBPC		PAGE_SIZEs/*ANumbt
 o++by  s pIS click -/--# /home	BPCSHIFT	PAGE_SHIFTs/*ALOG2(NBPC)+(++exactd-/--
-4-
-68 Snit of b12B, device i/o dsfp rameSt
nitd H re.
-68 CurrSntlyrOH usystem,supportsfp ge-snitd i/o.p- -/--# /home	BLKDEV_IOSHIFTs	BPCSHIFT--# /home	BLKDEV_IOSIZEs	(1<<BLKDEV_IOSHIFT)
-4-Anumbt
 o++BB'sepIS b12B, device b12B, -/--# /home	BLKDEV_BBs	BTOBB(BLKDEV_IOSIZE)--
-4-+by  s to(clicks -/--# /home	btoc(x)		(((__psunsigtod_t)(x)+(NBPC-1))>>BPCSHIFT)--# /home	btoct(x)	((__psunsigtod_t)(x)>>BPCSHIFT)--# /home	btoc64(x)	(((__uinc64_t)(x)+(NBPC-1))>>BPCSHIFT)--# /home	btoct64(x)	((__uinc64_t)(x)>>BPCSHIFT)--# /home	io_btoc(x)	(((__psunsigtod_t)(x)+(IO_NBPC-1))>>IO_BPCSHIFT)--# /home	io_btoct(x)	((__psunsigtod_t)(x)>>IO_BPCSHIFT)--
-4-+off_t+by  s to(clicks -/--# /home+offtoc(x)       (((__uinc64_t)(x)+(NBPC-1))>>BPCSHIFT)--# /home+offtoct(x)      ((xfs_off_t)(x)>>BPCSHIFT)--
-4-+clicks to(off_t+by  s -/--# /home	ctooff(x)	((xfs_off_t)(x)<<BPCSHIFT)--
-4-+clicks to(by  s -/--# /home	ctob(x)		((__psunsigtod_t)(x)<<BPCSHIFT)--# /home btoct(x)        ((__psunsigtod_t)(x)>>BPCSHIFT)--# /home	ctob64(x)	((__uinc64_t)(x)<<BPCSHIFT)--# /home	io_ctob(x)	((__psunsigtod_t)(x)<<IO_BPCSHIFT)--
-4-+by  s to(clicks -/--# /home+btoc(x)         (((__psunsigtod_t)(x)+(NBPC-1))>>BPCSHIFT)--
-#ifndef CELL_CAPABLE--# /home+FSC_NOTIFY_NAME_CHANGED(vp)b-#Snd(+
-
-#ifndef ENOATTR--# /home ENOATTR		ENODATAss/*AAt,*ibute _ty found -/--#Snd(+
-
-4- Note: EWRONGFS nevIS visibleuoutside OHe-kernel -/--# /home	EWRONGFS	EINVALss/*AM*/in winv2wrSFgr.ilesystem,Oype -/--
-4-
-68 XXX EFSCORRUPTED needs aAr6al(talue in,errno.h. asm-i386/errno.h won't
-68     , dirt codes,out o++itseknownArange in,errno.
-68 XXX Also+_tye: needs Oo(be < 1000 and fairlyruniqueAonALinux (mustn't
-68     conflicn winv2 nyrcode wt use alrecHynor0 nyrcode a drivIS mayfuse)
-68 XXX SomeroptISFs((currSntlyrwe do #2):
- -	1/ New error0code ["Filesystem,dsfcorrupted", _afSt
_ glibc upd]eed]
- -	2/ 990 ["UnknownAerror0990"]
- -	3/ EUCLEAN ["S,* OkureSneeds cleaniig"]
- -	4/ACoivertAEFSCORRUPTED Oo(EIO [justfprior to(e dirt il o(userspace]p- -/--# /home EFSCORRUPTED    990ss/*AFilesystem,dsfcorruptedn-/--
-# /home SYNCHRONIZE()	barrier()
-# /home __e dirt_address __buil,ii_e dirt_address(0)--
-4-
-68 IRIX (BSD) quotactl makes use o++sep ra   commands foS user/group,
- - wH reasAonALinux OH usyscall encodes,OHdoninformaSISF il o(OH ucmd
-68(field (see OHe-QCMDSmacro in,quota.h).  THeseSmacros help-keep OHe
-68 code portableu- OHeyrare _ty visibleufverSOHe-syscall inSt
face.
- -/--# /home Q_XSETGQLIM	XQM_CMD(0x8)s/*AsSt groupsddidk,limitse*/m-# /home Q_XGETGQUOTAsXQM_CMD(0x9)s/*AgSt groupsddidk,limitse*/m-
-4- IRIX usesda(dynamic sniiig algorithm (ndquot = 200 +Anumprocs*2)e*/m-/8 wt mayfwell need to(home-tune OHdsfif it eveS becomesdaF issue.  */m-# /home DQUOT_MAX_HEURISTIC	1024s/*ANR_DQUOTS */m-# /home ndquot			DQUOT_MAX_HEURISTICm-
-4- IRIX usesdOH ucurrSnt0snit o++OHeAnamg cache to(guess a good(talue */m-/8 - OHdsfisn't OHe-samg but is a good(enough,startiig pointrfor now. */m-# /home DQUOT_HASH_HEURISTIC	.iles_staS.nr_.ilesm-
-4- IRIX inodhs maiinain,OHe-projece ID also, zerorOHdonfield onALinux */m-# /home DEFAULT_PROJID	0--# /home dfltprid	DEFAULT_PROJID--
-# /home MAXPATHLEN	1024--
-# /home MIN(a,b)	(min(a,b))
-# /home MAX(a,b)	(max(a,b))
-# /home howmany(x, y)	(((x)+((y)-1))/(y))
-# /home roundup(x, y)	((((x)+((y)-1))/(y))*(y))
-
-4-
-68 JuggleuIRIX device numbt
sA- still use }in,ond(sk s,* Okures
- -/--# /home XFS_DEV_BITSMAJOR	14--# /home XFS_DEV_BITSMINOR	18--# /home XFS_DEV_MAXMAJ		0x1ff--# /home XFS_DEV_MAXMIN		0x3ffff--# /home XFS_DEV_MAJOR(dev)	((int)(((unsigtod)(dev)>>XFS_DEV_BITSMINOR) \ -s			    & XFS_DEV_MAXMAJ))
-# /home XFS_DEV_MINOR(dev)	((int)((dev)&XFS_DEV_MAXMIN))
-# /home XFS_MKDEV(major,minor)o((xfs_dev_t)(((major)<<XFS_DEV_BITSMINOR) \ -s			    | (minor&XFS_DEV_MAXMIN)))
-
-# /home XFS_DEV_TO_KDEVT(dev)	mk_kdev(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev))
-
-
-4- Prod Oe a kernel stack tracee*/m-
-d,aSIcAinlome tic Axfs_staB,o,*ace(tic )p-{Y-Edump_staB,()LY-}p-p-
-/*AM*ve OHe-kernel do_div  /hom(SISF(off to(ome side -/--
-#if  /home }__i386__--/*AFor0ia32 wt need to(pull0somer,*icks to(gSt pastfvarious+versISFo
-68(o++OHeAcompiler wHich,do+_tyiloke us usiig do_div in,OHe-middle
-68(o++largefduncSISFs.p- -/--d,aSIcAinlome __u32 xfs_do_div(tic A*a, __u32 b, int n)p-{Y-E__u32srod;Y-p-sswinch (n) {p-sdcas  4:p-sdsrod = *(__u32 *)a % bLY-ss	*(__u32 *)a = *(__u32 *)a / bLY-ss	e dirt rod;Y-sdcas  8:p-sds{p-sdsunsigtod 12ng __upp r,(__low,(__high,(__rod;Y-sdE__u64	c = *(__u64 *)a;Y-sdE__upp r0= __high0= c >> 32;Y-sdE__low0= c;Y-sdEif (__high)o{p-sds	__upp r0= __high0% (b);p-sds	__high0= __high0/ (b);p-sds}p-sd	asm("divl %2":"=a" (__low), "=d" (__rod):"rm" (b), "0" (__low), "1" (__upp r));p-sd	asm("":"=A" (c):"a" (__low),"d" (__high))LY-ss	*(__u64 *)a0= c;Y-sdEe dirt __rod;Y-sdE}
-6}b-p-s/*ANOTREACHED68/m-sr6dirt 0;Y-}p-
-/8 Snde effece d/ho(64 bit rod operatISF -/--d,aSIcAinlome __u32 xfs_do_rod(tic A*a, __u32 b, int n)p-{Y-Eswinch (n) {p-sdcas  4:p-sdsr6dirt *(__u32 *)a % bLY-sscas  8:p-sds{p-sdsunsigtod 12ng __upp r,(__low,(__high,(__rod;Y-sdE__u64	c = *(__u64 *)a;Y-sdE__upp r0= __high0= c >> 32;Y-sdE__low0= c;Y-sdEif (__high)o{p-sds	__upp r0= __high0% (b);p-sds	__high0= __high0/ (b);p-sds}p-sd	asm("divl %2":"=a" (__low), "=d" (__rod):"rm" (b), "0" (__low), "1" (__upp r));p-sd	asm("":"=A" (c):"a" (__low),"d" (__high))LY-ss	e dirt __rod;Y-sdE}
-6}b-p-s/*ANOTREACHED68/m-sr6dirt 0;Y-}p-#e_HWp-d,aSIcAinlome __u32 xfs_do_div(tic A*a, __u32 b, int n)p-{Y-E__u32srod;Y-p-sswinch (n) {p-sdcas  4:p-sdsrod = *(__u32 *)a % bLY-ss	*(__u32 *)a = *(__u32 *)a / bLY-ss	e dirt rod;Y-sdcas  8:p-sdsrod = do_div(*(__u64 *)a, b)LY-ss	e dirt rod;Y-s}b-p-s/*ANOTREACHED68/m-sr6dirt 0;Y-}p-
-/8 Snde effece d/ho(64 bit rod operatISF -/--d,aSIcAinlome __u32 xfs_do_rod(tic A*a, __u32 b, int n)p-{Y-Eswinch (n) {p-sdcas  4:p-sdsr6dirt *(__u32 *)a % bLY-sscas  8:p-sds{p-sds__u64	c = *(__u64 *)a;Y-sdEr6dirt do_div(c, b)LY-ss	}
-6}b-p-s/*ANOTREACHED68/m-sr6dirt 0;Y-}p-#end(+
-
-#undef do_div--# /home do_div(a, b)	xfs_do_div(&(a), (b), snitof(a))
-# /home do_rod(a, b)	xfs_do_rod(&(a), (b), snitof(a))
---d,aSIcAinlome __uinc64_t roundup_64(__uinc64_t x, __uinc32_t y)p-{Y-Ex += y(- 1LY-sdo_div(x, y)Lp-s, dirt(x * y)Lp-}
-
-#Snd(+ 4- __XFS_LINUX__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsolrw.c linux-2.4.27-rc4/fs/xfs/linux/xfsolrw.c
--- linux-2.4.26/fs/xfs/linux/xfsolrw.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsolrw.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,979 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiigdOHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--4-
-68  fs/xfs/linux/xfsolrw.c (Linux R ad W     stuff)
- -
-68/--
-#include "xfs.h"
-
-#include "xfs_fs.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_,*ans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_a2_HW.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_m*/in.h"
-#include "xfs_a2_HW_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ia2_HW_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ia2_HW.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinodh.h"
-#include "xfs_inodh.h"
-#include "xfs_bmap.h"
-#include "xfs_bin.h"
-#include "xfs_rta2_HW.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_refcache.h"
-#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_maW.h"
-#include "xfs_attr.h"
-#include "xfs_ nodhoitem.h"
-#include "xfs_buf_item.h"
-#include "xfs_utils.h"
-#include "xfs_ omap.h"
-
-#include <linux/capability.h>
-
-
-#if  /home (XFS_RW_TRACE)p-tic 
-xfs_rw_enSt
o,*ace(Y-Eil s	tag,
-sxfs_iocorh_t	*io,
-scoist char	*buf,
-ssnit_ s	snit,
-sloff_t		offs6e,
-sil s	io+c ls)p-{I-Exfs_ nodhot	*ip =,XFS_IO_INODE(ioo;p-
-sif ((p->i_rwtracee==,ct a) -s	, dirtLp-sktrace_enSt
((p->i_rwtrace,
-s	(tic A*)(unsigtod 12ng)tag,
-s	(tic A*)ip,
-s	(tic A*)((unsigtod 12ng)(((p->i_d.di_snita>> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)((p->i_d.di_snita& 0xffffffff)),
-s	(tic A*)(__psil _t)buf,
-s	(tic A*)((unsigtod 12ng)snit),
-s	(tic A*)((unsigtod 12ng)((offs6e0>> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)(offs6e0& 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)io+c ls),
-s	(tic A*)((unsigtod 12ng)(((o->io_new_snita>> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)((o->io_new_snita& 0xffffffff)),
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a)Lp-}
-
-tic 
-xfs_inval_cachedo,*ace(Y-Exfs_iocorh_t	*io,
-sxfs_off_t	offs6e,
-sxfs_off_t	len,
-sxfs_off_t	firse,
-sxfs_off_t	last)p-{I-Exfs_ nodhot	*ip =,XFS_IO_INODE(ioo;p-
-sif ((p->i_rwtracee==,ct a) -s	, dirtLp-sktrace_enSt
((p->i_rwtrace,
-s	(tic A*)(__psil _t)XFS_INVAL_CACHED,
-s	(tic A*)ip,
-s	(tic A*)((unsigtod 12ng)((offs6e0>> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)(offs6e0& 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)((len >> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)(len & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)((firse >> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)(firse & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)((lase >> 32) & 0xffffffff)),
-s	(tic A*)((unsigtod 12ng)(lase & 0xffffffff)),
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a,
-s	(tic A*)ct a)Lp-}
-#Snd(+
-
-4-
-68Exfs_iozero
- -
-68Exfs_iozero clearsdOH uspecifiBdtrange of bufft
,suppliBd,
- -	and marks all0tH uaffecee }b12B,s as(talid and modifiBd.  If
- -	anuaffecee }b12B, don_ty( 2_HW]eed,Ait,will be a2_HW]eed.  If
- -	anuaffecee }b12B, don_ty(completely0overw   tet, and don_ty
- -	talid befor  OH uoperatISF,Ait,will be recHAfverSdisk befor 
- -	beiigdparticlly0zeroBd.d- -/--STATIC ily
-xfs_iozero(Y-Ed,* Ok, nodh		*ip,s/*Ainodhss	*/
-sloff_t			pos,s/*Aoffs6e0in,.iles	*/
-ssnit_ s	sc*/in,s/*Asnit o++d]ea to(zeros	*/
-sloff_t			Snd_snit)s/*Amax,file snit  o(setd-/--{I-Eunsigtod		by  s;Y-Ed,* Ok,p ges	*p ge;Y-Ed,* Ok,address_space	*mapping;p-schar			*kaddr;p-sil s		d,aSus;--
-	mapping = ip->i_mappingLY-sdo {p-sdunsigtod 12ng index,Aoffs6e;--
-		offs6e0= (pos & (PAGE_CACHE_SIZE -1)); 4- Winvin,p ge 8/m-s	index0= pos >> PAGE_CACHE_SHIFTLY-ssby  s = PAGE_CACHE_SIZE -Aoffs6e;--dEif (by  s > c*/ino -s		by  s = c*/in;--
-		d,aSus = -ENOMEM;p-sdp ge = grab_cache_page(mapping, (ndex)LY-Edif (!pageo -s		br6ckLY- -s	kaddr = kmap(pageo;
-		d,aSus = mapping->a_ops->prep re_w    (ct a, page,Aoffs6e,p-sds				offs6e0++by  s)LY-Edif (d,aSus)o{p-sdsgo o(un12B,LY-Ed}b-p-ssrems6e((tic A*) (kaddr +Aoffs6e), 0, by  s)LY-Edflush_dcache_page(pageo;
-		d,aSus = mapping->a_ops->commit_w    (ct a, page,Aoffs6e,p-sds				offs6e0++by  s)LY-Edif (!d,aSus)o{p-sdspos += by  s;Y-E	sc*/in -= by  s;Y-E	sif (pos > i_snitorecH( p)o -s		si_snitow    (ip, pos < Snd_snit ? pos : Snd_snit)LY-Ed}b-p-un12B,:p-sdkunmap(pageo;
-		un12B,_page(pageo;
-		page_cache_release(pageo;
-		if (d,aSus) -s		br6ckLY-	} wHile (c*/ino;Y-m-s, dirty(-d,aSus);Y-}b---4-
-68 xfs_inval_cachedopages
-68 
-68 T/donroutinendsfrespoisibleufor-keepiig direct I/O and bufft
od I/O
-68 somewHat c*H rent.  FverSH re wt make surfROHatAwe'rfRatAleast
-68 temporarily0holdiigdOHe(inodh I/O 12B, exclusivelyAand OHen,call
-68 tHe-p ge cache to(flush and dnvalid]ee0 nyrcached-p ges.  If tHer 
- -rare _trcached-p ges OHisAroutinenwill be very,quick.d- -/--tic 
-xfs_inval_cachedop ges(Y-Etnodh_t		*vp,Y-Exfs_iocorh_t	*io,
-sxfs_off_t	offs6e,
-sil s	w    ,
-sil s	rel2B,)p-{I-Exfs_m*/in_t	*mp;p-
-sif (!VN_CACHED(vp))o{p-sd, dirtLp-s}b-p-smp =,(o->io_m*/in;--
-	4-
-	68 Wt need to(gSt tHe-I/O 12B, exclusivelyAin,ordIS
-	68  o(safelyAinvalid]ee0p ges and mappings.m-s */m-sif (rel2B,)o{p-sdXFS_IUNLOCK(mp, io, XFS_IOLOCK_SHAREDo;
-		XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL);p-s}.-p-s4- W   iigdbeyond EOF cre]egs a holfROHatAmustfbe0zeroBd */m-sif (w     && (offs6e0> XFS_SIZE(mp, io))) {p-sdxfs_fsnit_ sisnitLY-Y-s	XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RDo;
-		isnit = XFS_SIZE(mp, io);
-		if (offs6e0> isnit) {p-sddxfs_zero_tof(vp, io, offs6e, isnit, offs6e);p-sE}
-6dXFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RDo;
-	}.-p-sxfs_inval_cachedo,*ace(io, offs6e, -1, ctooff(offtoct(offs6e)), -1);p-sVOP_FLUSHINVAL_PAGES(vp,,ctooff(offtoct(offs6e)), -1, FI_REMAPF_LOCKEDo;
-	if (rel2B,)o{p-sdXFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL);p-s}.-}.-p-ssnit_ s	s4-+by  s recH,nor0(-) Aerror0*/m-xfs_recH(
-Ebhv_desc_t      *bdp,
-sd,* Ok,.iles*.ile,
-schar		*buf,
-ssnit_ s	snit,
-sloff_t		*offs6e,
-sil s	io+c ls,
-scredo,          *credp)p-{Y-Essnit_ s	r6e;--dxfs_fsnit_ sn;
-Exfs_ nodhot	*ip;
-Exfs_m*/in_t	*mp;p-
-sip =,XFS_BHVTOI(bdp);p-smp =,(p->i_m*/in;--
-	XFS_STATS_INC(xs_recH_calls);p-p-sif (unlikely(io+c ls & IO_ISDIRECT)) {p-sdif (((__psil _t)buf & BBMASK) ||p-sd    (*offs6e0& mp->m_b12B,read) ||p-sd    (snita& mp->m_b12B,read)) {p-sddif (*offs6e0>=,(p->i_d.di_snit)o{p-sds	, dirty(0);p-sds}p-sd	r6dirt -XFS_ERROR(EINVAL);p-sE}
-6}b-
-6n =,XFS_MAXIOFFSET(mp) -A*offs6e;--dif ((n <= 0) || (snita== 0)) -s	, dirt 0;p-p-sif (n < snit)p-sdsnit = n;p-p-sif (XFS_FORCED_SHUTDOWN(mp))o{p-sd, dirt -EIO;
-	}.-p-sif (!(io+c ls & IO_ISLOCKEDo)p-sdxfs_i12B,(ip, XFS_IOLOCK_SHAREDo;
-p-sif (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&m-s    !(io+c ls & IO_INVIS)) {p-sdiin error;Y-s	vrw12B,o, 12B,Oype = VRWLOCK_READ;p-sdiin dm.c ls =,FILP_DELAY_FLAG(.ile) | DM_SEM_FLAG_RD(io+c lso;
-p-s	error0= XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),A*offs6e, snit,p-sds	      dm.c ls, &12B,Oype);
-		if (error)o{p-sdsif (!(io+c ls & IO_ISLOCKEDo)p-sdsdxfs_iun12B,(ip, XFS_IOLOCK_SHAREDo;
-	s	r6dirt -error;Y-sE}
-6}b-
-6if (unlikely(io+c ls & IO_ISDIRECT)) {p-sdxfs_rw_enSt
o,*ace(XFS_DIORD_ENTER, &(p->i_iocorh,p-sds		buf, snit, *offs6e, io+c lso;
-s	r6d = do_g6nericodirect_recH(.ile, buf, snit, offs6e);p-sEUPDATE_ATIME(.ile->f_dentry->d_inodh);p-s} e_HW {p-sdxfs_rw_enSt
o,*ace(XFS_READ_ENTER, &(p->i_iocorh,p-sds		buf, snit, *offs6e, io+c lso;
-s	r6d = g6nericofile_recH(.ile, buf, snit, offs6e);p-s}.-p-sif (!(io+c ls & IO_ISLOCKEDo)p-sdxfs_iun12B,(ip, XFS_IOLOCK_SHAREDo;
-
-	XFS_STATS_ADD(xs_recH_by  s,(e d);p-p-sif (unlikely(io+c ls & IO_INVIS)) {p-sd/*AgSnericofile_recH upd]eesdOH uaSIme but wt need top-sd - undoROHatAbecause OHisAI/O was,supposed to(be invisible.p-sd -/
-		d,* Ok, nodh *inodh = LINVFS_GET_IP(BHV_TO_VNODE(bdp));
-		inodh->i_aSIme =,(p->i_d.di_aSIme.tos6c;p-s} e_HW {p-sdxfs_ichgSIme(ip, XFS_ICHGTIME_ACC);p-s}.-p-sr6dirt , tLY-}p-p-/*
-68 T/donroutinendsfcalled to(handle0zeroiig anyrspace dn2OH ulast
-68 b12B, o++OHeAfile OHatAisdbeyond OHeAEOF.  We do OHdonsince,OHe
-68 snit isdbeiigdincre]sed winvout w   iigdanynving OorOHatAb12B,
-68( ndrwe don't want anyome to(e ad OHeAgarb ge oinOHe-disk.d- -/--STATIC ily	s	s4-+error0(positive)0*/m-xfs_zero_last_b12B,(
-Ed,* Ok, nodh	*ip,Y-Exfs_iocorh_t	*io,
-sxfs_off_t	offs6e,
-sxfs_fsnit_ sisnit,
-sxfs_fsnit_ sSnd_snit)p-{I-Exfs_fileoff_t	last_fsb;
-Exfs_m*/in_t	*mp;p-sil s	nimaps;p-sil s	zero_offs6e;--dil s	zero_lenLY-	il s	isnit_fsb_offs6e;--dil s	error0= 0;
-Exfs_bmbt_irec_ simap;
-sloff_t		loff;
-ssnit_ s	lsnitLY-Y-sASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE) != 0);Y-sASSERT(offs6e0> isnit);b-p-smp =,(o->io_m*/in;--
-	isnit_fsb_offs6e =,XFS_B_FSB_OFFSET(mp, isnit);b-sif ((snit_fsb_offs6e == 0) {p-sd/*p-sd - TH re are _trex,*a+by  s dn2OH ulast b12B, onSdisk top-sd - zero, so(e dirt.p-sd -/
-		, dirt 0;p-s} -p-slast_fsb =,XFS_B_TO_FSBT(mp, isnit);b-snimaps = 1;p-	error0= XFS_BMAPI(mp, ct a, io, last_fsb, 1, 0, ct a, 0, &(map,p-sds  &nimaps, ct a);p-sif (error)o{p-sd, dirt error;Y-s} -sASSERT(nimaps > 0);Y-s4-
-	68 If tHe b12B, undISlyiigdisnit isdjustfa holf, OHen,tHer 
-	68 don_tyving Oorzero.m-s */m-sif (imap.b
_startb12B, == HOLESTARTBLOCK)o{p-sd, dirt 0LY-	}.-s4-
-	68 ZerorOHedpart o++OHeAlast b12B, beyond OHeAEOF, and w     it
-	68 out sync.  Wt need to(dropdOHe(i12B, wHile we do OHdonso we
-	68 don't decHl2B, wHeinOHe-bufft
,cache calls back to(us.m-s */m-sXFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RDo;
-	loff0= XFS_FSB_TO_B(mp, last_fsbo;
-	lsnit = XFS_FSB_TO_B(mp, 1);b-p-szero_offs6e =,(snit_fsb_offs6e;--dzero_len = mp->m_sb.sb_b12B,snit - (snit_fsb_offs6e;--p-	error0= xfs_iozero(ip, loff0+ zero_offs6e, zero_len, Snd_snit)LY-m-sXFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RDo;
-	ASSERT(error0>= 0);Y-s, dirtyerror;Y-}p-p-/*
-68 Zeror nyronSdisk space betweeinOHeucurrSnt0EOF and OHe new,
- - largerAEOF.  T/donhandlesdOH unormal cas  o++zeroiig OHeAremaiidIS
-68(o++OHeAlast b12B, dn2OH ufile and OHe unusual cas  o++zeroiig b12B,s
-68(out beyond OHeAsnit o++OHeA.ile.  T/dons6cond cas  only happeFo
-68(winv2fixed snit extSnks and wHeinOHe-system,crashes befor  OH u nodh
-68 snit was,upd]eed but afSt
}b12B,s w re a2_HW]eed.  IfA.ill dons6t,
-68 tHenr nyrholfs dn2OH urange aren.illed and zeroBd.  IfA_ty, OH uholes
-68 arenleftAaloneAasuholes.
-68/--
-ily	s	ss4-+error0(positive)0*/m-xfs_zero_tof(
-Etnodh_t		*vp,Y-Exfs_iocorh_t	*io,
-sxfs_off_t	offs6e,ss4-+startiig I/O offs6e */m-sxfs_fsnit_ sisnit,ss/*AcurrSnt0inodh snit */m-sxfs_fsnit_ sSnd_snit)s/*Act
miFcl inodh snit */m-{
-Ed,* Ok, nodh	*ip = LINVFS_GET_IP(vp)Lp-sxfs_fileoff_t	start_zero_fsb;
-Exfs_fileoff_t	Snd_zero_fsb;
-Exfs_fileoff_t	prev_zero_fsb;
-Exfs_fileoff_t	zero_c*/in_fsb;
-Exfs_fileoff_t	last_fsb;
-Exfs_extlen_t	buf_len_fsb;
-Exfs_extlen_t	prev_zero_c*/in;--Exfs_m*/in_t	*mp;p-sil s	nimaps;p-sil s	error0= 0;
-Exfs_bmbt_irec_ simap;
-sloff_t		loff;
-ssnit_ s	lsnitLY-Y-sASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE)o;
-	ASSERT(ismr12B,ed((o->io_io12B,, MR_UPDATE)o;
-p-smp =,(o->io_m*/in;--
-	4-
-	68 Firse handle0zeroiig tHe b12B, onSwHich,isnit resides.m-s * Wt only zero adpart o++OHatAb12B,nso it,is handleduspeciclly.m-s */m-serror0= xfs_zero_last_b12B,(ip, io, offs6e, isnit, Snd_snit)LY-Eif (error)o{p-sdASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE)o;
-		ASSERT(ismr12B,ed((o->io_io12B,, MR_UPDATE)o;
-sd, dirt error;Y-s} -
-	4-
-	68 Calcula   OH urange betweeinOHeunew snit and OHe old
-	68 wH re}b12B,s needing Oorbe0zeroBd mayfexist.  To(gSt tHe
-	68 bl2B, wHer  OH ulast byte dn2OH ufile currSntlyrresides,
-	68 wt need to(sub,*act(ome fverSOHe-snit and O* nc]ee back
-	68  o(a b12B, boundary.  Wt sub,*act(1 dn2cas  OHe-snit is
-	68 exactlyronSa b12B, boundary.m-s */m-slast_fsb =,isnit ? XFS_B_TO_FSBT(mp, isnit(- 1) : (xfs_fileoff_t)-1;p-	start_zero_fsb =,XFS_B_TO_FSB(mp, (xfs_ufsnit_ )isnit);b-sSnd_zero_fsb =,XFS_B_TO_FSBT(mp, offs6e - 1);b-	ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb)LY-Eif (last_fsb == Snd_zero_fsb) {p-sd/*p-sd - TH  snit was,only incremSnted onAitselast b12B,.p-sd - Wt took2care o++OHatAabove, so(justfe dirt.p-sd -/
-		, dirt 0;p-s} -p-sASSERT(start_zero_fsb <= Snd_zero_fsb);p-sprev_zero_fsb =,ct aFILEOFF;p-sprev_zero_c*/in = 0;
-EwHile (start_zero_fsb <= Snd_zero_fsb) {p-sdnimaps = 1;p-		zero_c*/in_fsb = Snd_zero_fsbA- start_zero_fsb + 1;p-		error0= XFS_BMAPI(mp, ct a, io, start_zero_fsb, zero_c*/in_fsb,p-sds	  0, ct a, 0, &(map, &nimaps, ct a);p-s	if (error)o{p-sdsASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE)o;
-			ASSERT(ismr12B,ed((o->io_io12B,, MR_UPDATE)o;
-sdd, dirt error;Y-ss}p-sdASSERT(nimaps > 0);Y-p-s	if (imap.b
_statta== XFS_EXT_UNWRITTEN ||p-sd    imap.b
_startb12B, == HOLESTARTBLOCK)o{p-sdd/*p-sd	68 T/donloopdhandlesdiniticliziigdpages OHatAwer 
-	d	68 particlly0initiclize }byrOH ucode below0OHdo
-	d	68 loop. It basicclly0zeroBsrOHedpart o++OHeApage
-	d	68 OHatAsitseonSa holfRand s6es+OHeApageAasuP_HOLE
-	d	68 and calls remapffif it is a mappe }.ile.
-	d	68/
-		sprev_zero_fsb =,ct aFILEOFF;p-s	sprev_zero_c*/in = 0;
-E		start_zero_fsb =,imap.b
_startoff0+p-sds		,imap.b
_b12B,c*/in;--E	sASSERT(start_zero_fsb <= (Snd_zero_fsbA+ 1)o;
-sddcontiiue;Y-ss}p-p-sd/*p-sd - TH re are b12B,s dn2OH urange r6questBd.d-		68 ZerorOHem a siigle w     atAa SIme.  Wt actucllyd-		68 don't zerorOHedSntireurange r6dirted dfAit,is
-d	68 OoorbigRand s mplynloopdaround to(gSt tHe-res,.p-sd - THatAisd_ty(OHe-mostfefficiSnt0yving Oordo, but itp-sd - donsimple and OHdsfp nv2deGuld _ty(bt exercise }ofStt.p-sd -/
-		buf_len_fsb = XFS_FILBLKS_MIN(imap.b
_b12B,c*/in,p-sds		      mp->m_w    io_b12B,s << 8o;
-sd/*p-sd - DropdOHe(inodh 12B, wHile we'rfRdoiig tHe I/O.p-sd - Wt'll0still igafROHe(io12B, to(protect us.m-sd -/
-		XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RDo;
-
-		loff0= XFS_FSB_TO_B(mp, start_zero_fsb)LY-E	lsnit = XFS_FSB_TO_B(mp, buf_len_fsbo;
-p-s	error0= xfs_iozero(ip, loff, lsnit, Snd_snit)LY-p-s	if (error)o{p-sdsgo o(out_12B,LY-Ed}b-p-ssprev_zero_fsb =,start_zero_fsb;
-Esprev_zero_c*/in = buf_len_fsb;
-E	start_zero_fsb =,imap.b
_startoff0+ buf_len_fsb;
-E	ASSERT(start_zero_fsb <= (Snd_zero_fsbA+ 1)o;
-
-		XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RDo;
-	}.-p-s, dirt 0;p-p-out_12B,:Y-m-sXFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RDo;
-	ASSERT(error0>= 0);Y-s, dirtyerror;Y-}p-p-ssnit_ s	ss4-+by  s w   tet, or0(-) error0*/m-xfs_w    (
-Ebhv_desc_t      *bdp,
-sd,* Ok,.iles*.ile,
-scoist char	*buf,
-ssnit_ s	snit,
-sloff_t		*offs6e,
-sil s	io+c ls,
-scredo,          *credp)p-{Y-Exfs_ nodhot	*xip;
-Exfs_m*/in_t	*mp;p-Essnit_ s	r6e;--dil s	error0= 0;
-Exfs_fsnit_      isnit, new_snit;
-Exfs_fsnit_ 	t, limit;
-Exfs_iocorh_t    *io;
-Etnodh_t		*vpLY-	il s	io12B,LY-Eil s	evSnksein = 0;
-Evrw12B,o,	12B,Oype;
-
-	XFS_STATS_INC(xs_w    _calls);p-p-svp =,BHV_TO_VNODE(bdp);
-Exip =,XFS_BHVTOI(bdp);p-Y-Eif (snita== 0)
-		, dirt 0;p-Y-Eio = &x(p->i_iocorh;p-smp =,(o->io_m*/in;--
-	xfs_cheB,ofvezen(mp, bdp, XFS_FREEZE_WRITE);p-Y-Eif (XFS_FORCED_SHUTDOWN(x(p->i_m*/in))o{p-sd, dirt -EIO;
-	}.-p-sif (unlikely(io+c ls & IO_ISDIRECT)) {p-sdif (((__psil _t)buf & BBMASK) ||p-sd    (*offs6e0& mp->m_b12B,read) ||p-sd    (snitaa& mp->m_b12B,read)) {p-sdd, dirt XFS_ERROR(-EINVAL);p-sE}
-6	io12B, =,XFS_IOLOCK_SHAREDLY-E	l2B,Oype = VRWLOCK_WRITE_DIRECT;p-s} e_HW {p-sdif (io->io_+c ls & XFS_IOCORE_RT)p-sdd, dirt XFS_ERROR(-EINVAL);p-sEio12B, =,XFS_IOLOCK_EXCLLY-E	l2B,Oype = VRWLOCK_WRITE;
-	}.-p-sif (io+c ls & IO_ISLOCKEDop-sEio12B, =,0;--
-	xfs_i12B,(xip, XFS_ILOCK_EXCL|io12B,);p-Y-Eisnit = x(p->i_d.di_snit;
-slimit =,XFS_MAXIOFFSET(mp);p-Y-Eif (.ile->f_+c ls & O_APPENDop-sE*offs6e =,(snit;
---d,art:p-sn = limit -A*offs6e;--dif (n <= 0) {p-sdxfs_iun12B,(xip, XFS_ILOCK_EXCL|io12B,);p-sd, dirt -EFBIGLY-	}.-sif (n < snit)p-sdsnit = n;p-p-snew_snita=A*offs6eA+ snit;
-sif (new_snita> isnit) {p-sd(o->io_new_snita= new_snit;
-E}.-p-sif ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&m-s    !(io+c ls & IO_INVIS) && !evSnksein)) {p-sdloff_t		sgafdsnita=A*offs6e;p-sEiin dm.c ls =,FILP_DELAY_FLAG(.ile) | DM_SEM_FLAG_RD(io+c lso;
-p-s	xfs_iun12B,(xip, XFS_ILOCK_EXCL);p-		error0= XFS_SEND_DATA(x(p->i_m*/in, DM_EVENT_WRITE, vp,p-sds	      *offs6e, snit,p-sds	      dm.c ls, &12B,Oype);
-		if (error)o{p-sdsif (io12B,) xfs_iun12B,(xip, io12B,);p-sd	r6dirt -error;Y-sE}
-6	xfs_i12B,(xip, XFS_ILOCK_EXCL);p-		evSnksein = 1;p-p-sd/*p-sd - TH (io12B, was,dropped and reaquired dn2XFS_SEND_DATAp-sd - so we igafROo(e cheB, OHe-snit wHeinappeFding.p-sd - Wt will only "go o(d,art;" once, since,igaiig sSnt0yvep-sd - evSnk prevSnks anoOH rncall  o(XFS_SEND_DATA,SwHich,isp-sd - wHat a2_Hws OHe-snit to(change in,OH ufirse place.
-sd -/
-		if ((.ile->f_+c ls & O_APPENDo &&m-s	    sgafdsnita!= x(p->i_d.di_snit)o{p-sds*offs6e =,(snit = x(p->i_d.di_snit;
-sdsgo o(d,art;Y-sE}
-6} -
-	4-
-	68 If tHe offs6e0is beyond OHeAsnit o++OHeA.ile, we igafRa(couple
-	68 o++OHdngs Oordo. Firse,n(+,tHer  is alrecHynspace a2_HW]eed
-	68 wt need to(eiOH rncre]egrholfs or0zerorOHeddisk or0...m-s *
-	68 If tHer  is aApageAwHer  OH uprevious+snit lands, wt need
-	68  o(zerorit out up  o(OH unew snit.m-s */m-
-sif (!(io+c ls & IO_ISDIRECT) && (*offs6e0>,(snit && isnit))o{p-sderror0= xfs_zero_tof(BHV_TO_VNODE(bdp),Aio, *offs6e,
-ss	isnit,A*offs6eA+ snit);
-		if (error)o{p-sdsxfs_iun12B,(xip, XFS_ILOCK_EXCL|io12B,);p-sds, dirt(-error);p-sE}
-6}b-	xfs_iun12B,(xip, XFS_ILOCK_EXCL);p-
-	4-
-	68 If we'rfRw   iigdOHeAfile OHeinmake surfROo clear tHe
-	68 s6euid and s6egid bitseif,OHe-processAisd_ty(beiigdrun
-	68 by root.  T/donkeepsepIopleufverSmodifyiig sSeuid and
-	68 s6egid binaries.m-s */m-
-sif (((x(p->i_d.di_rodh & S_ISUID) ||p-s    ((x(p->i_d.di_rodh & (S_ISGID | S_IXGRP))o==p-sE(S_ISGID | S_IXGRP))) &&m-s     !capable(CAP_FSETID))o{p-sderror0= xfs_w    _clear_sSeuid(x(p);
-		if (error)o{p-sdsxfs_iun12B,(xip, io12B,);p-sd	r6dirt -error;Y-sE}
-6}p-p-
-sif ((ssnit_ )+snit < 0) {p-sdr6d = -EINVAL;Y-sEgo o(error;Y-s} -
-	if (!access_ok(VERIFY_READ, buf, snit)) {p-sdr6d = -EINVAL;Y-sEgo o(error;Y-s} -
-r6dry:p-sif (unlikely(io+c ls & IO_ISDIRECT)) {p-sdxfs_inval_cachedop ges(vp, io, *offs6e, 1, 1);b-sdxfs_rw_enSt
o,*ace(XFS_DIOWR_ENTER,p-sds		io, buf, snit, *offs6e, io+c lso;
-s	r6d = do_g6nericodirect_w    (.ile, buf, snit, offs6e);p-s} e_HW {p-sdxfs_rw_enSt
o,*ace(XFS_WRITE_ENTER,p-sds		io, buf, snit, *offs6e, io+c lso;
-s	r6d = do_g6nericofile_w    (.ile, buf, snit, offs6e);p-s}p-p-sif (unlikely(io+c ls & IO_INVIS)) {p-sd/*AgSnericofile_w     upd]eesdOH umSIme/cSIme but wt need
-d	68 Oo undoROHatAbecause OHisAI/O was,supposed to(be
-d	68 invisible.p-sd -/
-		d,* Ok, nodh	*inodh = LINVFS_GET_IP(vp);
-		inodh->i_mSIme =,x(p->i_d.di_rSIme.tos6c;p-s	inodh->i_cSIme =,x(p->i_d.di_cSIme.tos6c;p-s} e_HW {p-sdxfs_ichgSIme(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);p-s}p-p-sif ((r6e == -ENOSPC)+&&m-s    DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&m-s    !(io+c ls & IO_INVIS)) {p-p-sdxfs_rwun12B,(bdp, 12B,Oype);
-		error0= XFS_SEND_NAMESP(x(p->i_m*/in, DM_EVENT_NOSPACE, vp,p-sds	DM_RIGHT_Nt a, vp, DM_RIGHT_Nt a, Nt a, Nt a,p-sds	0, 0, 0); 4- Delay fc l inStnSISFclly  unusBd */m-s	if (error)p-sd	r6dirt -error;Y-sExfs_rw12B,(bdp, 12B,Oype);
-		*offs6e =,x(p->i_d.di_snit;
-sdgo o(r6dry;p-s}p-p-error:p-sif (r6e <= 0) {p-sdif (io12B,)p-sdsxfs_rwun12B,(bdp, 12B,Oype);
-		r6dirt , tLY-s}p-p-sXFS_STATS_ADD(xs_w    _by  s,(e d);p-p-sif (*offs6e0>,x(p->i_d.di_snit)o{p-sdxfs_i12B,(xip, XFS_ILOCK_EXCL);p-		if (*offs6e0>,x(p->i_d.di_snit)o{p-sd	d,* Ok, nodh	*inodh = LINVFS_GET_IP(vp);
-p-sdsx(p->i_d.di_snita=A*offs6e;p-sEsi_snitow    (inodh, *offs6e);p-sd	x(p->i_upd]ee_corh = 1;p-			x(p->i_upd]ee_snita=A1;p-			mark_ nodhodirty_sync(inodh);p-sE}
-6	xfs_iun12B,(xip, XFS_ILOCK_EXCL);p-	}.-p-s4- Handle0various+SYNC-Oype w    s */m-sif ((.ile->f_+c ls & O_SYNC) || IS_SYNC(.ile->f_dentry->d_inodh)) {p-p-sd/*p-sd - If we'rfRtre]eiigdOHdonas,O_DSYNC( ndrwe igafR_ty(upd]eed yvep-sd - snit, forc  OH ulog.p-sd -/
-p-		if (!(mp->m_+c ls & XFS_MOUNT_OSYNCISOSYNC)p-sds&& !(x(p->i_upd]ee_snit))o{p-sdd/*p-sd	68 If( n a2_HW]eISF ,*ansacSISF(occurrSdp-sd	68 winvout extSndiigdOHe(snit, OHeinwe igafROo(forc p-sd	68 OH ulog up  He-prop r0pointr o(ensurfROHatAyvep-sd	68( 2_HW]eISF isepISmanent.  We can't c*/in onp-sd	68 OH ufact(OHatAbufft
od w    s 12B, out direct I/Op-sd	68 w    s -rOHeddirect I/O w     cGuld igafRextSndSdp-sd	68 OHeAsnit non,*ansacSISFclly, OHeinhom(she }befor 
-sd	68 we(d,artBd.  xfs_w    _file will OHdnkROHatAyveAfile
-sd	68 didn't grow but OHe upd]eefisn't safe(un1essAyvep-sd	68(snit change is 12ggBd.d-		s *
-	d	68(Forc  OH ulogeif,we'v  comm  tedAa(,*ansacSISFp-sd	68( gaiist OHe(inodh or0if someome e_HW has and
-	d	68 OHeAcomm  (e cord igsn't gome to(disk (e.g.
-	d	68 OHeAinodh isepintod).  T/donguarantees OHatp-sd	68( 2_ changesuaffeceiigdOHe(inodh are pISmanent
-sd	68 wHeinwe e dirt.p-sdd -/
-p-		Exfs_ nodholog_item_t *iip;
-E	Exfs_lsno, 1sn;
-p-sdsiip =,x(p->i_itemp;p-sEsif (iip && i(p->ili_last_1sn)o{p-sds	1sn =,((p->ili_last_1sn;p-sEs	xfs_log_forc (mp, lsn,p-sds			XFS_LOG_FORCE | XFS_LOG_SYNC);p-sEs} e_HW if (xfs_ pinc*/in(x(p) > 0)o{p-sds	xfs_log_forc (mp, (xfs_lsno,)0,p-sds			XFS_LOG_FORCE | XFS_LOG_SYNC);p-sEs}
-p-sd} e_HW {p-sd	xfs_,*ans_t	*tp;
-p-sds/*p-sd	68 O_SYNC or0O_DSYNC(_winv_ a size upd]eefare handledp-sd	68 OHeAsamg way.d-		s *
-	d	68(If tHe w     was,synchronous+OHeinwe need to(makep-sd	68(surfROHatAyve(inodh modifiW]eISF ,Ime isepISmanent.p-sd	68(Wt'll0igafRupd]eed yve ,Imed,ampAabove, so(her 
-sd	68 we(use a,synchronous+O*ansacSISF(to(logeyve(inodh.p-sd	68(It'sd_ty(fase,nbut it'sd_ecessary.m-s	s *
-	d	68(If tHis aAdsync w     and OHeAsnit got changedp-sd	68 non-,*ansacSISFclly, OHeinwt need to(ensurfROHatp-sd	68 OHeAsnit change g6es+12ggBd in,a,synchronousp-sd	68 O*ansacSISF.p-sdd -/
-p-		Etp0= xfs_,*ans_ 2_HW(mp, XFS_TRANS_WRITE_SYNC);p-sEsif ((error0= xfs_,*ans_res6rvB(tp, 0,p-sds			      XFS_SWRITE_LOG_RES(mp),p-sds			      0, 0, 0)))o{p-sdds4- T*ansacSISF(res6rvB failBd */m-s	d	xfs_,*ans_cancel(tp, 0);p-sEs} e_HW {p-sdds4- T*ansacSISF(res6rvB successful}*/m-s	d	xfs_i12B,(xip, XFS_ILOCK_EXCL);p-		d	xfs_,*ans_ijoin(tp, xip, XFS_ILOCK_EXCL);p-		d	xfs_,*ans_ihold(tp, xip);p-		d	xfs_,*ans_log_inodh(tp, xip, XFS_ILOG_CORE);p-		d	xfs_,*ans_set_sync(tp);p-		d	error0= xfs_,*ans_comm  (tp, 0, (xfs_lsno,)0);p-		d	xfs_iun12B,(xip, XFS_ILOCK_EXCL);p-		E}
-6	}
-6} 4- (io+c ls & O_SYNC) -/
-p-	4-
-	68 If wefare comiigdfverS n nfsd OHe ad OHeF ilsertAil o(OH 
-	68 reft
ence,cache.m-s */m-
-sif (!d,*cmp(currSnt->comm, "nfsd"o)p-sdxfs_refcache_ilsert(x(p);
-p-s4- Dropd12B, tHis way -rOHedold refcache release doninSH re */m-sif (io12B,)p-sdxfs_rwun12B,(bdp, 12B,Oype);
-
-s, dirt(e d);p-}p-p-/*
-68 A2_ixfs metad]ea bufft
s except(logestattamachome bufft
s
-68 gSt tHis attached-as+OHeir b_bdd,*at c 2_back duncSISF.
-68 T/dondonso OHatAweAcan,W]ech a bufft

-68 afSt
}premakurelyrunpintiigditROo(forciblyrshutdownAyveAfilesystem.
-68/--ily
-xfs_bdd,*at_cb(d,* Ok,xfs_buf *bp)p-{I-Exfs_m*/in_t	*mp;p-
-smp =,XFS_BUF_FSPRIVATE3(bp, xfs_m*/in_t *)LY-Eif (!XFS_FORCED_SHUTDOWN(mp))o{p-sdp gebuf_ior6quest(bp);
-		r6dirt 0;p-s} e_HW {p-sdxfs_buf,*ace("XFS__BDSTRAT IOERROR",nbpo;
-sd/*p-sd - Metad]ea w     OHat didn't get+12ggBd but
-d	68 w   tSn delayed anyway. THeseSaren't associ]eed
-		68 winvAa(,*ansacSISF, and can(be ignor6d.
-sd -/
-		if (XFS_BUF_IODONE_FUNC(bpoe==,ct a &&m-s	    (XFS_BUF_ISREAD(bpo)a== 0)
-			, dirty(xfs_bioerror_re_HW(bpo);
-		e_HWp-			, dirty(xfs_bioerror(bpo);
-	}Y-}p-p-
-ily
-xfs_bmap(bhv_desc_t	*bdp,
-sxfs_off_t	offs6e,
-sssnit_ s	c*/in,p-sil s	+c ls,
-sxfs_ omap_t	*iomapp,p-sil s	*niomaps)p-{I-Exfs_ nodhot	*ip =,XFS_BHVTOI(bdp);p-sxfs_iocorh_t	*io = &(p->i_iocorh;p-
-	ASSERT(((p->i_d.di_rodh & S_IFMT)a== S_IFREG);b-	ASSERT((((p->i_d.di_+c ls & XFS_DIFLAG_REALTIME) != 0)o==p-s       (((p->i_iocorh.io_+c ls & XFS_IOCORE_RT) != 0)o;Y-m-s, dirtyxfs_ omap(io, offs6e, c*/in, .c ls, iomapp, niomaps);p-}p-p-/*
-68 Wrapp r0around bdd,*at so OHatAweAcan,stopdd]ea
-68 d/erSgoing Oordisk dn2cas  wefare shuttiig downAyveAfilesystem.
-68 Typicclly0user+d]ea goBsrOHru OHdsfp nv;(ome o++OHeAexceptISFo
-68(is OHe-sup rb12B,.p-68/--ily
-xfsbdd,*at(
-Ed,* Ok,xfs_m*/in	*mp,
-Ed,* Ok,xfs_buf		*bp)p-{I-EASSERT(mp);p-Eif (!XFS_FORCED_SHUTDOWN(mp))o{p-sd4- Grio,redirectISF(wGuld go(her 
-sd68(if (XFS_BUF_IS_GRIO(bpo)a{p-sd -/
-p-		p gebuf_ior6quest(bp);
-		r6dirt 0;p-s}--
-	xfs_buf,*ace("XFSBDSTRAT IOERROR",nbpo;
-s, dirty(xfs_bioerror_re_HW(bpo);
-}p-p-/*
-68 If tHe undISlyiigd(d]ea/12g/rt) device is recHonly, tHer  are some
-68(operatISFs OHatAcan_ty(proceBd.d- -/--ily
-xfs_dev_is_recH_only(Y-Exfs_m*/in_t		*mp,
-Echar			*messagt)p-{I-Eif (xfs_recHonly_buf,arg(mp->m_ddev_targp) ||p-s    xfs_recHonly_buf,arg(mp->m_12gdev_targp) ||p-s    (mp->m_rtdev_targp && xfs_recHonly_buf,arg(mp->m_rtdev_targp)))o{p-sdcmn_err(CE_NOTE,p-sds"XFS: %s r6quired SF(read-only device.",nmessagt);p-sdcmn_err(CE_NOTE,p-sds"XFS: w     access unavailable,Acan_ty(proceBd.");
-		r6dirt EROFSLY-	}.-sr6dirt 0;Y-}pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsolrw.h linux-2.4.27-rc4/fs/xfs/linux/xfsolrw.h
--- linux-2.4.26/fs/xfs/linux/xfsolrw.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsolrw.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,111 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifndef __XFS_LRW_H__--# /home __XFS_LRW_H__----d,* Ok,tnodh;--d,* Ok,bhv_desc;--d,* Ok,xfs_m*/in;--d,* Ok,xfs_iocorh;p-d,* Ok,xfs_inodh;--d,* Ok,xfs_bmbt_irec;--d,* Ok,page_buf_s;--d,* Ok,xfs_iomap;
-
-#if  /home (XFS_RW_TRACE)p-4-
-68 D/homesufor-OH ucraceemechanismoninSxfsolrw.c.
- -/--# /home	XFS_RW_KTRACE_SIZE	128
-
-# /home	XFS_READ_ENTER		1
-# /home	XFS_WRITE_ENTER		2
-# /home XFS_IOMAP_READ_ENTER	3
-# /home	XFS_IOMAP_WRITE_ENTER	4
-# /home	XFS_IOMAP_READ_MAP	5
-# /home	XFS_IOMAP_WRITE_MAP	6
-# /home	XFS_IOMAP_WRITE_NOSPACE	7
-# /home	XFS_ITRUNC_START	8
-# /home	XFS_ITRUNC_FINISH1	9
-# /home	XFS_ITRUNC_FINISH2	10
-# /home	XFS_CTRUNC1		11
-# /home	XFS_CTRUNC2		12
-# /home	XFS_CTRUNC3		13
-# /home	XFS_CTRUNC4		14--# /home	XFS_CTRUNC5		15--# /home	XFS_CTRUNC6		16
-# /home	XFS_BUNMAPI		17
-# /home	XFS_INVAL_CACHED	18--# /home	XFS_DIORD_ENTER		19--# /home	XFS_DIOWR_ENTER		20
-# /home	XFS_SENDFILE_ENTER	21
-# /home	XFS_WRITEPAGE_ENTER	22
-# /home	XFS_RELEASEPAGE_ENTER	23
-# /home	XFS_IOMAP_ALLOC_ENTER	24
-# /home	XFS_IOMAP_ALLOC_MAP	25
-# /home	XFS_IOMAP_UNWRITTEN	26
-extSrt tic Axfs_rw_enSt
o,*ace(iin, d,* Ok,xfs_iocorh *,p-sdscoist char *, snit_ , loff_ , iino;Y-extSrt tic Axfs_inval_cachedo,*ace(d,* Ok,xfs_iocorh *,p-sdsxfs_off_t, xfs_off_t, xfs_off_t, xfs_off_to;Y-#e_HWp-# /home xfs_rw_enSt
o,*ace(tag, io, buf, snit, offs6e, io+c lsop-# /home xfs_inval_cachedo,*ace(io, offs6e, len, firse, last)p-#Snd(+
-
-4-
-68 Maximum c*/in of bmaps usBd by r ad and w     p nvs.
- -/--# /home	XFS_MAX_RW_NBMAPS	4
-Y-extSrt intrxfs_bmap(d,* Ok,bhv_desc *, xfs_off_t, ssnit_ , iin,p-sdsd,* Ok,xfs_iomap *, intr*o;Y-extSrt intrxfsbdd,*at(d,* Ok,xfs_m*/in *, s,* Ok,page_buf_sr*o;Y-extSrt intrxfs_bdd,*at_cb(d,* Ok,page_buf_sr*o;Y-Y-extSrt intrxfs_zero_tof(d,* Ok,tnodh *, s,* Ok,xfs_iocorh *, xfs_off_t,p-		d	xfs_fsnit_ , xfs_fsnit_ o;Y-extSrt tic Axfs_inval_cachedop ges(d,* Ok,tnodh	*, s,* Ok,xfs_iocorh *,p-		d	xfs_off_ , iin, iino;Y-extSrt ssnit_  xfs_recH(d,* Ok,bhv_desc *, d,* Ok,.ile *, char	*,p-		d	snit_ , loff_  *, int, d,* Ok,credr*o;Y-extSrt ssnit_  xfs_w    (d,* Ok,bhv_desc *, d,* Ok,.ile *, coist char *,p-		d	snit_ , loff_  *, int, d,* Ok,credr*o;Y-Y-extSrt intrxfs_dev_is_recH_only(d,* Ok,xfs_m*/in *, char *o;Y-Y-# /home XFS_FSB_TO_DB_IO(io,fsb) \p-		((((o)->io_+c ls & XFS_IOCORE_RT) ? \p-		 XFS_FSB_TO_BB(((o)->io_m*/in, (fsb)) : \p-		 XFS_FSB_TO_DADDR(((o)->io_m*/in, (fsb)))
-
-#Snd(+	4- __XFS_LRW_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsostats.c linux-2.4.27-rc4/fs/xfs/linux/xfsostats.c
--- linux-2.4.26/fs/xfs/linux/xfsostats.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsostats.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,117 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-#include <linux/proc_fs.h>----d,* Ok,xfsstats,xfsstats;Y-Y-STATIC ily
-xfs_recH_xfsstats(
-schar		*buff r,
-schar		**d,art,
-soff_t		offs6e,
-sil s	c*/in,p-sil s	*tof,p-stic s	*d]ea)p-{I-Eil s	i, j, len;
-Ed,aSIc s,* Ok,xstats_entryo{p-sdchar	*desc;--sEiinsSndpoint;p-s} xstats[] =o{p-sd{ "extSnk_ 2_HW",	XFSSTAT_END_EXTENT_ALLOC	},p-sd{ "abt",		XFSSTAT_END_ALLOC_BTREE		},p-sd{ "blk_map",		XFSSTAT_END_BLOCK_MAPPING	},p-sd{ "bmbt",		XFSSTAT_END_BLOCK_MAP_BTREE	},p-sd{ "dir",		XFSSTAT_END_DIRECTORY_OPS	},p-sd{ ",*ans",		XFSSTAT_END_TRANSACTIONS	},p-sd{ "ig",			XFSSTAT_END_INODE_OPS		},p-sd{ "log",		XFSSTAT_END_LOG_OPS		},p-sd{ "push_ail",		XFSSTAT_END_TAIL_PUSHING	},p-sd{ "xd,*at",		XFSSTAT_END_WRITE_CONVERT	},p-sd{ "rw",			XFSSTAT_END_READ_WRITE_OPS	},p-sd{ "attr",		XFSSTAT_END_ATTRIBUTE_OPS	},p-sd{ "iclusct
",		XFSSTAT_END_INODE_CLUSTER	},p-sd{ "tnodhs",		XFSSTAT_END_VNODE_OPS		},p-sd{ "buf",		XFSSTAT_END_BUF			},p-s};Y-m-sfor-(i=j=len = 0;+( < snitof(xstats)/snitof(s,* Ok,xstats_entry);+(++) {p-sdlen += spriitf(bufft
,+ len, xstats[i].desco;
-sd/* intornloopddoBsreach group -/
-		wHile (j < xstats[i].Sndpoint)o{p-sddlen += spriitf(bufft
,+ len, " %u",p-sds		*(((__u32*)&xfsstats),+ j)o;
-sddj++;p-sE}
-6	bufft
[len++] =o'\n'LY-	}.-s4-+ex,*a+precisISF c*/int
s */m-slen += spriitf(bufft
,+ len, "xpc %Lu %Lu %Lu\n",p-sdsxfsstats.xs_xd,*at_by  s,p-sdsxfsstats.xs_w    _by  s,p-sdsxfsstats.xs_recH_by  so;
-	len += spriitf(bufft
,+ len, "debug %u\n",p-#if  /home (XFSDEBUG)
-		1o;Y-#e_HWp-		0o;Y-#end(+
-
-	if (offs6e0>= len)o{p-sd*d,art = bufft
;
-		*tofa=A1;p-		, dirt 0LY-	}.-s*d,art = bufft
 +Aoffs6e;p-Eif ((len -= offs6e) > c*/ino -s	, dirt c*/in;--E*tofa=A1;p-.-sr6dirt len;
-}
-
-tic 
-xfs_init_procfs(tic )p-{I-Eif (!proc_mkdir("fs/xfs", 0)) -s	, dirt;--Ecre]eg_proc_recH_entry("fs/xfs/stat", 0, 0, xfs_recH_xfsstats, ct a);p-}
-
-tic 
-xfs_cleanup_procfs(tic )p-{I-Eremovg_proc_entry("fs/xfs/stat", ct a);p-sremovg_proc_entry("fs/xfs", ct a);p-}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsostats.h linux-2.4.27-rc4/fs/xfs/linux/xfsostats.h
--- linux-2.4.26/fs/xfs/linux/xfsostats.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsostats.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,160 +0,0 @@
-4-
-68 Copyright (c) 2000 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifndef __XFS_STATS_H__--# /home __XFS_STATS_H__--
-
-#if  /home (CONFIG_PROC_FS) && ! /home (XFS_STATS_OFF)
-
-4-
-68 XFS globalestatid,ics
- -/--d,* Ok,xfsstats,{I-#  /home XFSSTAT_END_EXTENT_ALLOC	4p-s__uiit32_t		xs_ 2_HWx;p-s__uiit32_t		xs_ 2_HWb;p-s__uiit32_t		xs_d/hox;p-s__uiit32_t		xs_d/hob;p-#  /home XFSSTAT_END_ALLOC_BTREE	(XFSSTAT_END_EXTENT_ALLOC+4)p-s__uiit32_t		xs_ bt_12okup;p-s__uiit32_t		xs_ bt_comparh;p-s__uiit32_t		xs_ bt_insrec;--s__uiit32_t		xs_ bt_delrec;--#  /home XFSSTAT_END_BLOCK_MAPPING	(XFSSTAT_END_ALLOC_BTREE+7)p-s__uiit32_t		xs_blk_mapr;--s__uiit32_t		xs_blk_mapw;--s__uiit32_t		xs_blk_unmap;--s__uiit32_t		xs_ dH_exlist;--s__uiit32_t		xs_del_exlist;--s__uiit32_t		xs_12ok_exlist;--s__uiit32_t		xs_cmp_exlist;--#  /home XFSSTAT_END_BLOCK_MAP_BTREE	(XFSSTAT_END_BLOCK_MAPPING+4)p-s__uiit32_t		xs_bmbt_12okup;p-s__uiit32_t		xs_bmbt_comparh;p-s__uiit32_t		xs_bmbt_insrec;--s__uiit32_t		xs_bmbt_delrec;--#  /home XFSSTAT_END_DIRECTORY_OPS	(XFSSTAT_END_BLOCK_MAP_BTREE+4)p-s__uiit32_t		xs_dir_12okup;p-s__uiit32_t		xs_dir_cre]eg;p-s__uiit32_t		xs_dir_removg;p-s__uiit32_t		xs_dir_getdents;--#  /home XFSSTAT_END_TRANSACTIONS	(XFSSTAT_END_DIRECTORY_OPS+3)p-s__uiit32_t		xs_,*ans_sync;--s__uiit32_t		xs_,*ans_ sync;--s__uiit32_t		xs_,*ans_empty;--#  /home XFSSTAT_END_INODE_OPS		(XFSSTAT_END_TRANSACTIONS+7)p-s__uiit32_t		xs_ig_attempts;--s__uiit32_t		xs_ig_found;--s__uiit32_t		xs_ig_frecycle;--s__uiit32_t		xs_ig_missed;--s__uiit32_t		xs_ig_dup;p-s__uiit32_t		xs_ig_reclaims;--s__uiit32_t		xs_ig_attrchg;--#  /home XFSSTAT_END_LOG_OPS		(XFSSTAT_END_INODE_OPS+5)p-s__uiit32_t		xs_log_w    s;--s__uiit32_t		xs_12g_b12B,s;--s__uiit32_t		xs_12g_noic12gs;--s__uiit32_t		xs_12g_forc ;--s__uiit32_t		xs_12g_forc _sleep;--#  /home XFSSTAT_END_TAIL_PUSHING	(XFSSTAT_END_LOG_OPS+10)p-s__uiit32_t		xs_,*y_12gspace;--s__uiit32_t		xs_sleep_12gspace;--s__uiit32_t		xs_push_ail;--s__uiit32_t		xs_push_ail_success;--s__uiit32_t		xs_push_ail_pushbuf;--s__uiit32_t		xs_push_ail_pintod;--s__uiit32_t		xs_push_ail_12B,ed;--s__uiit32_t		xs_push_ail_flushiig;--s__uiit32_t		xs_push_ail_res,arts;--s__uiit32_t		xs_push_ail_flush;--#  /home XFSSTAT_END_WRITE_CONVERT	(XFSSTAT_END_TAIL_PUSHING+2)p-s__uiit32_t		xs_xd,*at_quick;--s__uiit32_t		xs_xd,*at_split;--#  /home XFSSTAT_END_READ_WRITE_OPS	(XFSSTAT_END_WRITE_CONVERT+2)p-s__uiit32_t		xs_w    _calls;--s__uiit32_t		xs_recH_calls;p-#  /home XFSSTAT_END_ATTRIBUTE_OPS	(XFSSTAT_END_READ_WRITE_OPS+4)p-s__uiit32_t		xs_ ttr_get;--s__uiit32_t		xs_ ttr_set;--s__uiit32_t		xs_ ttr_removg;p-s__uiit32_t		xs_ ttr_list;--#  /home XFSSTAT_END_INODE_CLUSTER	(XFSSTAT_END_ATTRIBUTE_OPS+3)p-s__uiit32_t		xs_iflush_c*/in;--E__uiit32_t		xs_iclusct
_flushcin;--E__uiit32_t		xs_iclusct
_flushinodh;--#  /home XFSSTAT_END_VNODE_OPS		(XFSSTAT_END_INODE_CLUSTER+8)p-s__uiit32_t		vn_acSIvg;s4-+#,tnodhsd_ty(SF d/ho(lists */m-s__uiit32_t		vn_a2_HW;s4-+#,,Imed vn_a2_HWfcalled */m-s__uiit32_t		vn_get;	s4-+#,,Imed vn_get+called */m-s__uiit32_t		vn_hold;s4-+#,,Imed vn_hold+called */m-s__uiit32_t		vn_rele;s4-+#,,Imed vn_rele+called */m-s__uiit32_t		vn_reclaim;s4-+#,,Imed vn_reclaim called */m-s__uiit32_t		vn_removg;s4-+#,,Imed vn_removg called */m-s__uiit32_t		vn_d/ho;s4-+#,,Imed vn_d/ho(called */m-# /home XFSSTAT_END_BUF			(XFSSTAT_END_VNODE_OPS+9)p-s__uiit32_t		pb_get;--s__uiit32_t		pb_cre]eg;p-s__uiit32_t		pb_get_12B,ed;--s__uiit32_t		pb_get_12B,ed_wa   d;--s__uiit32_t		pb_busy_12B,ed;--s__uiit32_t		pb_miss_12B,ed;--s__uiit32_t		pb_page_r6dri s;--s__uiit32_t		pb_page_found;--s__uiit32_t		pb_get_recH;
-4- Ex,*a+precisISF c*/int
s */m-s__uiit64_t		xs_xd,*at_by  s;m-s__uiit64_t		xs_w    _by  s;m-s__uiit64_t		xs_recH_by  s;p-};Y-Y-extSrt d,* Ok,xfsstats,xfsstats;Y-Y-#  /home XFS_STATS_INC(c*/ino		(,xfsstats.c*/in++ )Y-#  /home XFS_STATS_DEC(c*/ino		(,xfsstats.c*/in-- )Y-#  /home XFS_STATS_ADD(c*/in, inc)	(,xfsstats.c*/in += (inc) )Y-Y-extSrt tic Axfs_init_procfs(tic );Y-extSrt tic Axfs_cleanup_procfs(tic );--
-
-#e_HWs4-+!CONFIG_PROC_FS -/--
-#  /home XFS_STATS_INC(c*/inoY-#  /home XFS_STATS_DEC(c*/inoY-#  /home XFS_STATS_ADD(c*/in, inc)
---d,aSIc __inlome tic Axfs_init_procfs(tic ) { };--d,aSIc __inlome tic Axfs_cleanup_procfs(tic ) { };--
-#Snd(+	4- !CONFIG_PROC_FS -/--
-#Snd(+ 4- __XFS_STATS_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsosup r.c linux-2.4.27-rc4/fs/xfs/linux/xfsosup r.c
--- linux-2.4.26/fs/xfs/linux/xfsosup r.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsosup r.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,985 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_clnt.h"
-#include "xfs_,*ans.h"
-#include "xfs_sb.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_a2_HW.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_m*/in.h"
-#include "xfs_a2_HW_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_ia2_HW_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ia2_HW.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_dinodh.h"
-#include "xfs_inodh.h"
-#include "xfs_bmap.h"
-#include "xfs_bin.h"
-#include "xfs_rta2_HW.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_maW.h"
-#include "xfs_attr.h"
-#include "xfs_buf_item.h"
-#include "xfs_utils.h"
-#include "xfs_versISF.h"
-
-#include <linux/blkdev.h>--#include <linux/init.h>----STATIC d,* Ok,quotactl_ops linvfs_qops;p-STATIC d,* Ok,sup r_operatISFs linvfs_sops;p-STATIC kmem_cache_  * linvfs_ nodhocachep;----STATIC d,* Ok,xfs_m*/in_args -
-xfs_args_a2_HW]ee(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Ed,* Ok,xfs_m*/in_args	*args;p-.-sargs = kmem_z 2_HW(snitof(s,* Ok,xfs_m*/in_args), KM_SLEEP);p-sargs->logbufs = args->logbufsnita=A-1;p-	strncpy(args->fsname, bdevname(sb->s_dev), MAXNAMELEN);
-p-s4- Copy OH ualrecHy-parsBd m*/in(2) .c ls we'rfRinStrestBd dn2*/m-sif (sb->s_+c ls & MS_NOATIME) -s	args->fc ls |=,XFSMNT_NOATIME;
-p-s4- DefaultROo(32 bit(inodhseonSLinux( 2_ yve ,Ime2*/m-sargs->fc ls |=,XFSMNT_32BITINODES;p-.-sr6dirt args;p-}
-
-__uiit64_t
-xfs_maxofile_offs6e(
-Eunsigted dl s	b12B,shift)m-{
-Eunsigted dl s	pagefactor0= 1;p-	unsigted dl s	bitshift =,BITS_PER_LONG - 1;
-p-s4- FigurfRout maximum filesnit, onSLinux(OHdoncan,depeFd onp-s68 OH ufilesystem b12B,snita(onS32 bit(platforms).m-s * __b12B,_preparh_w     doBsrOHdoninSan,[unsigted] long...m-s *      page->iidIx << (PAGE_CACHE_SHIFT - bbits)m-s * So, forApageAsize }b12B,s (4K onS32 bit(platforms),p-s68 OHis wraps at around 8Tb (hence,MAX_LFS_FILESIZESwHich,isp-s *      (((u64)PAGE_CACHE_SIZES<< (BITS_PER_LONG-1))-1)p-s * but forAsmaller b12B,snits it is 1essA(bbits = log2 bsnit).m-s * Ntye1: get_b12B,_tROakesua long (implicit+castdfverS bove)m-s * Ntye2: TH (Large B12B, Device (LBD and HAVE_SECTOR_T) p nchm-s * can,opSISFclly convertAOH u[unsigted] longdfverS boveAil om-s * an,[unsigted] long long.
-s */m-
-#if BITS_PER_LONG ==S32
-spagefactor0= PAGE_CACHE_SIZES>> (PAGE_CACHE_SHIFT - b12B,shift);Y-#end(+
-
-	, dirty(((__uiit64_t)pagefactor)S<< bitshift) - 1;
-}----STATIC __inlome__ tic 
-xfs_set_inodhops(
-Ed,* Ok, nodh		*inodh)m-{
-Etnodh_t			*vp = LINVFS_GET_VP(inodh);p-m-sif (vp->v_Oype == VNON) {p-sdr6movg_ nodhohash(inodh);p-sEmake_bad_inodh(inodh);p-s} e_HW if (S_ISREG(inodh->i_modh)) {p-s	inodh->i_op = &linvfs_file_ nodhooperatISFs;p-s	inodh->i_fop = &linvfs_file_operatISFs;p-s	inodh->i_mappiig->a_ops = &linvfs_aops;p-s} e_HW if (S_ISDIR(inodh->i_modh)) {p-s	inodh->i_op = &linvfs_dir_ nodhooperatISFs;p-s	inodh->i_fop = &linvfs_dir_operatISFs;p-s} e_HW if (S_ISLNK(inodh->i_modh)) {p-s	inodh->i_op = &linvfs_symlink_ nodhooperatISFs;p-s	if (inodh->i_b12B,s)
-			inodh->i_mappiig->a_ops = &linvfs_aops;p-s} e_HW {p-s	inodh->i_op = &linvfs_file_ nodhooperatISFs;p-s	init_specia2_inodh(inodh, inodh->i_modh,p-sds		kdev_t_to_nr(inodh->i_rdev));
-	}Y-}p-p-STATIC __inlome__ tic 
-xfs_revalid]ee_inodh(
-Exfs_m*/in_t		*mp,
-Etnodh_t			*vp,
-sxfs_ nodh_t		*ip)m-{
-Ed,* Ok, nodh		*inodh = LINVFS_GET_IP(vp);
-p-sinodh->i_modh	= (ip->i_d.di_rodh & MODEMASK) | VTTOIF(vp->v_Oype);p-Einodh->i_nlomk	= ip->i_d.di_nlomk;p-Einodh->i_uid	= ip->i_d.di_uid;p-Einodh->i_gid	= ip->i_d.di_gid;p-Eif (((1S<< vp->v_Oype) & ((1<<VBLK) | (1<<VCHR)o)a== 0) {p-s	inodh->i_rdev =,cODEV;p-s} e_HW {p-s	xfs_dev_t dev =,ip->i_df.if_u2.if_rdev;p-s	inodh->i_rdev =,XFS_DEV_TO_KDEVT(dev);
-	}Y-	inodh->i_b1ksnita=APAGE_CACHE_SIZE;p-Einodh->i_generaSISF = ip->i_d.di_gen;
-Ei_snitow    (inodh, (p->i_d.di_snit);Y-	inodh->i_b12B,s =p-sEXFS_FSB_TO_BB(mp, ip->i_d.di_nb12B,s + ip->i_delayed_b1ks);Y-	inodh->i_a,Ime	= ip->i_d.di_aSIme.tos6c;p-sinodh->i_mSIme	= ip->i_d.di_mSIme.tos6c;p-sinodh->i_cSIme	= ip->i_d.di_cSIme.tos6c;p-sif (ip->i_d.di_+c ls & XFS_DIFLAG_IMMUTABLE)p-s	inodh->i_fc ls |=,S_IMMUTABLE;p-se_HWp-		inodh->i_fc ls &= ~S_IMMUTABLE;p-sif (ip->i_d.di_+c ls & XFS_DIFLAG_APPENDop-sEinodh->i_fc ls |=,S_APPEND;p-se_HWp-		inodh->i_fc ls &= ~S_APPEND;p-sif (ip->i_d.di_+c ls & XFS_DIFLAG_SYNC)p-sdinodh->i_fc ls |=,S_SYNC;p-se_HWp-		inodh->i_fc ls &= ~S_SYNC;p-sif (ip->i_d.di_+c ls & XFS_DIFLAG_NOATIME) -s	inodh->i_fc ls |=,S_NOATIME;
-se_HWp-		inodh->i_fc ls &= ~S_NOATIME;
-p-svp->v_fc l &= ~VMODIFIEDLY-}
-
-tic 
-xfs_initiclize_vnodh(
-Ebhv_desc_t		*bdp,
-stnodh_t			*vp,
-sbhv_desc_t		* nodh_bhv,p-sil s		un12B,)p-{I-Exfs_ nodhot		*ip =,XFS_BHVTOI( nodh_bhv);
-Ed,* Ok, nodh		*inodh = LINVFS_GET_IP(vp);
-p-sif (! nodh_bhv->bd_vobj) {p-s	vp->v_vfsp = bhvtovfs(bdp);p-ssbhv_desc_init( nodh_bhv, ip, vp, &xfs_vnodhops);p-ssbhv_ilsert(VN_BHV_HEAD(vp),Ainodh_bhv);
-E}
-p-svp->v_Oype = IFTOVT(ip->i_d.di_rodh);
-p-s4- HgafRwe been(called duriigdOHe(new inodh cre]egrprocess,p-s68 inSwHich,cas  wefare Ooorearly0to(fill dn2OH uLinux(inodh.p-s2*/m-sif (vp->v_Oype == VNON)
-s	, dirt;--I-Exfs_revalid]ee_inodh(XFS_BHVTOM(bdp),Avp, ip);
-p-s4- For0new inodhsnwt need to(sSt tHe-ops vectors,p-s68 and un12B,eyve(inodh.p-s2*/m-sif (un12B,e&& (inodh->i_statta& I_NEW)) {p-sdxfs_set_inodhops(inodh);p-sEun12B,_new_inodh(inodh);p-s}Y-}p-p-s,* Ok, nodh -
-xfs_get_inodh(
-Ebhv_desc_t	*bdp,
-sxfs_ino_t	ino,p-sil s	+c ls)m-{
-Ed,* Ok,vfs	*vfsp = bhvtovfs(bdp);p-
-	, dirtyiget_12B,ed(vfsp->vfsosup r,Aino);p-}
-
-tic 
-xfs_flush_inodh(
-Exfs_ nodhot	*ip)m-{
-Ed,* Ok, nodh	*inodh = LINVFS_GET_IP(XFS_ITOV(ip)o;Y-m-sfilemap_fd]eaw    (inodh->i_mappiig);p-}
-
-tic 
-xfs_flush_device(
-Exfs_ nodhot	*ip)m-{
-Ed,* Ok, nodh	*inodh = LINVFS_GET_IP(XFS_ITOV(ip)o;Y-m-sfsync_no_sup r(inodh->i_dev);
-	xfs_log_forc ((p->i_m*/in, (xfs_lsno,)0, XFS_LOG_FORCE|XFS_LOG_SYNC);p-}p-p-s,* Ok,dentry -
-d_a2_HW_anon(s,* Ok, nodh -inodh)m-{
-Es,* Ok,dentry -dentry;Y-m-sspii_12B,(&dcache_12B,);p-slist_for_each_entry(dentry, &inodh->i_dentry, d_a2ias) {p-sdif (!(dentry->d_+c ls & DCACHE_NFSD_DISCONNECTED)) -s	dgo o(found;--s}m-sspii_un12B,(&dcache_12B,);p-m-sdentry = d_a2_HW_root(inodh);p-sif (likely(dentry !=,ct a)) -s	dentry->d_+c ls |=,DCACHE_NFSD_DISCONNECTED;
-	, dirtydentry;Y-(found:p-sdget_12B,ed(dentry);m-sdentry->d_vfs_fc ls |=,DCACHE_REFERENCED;
-	spii_un12B,(&dcache_12B,);p-	iput(inodh);p-s, dirtydentry;Y-}p-p-/*ARGSUSED8/--ily
-xfs_blkdev_get(Y-Exfs_m*/in_t		*mp,
-Ecoist chars	*name,
-Es,* Ok,b12B,_device	**bdevp)m-{
-Ed,* Ok,nameid]ea	nd;p-Eint	d	error;p-m-serror0= p nv_12okup(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd);p-sif (error)o{p-sdpriitk("XFS: Invalid device [%s],(error=%d\n", name, error);p-sEr6dirt -error;Y-s}.-p-s4- I OHdnkRwefactuclly wank,bd_acquire H re..  --hch,*/m-s*bdevp = bdget(kdev_t_to_nr(nd.dentry->d_inodh->i_rdev));
-	if (*bdevp)m-d	error0= blkdev_get(*bdevp, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
-se_HWp-		error0= -ENOMEM;p-m-sp nv_release(&nd);p-sr6dirt -error;Y-}
-
-tic 
-xfs_blkdev_put(
-Es,* Ok,b12B,_device	*bdev)p-{I-Eif (bdev)p-s	b1kdev_put(bdev, BDEV_FS);
-}
-
-tic 
-xfs_flush_buf,arg(
-	xfs_buf,arg_t		*btp)m-{
-Ep gebuf_delw  _flush(btp, PBDF_WAIT, ct a);p-}
-
-tic 
-xfs_d/ho_buf,arg(
-	xfs_buf,arg_t		*btp)m-{
-Exfs_flush_buf,arg(btp);p-	kmem_d/ho(btp, snitof(*btp));p-}
-
-ily
-xfs_recHonly_buf,arg(
-	xfs_buf,arg_t		*btp)m-{
-E, dirtyis_recH_only(btp->pbr_kdev);
-}
-
-tic 
-xfs_re_HW_buf,arg(
-	xfs_buf,arg_t		*btp)m-{
-Edestroy_bufft
s(btp->pbr_kdev);
-	,* nc]ee_inodhop ges(btp->pbr_mappiig, 0 a);p-}
-
-unsigted dl 
-xfs_getsnitobuf,arg(
-	xfs_buf,arg_t		*btp)m-{
-E, dirtyb12B,_snit(btp->pbr_kdev);
-}
-
-tic 
-xfs_setsnitobuf,arg(
-	xfs_buf,arg_t		*btp,
-Eunsigted dl s	b12B,snit,p-sunsigted dl s	sectorsnit)m-{
-Ebtp->pbr_bsnita=Ab12B,snit;
-Ebtp->pbr_sshift =,ffs(sectorsnit) - 1;
-Ebtp->pbr_smask =,sectorsnit - 1;
-p-sif (set_b12B,snit(btp->pbr_kdev,,sectorsnit))o{p-sdpriitk(KERN_WARNING
-sds"XFS: Can_ty(set_b12B,snit to(%u onSdevice 0x%x\n",p-sdssectorsnit, kdev_t_to_nr(btp->pbr_kdev));p-s}Y-}p-p-xfs_buf,arg_t -
-xfs_a2_HW_buf,arg(
-	s,* Ok,b12B,_device	*bdev)p-{I-Exfs_buf,arg_t		*btp;
-p-sbtp0= kmem_z 2_HW(snitof(*btp), KM_SLEEP);p-
-Ebtp->pbr_dev =, bdev->bd_dev;p-sbtp->pbr_kdev =,to_kdev_t(btp->pbr_dev);p-sbtp->pbr_bdev =,bdev;p-sbtp->pbr_mappiig =,bdev->bd_inodh->i_mappiig;
-	xfs_setsnitobuf,arg(btp, PAGE_CACHE_SIZE,p-sds    get_hardsect_snit(btp->pbr_kdev));p-
-Eswiech (MAJOR(btp->pbr_dev))o{p-scas  MD_MAJOR:p-scas  EVMS_MAJOR:p-ssbtp->pbr_fc ls = PBR_ALIGNED_ONLY;p-ssbreck;p-Ecas  LVM_BLK_MAJOR:p-ssbtp->pbr_fc ls = PBR_SECTOR_ONLY;p-ssbreck;p-E}p-
-	, dirtybtp;
-}p-p-STATIC s,* Ok, nodh -
-linvfs_a2_HW_inodh(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Etnodh_t			*vp;
-p-svp = (tnodh_t *)kmem_cache_ 2_HW(linvfs_ nodhocachep, Y-((((((((((((((((kmem_dc ls_convert(KM_SLEEP));p-Eif (!vp)m-d	, dirtyct a;p-sr6dirt LINVFS_GET_IP(vp);
-}p-p-STATIC tic 
-linvfs_destroy_inodh(
-Ed,* Ok, nodh		*inodh)m-{
-Ekmem_cache_d/ho(linvfs_ nodhocachep, LINVFS_GET_VP(inodh));
-}p-p-# /home VNODE_SIZE	\p-	(snitof(tnodh_t) - snitof(s,* Ok,inodh) +Aoffs6eof(s,* Ok,inodh, u))
-
-STATIC tic 
-init_once(
-Etic s		*d]ea,
-Ekmem_cache_t		*cachep,p-sunsigted longs	+c ls)m-{
-Etnodh_t			*vp = (tnodh_t *)d]ea;
-p-sif ((+c ls & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR))o==p-s    SLAB_CTOR_CONSTRUCTOR)o{p-sds,* Ok, nodh -inodh = LINVFS_GET_IP(vp);
-		mems6e(vp, 0, VNODE_SIZE);
-		__ nodhoinit_once(inodh);p-s}Y-}p-p-STATIC ily
-init_inodhcache( tic A)m-{
-Elinvfs_ nodhocachep0= kmem_cache_cre]eg("linvfs_ cache",p-sds	VNODE_SIZE, 0, SLAB_HWCACHE_ALIGN,p-sds	init_once, ct a);p-p-sif (linvfs_ nodhocachep0==,ct a)p-sEr6dirt -ENOMEM;p-sr6dirt 0;Y-}p-
-STATIC tic 
-destroy_inodhcache( tic A)m-{
-Eif (kmem_cache_destroy(linvfs_ nodhocachep)) -s	priitk(KERN_WARNING "%s:,cache s,ill dn2use!\n", __FUNCTION__);p-}p-p-/*
-68 Attempt0to(flusheyve(inodh,(OHdonwill actuclly fail
-68 if OHeAinodh isepintod, but wt dirtydOHe(inodh agaii
-68( t tHe-pointrwHeinit is unpintedAafSt
}a(logew    ,
- - since OHisAdonwheinOHe- nodh itselfAbecomed flushable. 
- -/--STATIC tic 
-linvfs_w    _inodh(
-Ed,* Ok, nodh		*inodh,p-sil s		sync)m-{
-Etnodh_t			*vp = LINVFS_GET_VP(inodh);p-Eint	d	error, .c ls = FLUSH_INODE;p-p-sif (vp) {p-s	vno,*ace_entry(vp, __FUNCTION__, (insn_t *)__r6dirt_ dHress);p-		if (sync)m-	s	+c ls |=,FLUSH_SYNC;p-s	VOP_IFLUSH(vp, .c ls, error);p-s}
-}p-p-STATIC tic 
-linvfs_clear_inodh(
-Ed,* Ok, nodh		*inodh)m-{
-Etnodh_t			*vp = LINVFS_GET_VP(inodh);p-m-sif (vp) {p-s	vnorele(vp);
-		vno,*ace_entry(vp, __FUNCTION__, (insn_t *)__r6dirt_ dHress);p-		/*p-sd - Do( 2_ our cleanup, and removg OHisAvnodh.p-sd -/
-		vn_removg(vp);
-	}Y-}p-p-
-# /home SYNCD_FLAGS	(SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE)p-p-STATIC ily
-syncd(tic  *arg)m-{
-Etfs_,			*vfsp = (tfs_, *) arg;p-Eint	d	error;p-m-sdaemonnit();p-sr6parhnt_to_init();
-Edigmask_12B,();
-Edigfills6e(&currSnt->b12B,ed);
-E__r6calc_sngpSndiig(currSnt);
-Edigmask_un12B,();p-
-Espriitf(currSnt->comm, "xfssyncd");p-
-Evfsp->vfsosync_task =,currSnt;
-Ewmb();
-Ewake_up(&vfsp->vfsowa  osync_tasko;Y-m-sfor-(;;)o{p-sdset_currSnt_statt(TASK_INTERRUPTIBLE);p-		schedulh_timeout(xfs_syncd_inStrval);p-		if (vfsp->vfsofc l & VFS_UMOUNT)m-	s	breck;p-E	if (vfsp->vfsofc l & VFS_RDONLY)m-	s	continue;p-s	VFS_SYNC(vfsp, SYNCD_FLAGS, ct a, error);p-s}
-
-Evfsp->vfsosync_task =,ct a;p-swmb();
-Ewake_up(&vfsp->vfsowa  osync_tasko;Y-m-sr6dirt 0;Y-}p-
-STATIC ily
-linvfs_s,art_syncd(tfs_, *vfsp)p-{I-Eil epid;p-m-spc  = kernel_OHe ad(syncd, (tic  *) vfsp,m-	s	CLONE_VM | CLONE_FS | CLONE_FILES);p-Eif (pc  < 0)
-		r6dirt pid;p-	wa  oeveit(vfsp->vfsowa  osync_task, vfsp->vfsosync_task);p-sr6dirt 0;Y-}p-
-STATIC tic 
-linvfs_s,op_syncd(tfs_, *vfsp)p-{I-Evfsp->vfsofc l |=,VFS_UMOUNT;p-swmb();
-
-Ewake_up_process(vfsp->vfsosync_task);p-swa  oeveit(vfsp->vfsowa  osync_task, !vfsp->vfsosync_task);p-}p-
-STATIC tic 
-linvfs_put_sup r(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error;p-m-slinvfs_s,op_syncd(tfsp);
-	VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, ct a, error);p-sif (!error)p-s	VFS_UNMOUNT(vfsp, 0, ct a, error);p-sif (error)o{p-sdpriitk("XFS unm*/in got error0%d\n", error);p-sEpriitk("%s:,vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp);p-sEr6dirt;p-s}
-
-Evfs_dea2_HW]ee(vfsp);p-}p-
-STATIC tic 
-linvfs_w    _sup r(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error;p-m-sif (sb->s_+c ls & MS_RDONLY)o{p-sdsb->s_dirt = 0; 4- paranoia -/
-		r6dirt;p-s}
-s4- Pusheyve(logeand sup rb12B,}a(little2*/m-sVFS_SYNC(vfsp, SYNC_FSDATA, ct a, error);p-ssb->s_dirt = 0;Y-}p-
-STATIC ily
-linvfs_sync_sup r(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Etfs_,		*vfsp = LINVFS_GET_VFS(sb);p-Eint	derror;p-m-sVFS_SYNC(vfsp, SYNC_FSDATA|SYNC_WAIT, ct a, error);p-sr6dirt -error;Y-}
-
-STATIC ily
-linvfs_s,atfs(
-Ed,* Ok,sup r_b12B,	*sb,
-Es,* Ok,s,atfssd*d,atp)m-{
-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error;p-m-sVFS_STATVFS(vfsp, d,atp, ct a, error);p-sr6dirt -error;Y-}
-
-STATIC ily
-linvfs_remo/in(
-Ed,* Ok,sup r_b12B,	*sb,
-Eint	d	*+c ls,
-schar			*opSISFs)m-{
-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Ed,* Ok,xfs_m*/in_args	*args0= xfs_args_a2_HW]ee(sb);p-Eint	d	error;p-m-sVFS_PARSEARGS(vfsp, opSISFs, args, 1, error);p-sif (!error)p-s	VFS_MNTUPDATE(vfsp, .c ls, args, error);p-skmem_d/ho(args, snitof(*args));p-sr6dirt -error;Y-}
-
-STATIC tic 
-linvfs_d/hoze_fs(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Etnodh_t			*vp;
-Eint	d	error;p-m-sif (sb->s_+c ls & MS_RDONLY)
-		r6dirt;p-sVFS_ROOT(vfsp, &vp, error);p-sVOP_IOCTL(vp, LINVFS_GET_IP(vp), ct a, 0, XFS_IOC_FREEZE, 0, error);p-sVN_RELE(vp);
-}p-p-STATIC tic 
-linvfs_und/hoze_fs(
-Ed,* Ok,sup r_b12B,	*sb)m-{
-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Etnodh_t			*vp;
-Eint	d	error;p-m-sVFS_ROOT(vfsp, &vp, error);p-sVOP_IOCTL(vp, LINVFS_GET_IP(vp), ct a, 0, XFS_IOC_THAW, 0, error);p-sVN_RELE(vp);
-}p-p-STATIC ily
-linvfs_dentry_to_fh(
-Ed,* Ok,dentry		*dentry,
-E__u32s		*d]ea,
-Eint	d	*lenp,p-sil s		need_parhnt)m-{
-Ed,* Ok, nodh		*inodh = dentry->d_inodh ;p-Etnodh_t			*vp = LINVFS_GET_VP(inodh);p-Eint	d	maxlen = *lenp;
-	xfs_fid2_t		fid;p-Eint	d	error;p-m-sif (maxlen < 3)
-		r6dirt 255 ;p-m-sVOP_FID2(vp, (s,* Ok,fc  *)&fc , error);p-sd]ea[0] =o(__u32)fc .fc _ino;s4-+32 bits(o++inodh iseOK2*/m-sd]ea[1] =ofc .fc _gen;
-m-s*lenp =o2 ;m-sif (maxlen < 4 || ! need_parhnt)m-		r6dirt 2 ;p-m-sinodh = dentry->d_parhnt->d_inodh ;p-Etp = LINVFS_GET_VP(inodh);p-m-sVOP_FID2(vp, (s,* Ok,fc  *)&fc , error);p-sd]ea[2] =o(__u32)fc .fc _ino;s4-+32 bits(o++inodh iseOK2*/m-s*lenp =o3 ;m-sif (maxlen < 4)m-		r6dirt 3 ;m-sd]ea[3] =ofc .fc _gen;
-s*lenp =o4 ;p-sr6dirt 4 ;p-}p-p-STATIC s,* Ok,dentry -
-linvfs_dh_to_dentry(
-Ed,* Ok,sup r_b12B,	*sb,
-E__u32s		*d]ea,
-Eint	d	len,
-Eint	d	fhOype,
-Eint	d	parhnt)m-{
-Etnodh_t			*vp;
-Ed,* Ok, nodh		*inodh = ct a;p-sd,* Ok,dentry		*result;
-	xfs_fid2_t		xfid;p-Etfs_,			*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error;p-m-sxfc .fc _len = snitof(xfs_fid2_t) - snitof(xfc .fc _len);
-	xfc .fc _pad = 0;Y-p-sif (!parhnt) {p-sdxfc .fc _gen = d]ea[1];p-sdxfc .fc _ino =o(__u64)d]ea[0];p-s} e_HW {p-s	if (fhOype0==,4)m-		dxfc .fc _gen = d]ea[3];p-sde_HWp-			xfc .fc _gen = 0;p-sdxfc .fc _ino =o(__u64)d]ea[2];p-s}
-
-EVFS_VGET(vfsp, &vp, (fc _, *)&xfc , error);p-sif (error || vp0==,ct a)p-sEr6dirt ERR_PTR(-ESTALE) ;p-m-sinodh = LINVFS_GET_IP(vp);
-p-sresult = d_a2_HW_anon(inodh);p-sif (unlikely(result ==,ct a)) {p-s	iput(inodh);p-sEr6dirt ERR_PTR(-ENOMEM);
-	}Y-	r6dirt result;
-}
-
-STATIC ily
-linvfs_show_opSISFs(
-Ed,* Ok,seq_file		*m,
-Es,* Ok,vfsm*/in		*mnt)m-{
-Ed,* Ok,vfssd*vfsp = LINVFS_GET_VFS(mnt->mnt_sb);p-Eint	d	error;p-m-sVFS_SHOWARGS(vfsp, m, error);p-sr6dirt error;Y-}
-
-STATIC ily
-linvfs_getxstatt(
-Ed,* Ok,sup r_b12B,	*sb,
-Es,* Ok,fs_quota_s,at	*+qs)m-{
-Ed,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error;p-m-sVFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (c dHr_t)+qs, error);p-sr6dirt -error;Y-}
-
-STATIC ily
-linvfs_setxstatt(
-Ed,* Ok,sup r_b12B,	*sb,
-Eunsigted dl s	+c ls,
-sint	d	op)m-{
-Ed,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error;p-m-sVFS_QUOTACTL(vfsp, op, 0, (c dHr_t)&.c ls, error);p-sr6dirt -error;Y-}
-
-STATIC ily
-linvfs_getxquota(
-Ed,* Ok,sup r_b12B,	*sb,
-Eint	d	Oype,
-Eqc _,ds	id,
-Es,* Ok,fs_disk_quota	*+dq)m-{
-Ed,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error, getrodh;p-m-sgetrodh =o(Oype0==,GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA;m-sVFS_QUOTACTL(vfsp, getrodh, c , (c dHr_t)+dq, error);p-sr6dirt -error;Y-}
-
-STATIC ily
-linvfs_setxquota(
-Ed,* Ok,sup r_b12B,	*sb,
-Eint	d	Oype,
-Eqc _,ds	id,
-Es,* Ok,fs_disk_quota	*+dq)m-{
-Ed,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p-Eint	d	error, setrodh;p-m-ssetrodh =o(Oype0==,GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM;m-sVFS_QUOTACTL(vfsp, setrodh, c , (c dHr_t)+dq, error);p-sr6dirt -error;Y-}
-
-STATIC d,* Ok,sup r_b12B, -
-linvfs_recH_sup r(
-Ed,* Ok,sup r_b12B,	*sb,p-stic s		*d]ea,
-Eint	d	silent)m-{
-Etnodh_t			*rootvp;
-Ed,* Ok,vfs		*vfsp = vfs_a2_HWatt();p-Ed,* Ok,xfs_m*/in_args	*args0= xfs_args_a2_HW]ee(sb);p-Es,* Ok,s,atfssds,atvfs;p-Eint	d	error;p-m-svfsp->vfsosup r = sb;p-sLINVFS_SET_VFS(sb, vfsp);p-sif (sb->s_+c ls & MS_RDONLY)
-		vfsp->vfsofc l |=,VFS_RDONLY;p-sbhv_ilsert_a2__vfsops(vfsp);p-
-sVFS_PARSEARGS(vfsp, (char *od]ea, args, 0, error);p-sif (error)o{p-sdbhv_r6movg_a2__vfsops(vfsp, 1);p-sEgo o(fail_vfsop;p-s}
-
-Esb_min_b12B,snit(sb, BBSIZE);
-	sb->s_qcop = &linvfs_qops;p-	sb->s_op = &linvfs_sops;p-
-sVFS_MOUNT(vfsp, args, ct a, error);p-sif (error)o{p-sdbhv_r6movg_a2__vfsops(vfsp, 1);p-sEgo o(fail_vfsop;p-s}
-
-EVFS_STATVFS(vfsp, &s,atvfs, ct a, error);p-sif (error)p-sEgo o(fail_unm*/in;p-m-ssb->s_dirt = 1;p-	sb->s_magic = s,atvfs.f_Oype;p-	sb->s_b12B,snit = s,atvfs.f_bsnit;
-Esb->s_b12B,snit_bits = ffs(s,atvfs.f_bsnit) - 1;
-Esb->s_maxby  s0= xfs_maxofile_offs6e(sb->s_b12B,snit_bits);
-	set_posix_aclofc l(sb);p-
-sVFS_ROOT(vfsp, &rootvp, error);p-sif (error)p-sEgo o(fail_unm*/in;p-m-ssb->s_root = d_a2_HW_root(LINVFS_GET_IP(rootvp));p-Eif (!sb->s_root)p-sEgo o(fail_vnrele;p-Eif (is_bad_inodh(sb->s_root->d_inodh))p-sEgo o(fail_vnrele;p-Eif (linvfs_s,art_syncd(tfsp))p-sEgo o(fail_vnrele;p-Evno,*ace_exit(rootvp, __FUNCTION__, (insn_t *)__r6dirt_ dHress);p-
-skmem_d/ho(args, snitof(*args));p-sr6dirt sb;p-
-fail_vnrele:p-sif (sb->s_root)o{p-sddput(sb->s_root);p-sEsb->s_root = ct a;p-s} e_HW {p-s	VN_RELE(rootvp);p-s}
-
-fail_unm*/in:
-sVFS_UNMOUNT(vfsp, 0, ct a, error);p-
-fail_vfsop:
-Evfs_dea2_HW]ee(vfsp);p-skmem_d/ho(args, snitof(*args));p-sr6dirt ct a;p-}p-p-
-STATIC d,* Ok,sup r_operatISFs linvfs_sops =o{p-s.a2_HW_inodh		= linvfs_a2_HW_inodh,
-E.destroy_inodh		= linvfs_destroy_inodh,
-E.w    _inodh		= linvfs_w    _inodh,
-E.clear_inodh		= linvfs_clear_inodh,
-E.put_sup r		= linvfs_put_sup r,
-E.w    _sup r		= linvfs_w    _sup r,
-E.sync_fssd= linvfs_sync_sup r,
-E.w    _sup r_12B,fss= linvfs_d/hoze_fs,
-E.un12B,fssd= linvfs_und/hoze_fs,
-E.s,atfssdd= linvfs_s,atfs,
-E.remo/in_fssd= linvfs_remo/in,
-E.dh_to_dentrysd= linvfs_dh_to_dentry,
-E.dentry_to_fh		= linvfs_dentry_to_fh,
-E.show_opSISFsdd= linvfs_show_opSISFs,p-};Y-Y-STATIC d,* Ok,quotactl_ops linvfs_qops =o{p-s.get_xstattdd= linvfs_getxstatt,
-E.set_xstattdd= linvfs_setxstatt,
-E.get_xquota	d= linvfs_getxquota,
-E.set_xquota	d= linvfs_setxquota,
-};Y-Y-STATIC d,* Ok,file_system_Oype xfs_fs_Oype = {p-s.own r		d= THIS_MODULE,p-s.name		d= "xfs",
-E.recH_sup rsd= linvfs_recH_sup r,
-E.ds_+c lssd= FS_REQUIRES_DEV,
-};Y-Y-
-STATIC ily __iniy
-init_xfs_fs( tic A)m-{
-Eint	d	error;p-Es,* Ok,sysinfod	si;p-Es,aSIc char		message[] __iniyd]ea = KERN_INFO \p-		XFS_VERSION_STRING " winv2",XFS_BUILD_OPTIONS2",enabled\n";p-
-spriitk(message);p-
-Esi_meminfo(&si);
-	xfs_physmem = sn.totalram;p-
-sk,*ace_init(64);p-
-Eerror0= init_inodhcache();p-sif (error < 0)
-		go o(undo_inodhcache;p-
-Eerror0= p gebuf_init();
-Eif (error < 0)
-		go o(undo_p gebuf;p-m-svn_init();
-Exfs_init();
-Euuc _init();
-Evfs_initdmapi();
-Evfs_initquota();p-
-Eerror0= regisct
_filesystem(&xfs_fs_Oype);p-sif (error)p-sEgo o(undo_regisct
;p-sr6dirt 0;Y-p-undo_regisct
:
-Ep gebuf_ct
minate();p-
-undo_p gebuf:p-sdestroy_inodhcache();p-
-undo_inodhcache:
-sr6dirt error;Y-}
-
-STATIC tic A__exitY-exit_xfs_fs( tic A)m-{
-Eunregisct
_filesystem(&xfs_fs_Oype);p-sxfs_cleanup();
-Evfs_exitquota();p-Evfs_exitdmapi();
-Ep gebuf_ct
minate();p-sdestroy_inodhcache();p-sk,*ace_uninit();
-}
-
-rodule_init( nit_xfs_fs);
-rodule_exit(exit_xfs_fs);p-
-MODULE_AUTHOR("Silicon Graphics, Inc.");p-MODULE_DESCRIPTION(XFS_VERSION_STRING " winv2",XFS_BUILD_OPTIONS2",enabled");p-MODULE_LICENSE("GPL");pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsosup r.h linux-2.4.27-rc4/fs/xfs/linux/xfsosup r.h
--- linux-2.4.26/fs/xfs/linux/xfsosup r.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsosup r.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,141 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifndef __XFS_SUPER_H__--# /home __XFS_SUPER_H__----#ifdef CONFIG_XFS_DMAPIY-#  /home vfs_insertdmapi(vfs)	vfs_insertops(vfsp, &xfs_dmops)Y-#  /home vfs_initdmapi()	dmapi_init()Y-#  /home vfs_exitdmapi()	dmapi_uninit()Y-#e_HWp-#  /home vfs_insertdmapi(vfs)	do+{ } wHile (0)Y-#  /home vfs_initdmapi()	do+{ } wHile (0)Y-#  /home vfs_exitdmapi()	do+{ } wHile (0)Y-#end(+
-
-#ifdef CONFIG_XFS_QUOTAp-#  /home vfs_insertquota(vfs)	vfs_insertops(vfsp, &xfs_qmops)Y-extSrt tic Axfs_qm_init(tic );Y-extSrt tic Axfs_qm_exit(tic );Y-#  /home vfs_initquota()	xfs_qm_init()Y-#  /home vfs_exitquota()	xfs_qm_exit()Y-#e_HWp-#  /home vfs_insertquota(vfs)	do+{ } wHile (0)Y-#  /home vfs_initquota()	do+{ } wHile (0)Y-#  /home vfs_exitquota()	do+{ } wHile (0)Y-#end(+
-
-#ifdef CONFIG_XFS_POSIX_ACLY-#  /home XFS_ACL_STRING		"ACLs, "Y-#  /home set_posix_aclofc l(sb)	((sb)->s_+c ls |= MS_POSIXACL)Y-#e_HWp-#  /home XFS_ACL_STRINGY-#  /home set_posix_aclofc l(sb)	do+{ } wHile (0)Y-#end(+
-
-#ifdef CONFIG_XFS_SECURITYY-#  /home XFS_SECURITY_STRING	"secu   y attributes, "Y-#  /home ENOSECURITY		0Y-#e_HWp-#  /home XFS_SECURITY_STRINGY-#  /home ENOSECURITY		EOPNOTSUPPY-#end(+
-
-#ifdef CONFIG_XFS_RTp-#  /home XFS_REALTIME_STRING	"recltime, "Y-#e_HWp-#  /home XFS_REALTIME_STRINGY-#end(+
-
-#if,XFS_BIG_BLKNOSp-# if,XFS_BIG_INUMSp-#   /home XFS_BIGFS_STRING	"large b12B,/inodh numbers, "Y-# e_HWp-#   /home XFS_BIGFS_STRING	"large b12B, numbers, "Y-# end(+
-#e_HWp-#  /home XFS_BIGFS_STRINGY-#end(+
-
-#ifdef CONFIG_XFS_TRACEp-#  /home XFS_TRACE_STRING	",*aciig, "Y-#e_HWp-#  /home XFS_TRACE_STRINGY-#end(+
-
-#ifdef XFSDEBUGp-#  /home XFS_DBG_STRING		"debug"Y-#e_HWp-#  /home XFS_DBG_STRING		"no debug"Y-#end(+
-
-# /home XFS_BUILD_OPTIONS	XFS_ACL_STRING \p-				XFS_SECURITY_STRING \p-				XFS_REALTIME_STRING \p-				XFS_BIGFS_STRING \p-				XFS_TRACE_STRING \p-				XFS_DBG_STRING 4- DBG must benlastd*/m-
-# /home LINVFS_GET_VFS(s) \p-	(tfs_, *)((s)->u.generic_sbp)m-# /home LINVFS_SET_VFS(s, vfsp) \p-	((s)->u.generic_sbp = vfsp)p-p-s,* Ok,xfs_ nodh;p-s,* Ok,xfs_m*/in;p-s,* Ok,pb_,argen;p-s,* Ok,b12B,_device;p-
-extSrt __uiit64_t xfs_maxofile_offs6e(unsigted dl );p-
-extSrt s,* Ok, nodh -xfs_get_inodh(bhv_desc_t *,,xfs_ no_n, int);Y-extSrt tic Axfs_initiclize_vnodh(bhv_desc_t *,,tnodh_t *, bhv_desc_t *,,dl );p-
-extSrt tic Axfs_flush_inodh(s,* Ok,xfs_ nodh *);Y-extSrt tic Axfs_flush_device(s,* Ok,xfs_ nodh *);Y-Y-extSrt ily  xfs_blkdev_get(s,* Ok,xfs_m*/in *,,coist char *,p-				s,* Ok,b12B,_device **);Y-extSrt tic Axfs_b1kdev_put(s,* Ok,b12B,_device *);p-
-extSrt s,* Ok,pb_,argen -xfs_a2_HW_buf,arg(s,* Ok,b12B,_device *);p-extSrt tic Axfs_re_HW_buf,arg(s,* Ok,pb_,argen -);Y-extSrt tic Axfs_f/ho_buf,arg(s,* Ok,pb_,argen -);Y-extSrt tic Axfs_flush_buf,arg(s,* Ok,pb_,argen -);Y-extSrt ily xfs_recHonly_buf,arg(s,* Ok,pb_,argen -);Y-extSrt tic Axfs_setsnitobuf,arg(s,* Ok,pb_,argen -, unsigted dl , unsigted dl );Y-extSrt unsigted dl  xfs_getsnitobuf,arg(s,* Ok,pb_,argen -);Y-
-4- m nchiig a 2.6 kernel export,(OHuon_t xfs_+prefixd*/m-extSrt s,* Ok,dentry -d_a2_HW_anon(s,* Ok, nodh -inodh);Y-
-#Snd(+	4- __XFS_SUPER_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsosysctl.c linux-2.4.27-rc4/fs/xfs/linux/xfsosysctl.c
--- linux-2.4.26/fs/xfs/linux/xfsosysctl.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsosysctl.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,195 +0,0 @@
-4-
-68 Copyright (c) 2001-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-#include "xfs_refcache.h"
-#include <linux/sysctl.h>--#include <linux/proc_fs.h>Y-Y-
-s,aSIc s,* Ok,ctl_table_H adIS -xfs_table_H adIS;Y-Y-
-4- Customrproc igndlt
s */m-
-STATIC ily
-xfs_refcache_resnitoproc_igndlt
(
-Ectl_table	*ctl,
-Eint	dw    ,
-	d,* Ok,file	*filp,p-stic s	*bufft
,
-	dnitotd	*lenp)m-{
-Eint	drey, *valp = ctl->d]ea;
-Eint	dxfs_refcache_new_snit;
-Eint	dxfs_refcache_old_snit = *valp;Y-m-sr6d0= proc_dointvec_minmax(ctl,ew    , filp, bufft
, lenp);p-sxfs_refcache_new_snit = *valp;Y-m-sif (!r6d0&& w     && xfs_refcache_new_snit != xfs_refcache_old_snit) {p-sdxfs_refcache_resnit(xfs_refcache_new_snit);p-sE4- Don'k,purge morfROHan snit o++OHeAcache -/
-		if (xfs_refcache_new_snit < xfs_refcache_purge_c*/inoY-	sdxfs_refcache_purge_c*/in = xfs_refcache_new_snit;p-s}
-
-Er6dirt ret;
-}
-
-#ifdef CONFIG_PROC_FS
-STATIC ily
-xfs_stats_clear_proc_igndlt
(
-Ectl_table	*ctl,
-Eint	dw    ,
-	d,* Ok,file	*filp,p-stic s	*bufft
,
-	dnitotd	*lenp)m-{
-Eint	drey, *valp = ctl->d]ea;
-E__uiit32_t	vn_acSIvg;Y-m-sr6d0= proc_dointvec_minmax(ctl,ew    , filp, bufft
, lenp);p-m-sif (!r6d0&& w     && *valp)o{p-sdpriitk("XFS Cleariig xfsstats\n");p-sE4- sgafRvn_acSIvg,n(t'sua universal ,* th! -/
-		vn_acSIvg = xfsstats.vn_acSIvg;Y-		mems6e(&xfsstats, 0, snitof(xfsstats));p-s	xfsstats.vn_acSIvg = vn_acSIvg;Y-		xfs_stats_clear = 0;p-s}
-
-Er6dirt ret;
-}
-#Snd(+ 4- CONFIG_PROC_FS -/--
-STATIC ctl_table xfs_table[] = {p-s{XFS_REFCACHE_SIZE, "refcache_snit", &xfs_params.refcache_snit.val,
-	dnitof(dl ), 0644, ct a, &xfs_refcache_resnitoproc_igndlt
,
-	&sysctl_intvec, ct a, 
-	&xfs_params.refcache_snit.min, &xfs_params.refcache_snit.max},
-
-E/* Ntye,+OHeAmax H rendsfdifft
ein, it is OHeAcurrSnt refcache snit -/
-	{XFS_REFCACHE_PURGE, "refcache_purge", &xfs_params.refcache_purge.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.refcache_purge.min, &xfs_params.refcache_snit.val},
-
-E{XFS_RESTRICT_CHOWN, "red,*ict_chown", &xfs_params.red,*ict_chown.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.red,*ict_chown.min, &xfs_params.red,*ict_chown.max},
-
-E{XFS_SGID_INHERIT, "irix_sgi _inH rit", &xfs_params.sgi _inH rit.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.sgi _inH rit.min, &xfs_params.sgi _inH rit.max},
-
-E{XFS_SYMLINK_MODE, "irix_symlink_rodh", &xfs_params.symlink_rodh.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.symlink_rodh.min, &xfs_params.symlink_rodh.max},
-
-E{XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.panic_mask.min, &xfs_params.panic_mask.max},
-
-E{XFS_ERRLEVEa, "error_lmvel", &xfs_params.error_lmvel.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.error_lmvel.min, &xfs_params.error_lmvel.max},
-
-E{XFS_SYNC_INTERVAa, "sync_inStrval", &xfs_params.sync_inStrval.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a, 
-	&xfs_params.sync_inStrval.min, &xfs_params.sync_inStrval.max},
-
-E{XFS_INHERIT_SYNC, "inH rit_sync", &xfs_params.inH rit_sync.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a,
-	&xfs_params.inH rit_sync.min, &xfs_params.inH rit_sync.max},
-
-E{XFS_INHERIT_NODUMP, "inH rit_nod mp", &xfs_params.inH rit_nod mp.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a,
-	&xfs_params.inH rit_nod mp.min, &xfs_params.inH rit_nod mp.max},
-
-E{XFS_INHERIT_NOATIME, "inH rit_noaSIme", &xfs_params.inH rit_noaSIm.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a,
-	&xfs_params.inH rit_noaSIm.min, &xfs_params.inH rit_noaSIm.max},
-	
-E{XFS_FLUSH_INTERVAa, "flush_inStrval", &xfs_params.flush_inStrval.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a,
-	&xfs_params.flush_inStrval.min, &xfs_params.flush_inStrval.max},
-
-E{XFS_AGE_BUFFER, "age_bufft
", &xfs_params.age_bufft
.val,
-	dnitof(dl ), 0644, ct a, &proc_dointvec_minmax,
-	&sysctl_intvec, ct a,
-	&xfs_params.age_bufft
.min, &xfs_params.age_bufft
.max},
-
-E/* please keep OHdonOH ulastdentry -/
-#ifdef CONFIG_PROC_FS
-E{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
-	dnitof(dl ), 0644, ct a, &xfs_stats_clear_proc_igndlt
,
-	&sysctl_intvec, ct a, 
-	&xfs_params.stats_clear.min, &xfs_params.stats_clear.max},
-#Snd(+ 4- CONFIG_PROC_FS -/--
-	{0}
-};Y-Y-STATIC ctl_table xfs_dir_table[] = {p-s{FS_XFS, "xfs", ct a, 0, 0555, xfs_table},
-	{0}
-};Y-Y-STATIC ctl_table xfs_root_table[] = {p-s{CTL_FS, "fs",  ct a, 0, 0555, xfs_dir_table},
-	{0}
-};Y-Y-tic 
-xfs_sysctl_regisct
(tic )p-{I-Exfs_table_H adIS = regisct
_sysctl_table(xfs_root_table, 1);p-}
-
-tic 
-xfs_sysctl_unregisct
(tic )p-{I-Eif (xfs_table_H adISoY-	sunregisct
_sysctl_table(xfs_table_H adISo;p-}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsosysctl.h linux-2.4.27-rc4/fs/xfs/linux/xfsosysctl.h
--- linux-2.4.26/fs/xfs/linux/xfsosysctl.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsosysctl.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,111 +0,0 @@
-4-
-68 Copyright (c) 2001-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#ifndef __XFS_SYSCTL_H__--# /home __XFS_SYSCTL_H__--
-#include <linux/sysctl.h>--
-4-
-68 Tunable xfs paramect
s
- -/--
-Oypedef s,* Ok,xfs_sysctl_val {
-Eint min;
-Eint val;
-Eint max;p-},xfs_sysctl_val_n;p-m-Oypedef s,* Ok,xfs_param {I-Exfs_sysctl_val_n refcache_snit;s4-+Snit o++NFS reft
eiceAcache.((((((-/
-	xfs_sysctl_val_n refcache_purge;4-+# o++entriBs to(purge each SIme.((-/
-	xfs_sysctl_val_n red,*ict_chown;4-+Root/non-root can,gIvg awayn.iles.-/
-	xfs_sysctl_val_n sgi _inH rit;s4-+InH rit,S_ISGID bit+(++process' GID p-				s68 is+_tyia member o++OHeAparhnt dirp-				s68 GID -/
-	xfs_sysctl_val_n symlink_rodh;s4-+LdnkRcre]e rodh afftcte }byrumask -/
-	xfs_sysctl_val_n panic_mask;s4-+bitmask to(causeApanic onSerrors. -/
-	xfs_sysctl_val_n error_lmvel;s4-+Deg/ho(o++reportiig for-problems  -/
-	xfs_sysctl_val_n sync_inStrval;s4-+SIme between(sync(calls(((((((((((-/
-	xfs_sysctl_val_n stats_clear;s4-+Res6t( 2_ XFS s,aSIsyics to(zero. -/
-	xfs_sysctl_val_n inH rit_sync;s4-+InH rit,OHeA"sync", nodh fc l. -/
-	xfs_sysctl_val_n inH rit_nod mp;4-+InH rit,OHeA"nod mp", nodh fc l. -/
-	xfs_sysctl_val_n inH rit_noaSIm;4-+InH rit,OHeA"noaSIme", nodh fc l. -/
-	xfs_sysctl_val_n flush_inStrval;4-+inStrval between(ruFs(o++OHep-				s68 delw  (flushedaemon.((-/
-	xfs_sysctl_val_n age_bufft
;s4-+SIme for-bufft
 to(age beforep-				s68 we(flusheit.((-/
-},xfs_param_n;p-m-4-
-68 xfs_error_lmvel:
- -
-68 How much error0reportiig will benstrerwHeininStrnal problems arep-68 eic*/int
ed.((TheseAproblems normally r6dirt an,EFSCORRUPTED OorOHeirp-f* caller,(winv2noroOH rninformaSISF reportBd.d- -
-68 0	No error0reports
-68 1	Report,EFSCORRUPTED errors OHatAwill causeAa filesystemAdeutdown
-68 5	Report, 2_ EFSCORRUPTED errors ( 2_ o++OHeAabovg errors,nplus0 ny
-68	addiSISFal errors OHatAare known Oornot causeAdeutdowns)Y- -
-68 xfs_panic_mask bit+0x8 dirtonOH uerror0reportsninSoApanics
- -/--
-enum {I-EXFS_REFCACHE_SIZE = 1,I-EXFS_REFCACHE_PURGE =o2,I-EXFS_RESTRICT_CHOWN =o3,I-EXFS_SGID_INHERIT =o4,I-EXFS_SYMLINK_MODE =o5,I-EXFS_PANIC_MASK =o6,I-EXFS_ERRLEVEa =o7,I-EXFS_SYNC_INTERVAa =o8,I-EXFS_STATS_CLEAR = 12,I-EXFS_INHERIT_SYNC = 13,I-EXFS_INHERIT_NODUMP = 14,I-EXFS_INHERIT_NOATIME = 15,I-EXFS_FLUSH_INTERVAa = 16,I-EXFS_AGE_BUFFER = 17,
-};Y-Y-extSrt xfs_param_n	xfs_params;
-
-#ifdef CONFIG_SYSCTLY-extSrt tic Axfs_sysctl_regisct
(tic );Y-extSrt tic Axfs_sysctl_unregisct
(tic );Y-#e_HWp-#  /home xfs_sysctl_regisct
()		do+{ } wHile (0)Y-#  /home xfs_sysctl_unregisct
()	do+{ } wHile (0)Y-#end(+ 4- CONFIG_SYSCTL -/--
-#end(+ 4- __XFS_SYSCTL_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsoversISF.h linux-2.4.27-rc4/fs/xfs/linux/xfsoversISF.h
--- linux-2.4.26/fs/xfs/linux/xfsoversISF.h	2004-02-18 13:36:31.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsoversISF.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,44 +0,0 @@
-4-
-68 Copyright (c) 2001-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.	 AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-4-
-68 Dummyn.ile OHatAcan,contain,a+SImes,amp to(putninSoAOHep-68 XFS init s,*iig, SoAhelpnusers keep Orack o++wHatAOHey'rep-68 ruFning
-68/--
-#ifndef __XFS_VERSION_H__--# /home __XFS_VERSION_H__--
-# /home XFS_VERSION_STRING "SGI XFS"--
-#end(+ 4- __XFS_VERSION_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsovfs.c linux-2.4.27-rc4/fs/xfs/linux/xfsovfs.c
--- linux-2.4.26/fs/xfs/linux/xfsovfs.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsovfs.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,328 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_macros.h"
-#include "xfs_inum.h"
-#include "xfs_log.h"
-#include "xfs_clnt.h"
-#include "xfs_Orans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_imap.h"
-#include "xfs_a2_HW.h"
-#include "xfs_dmapi.h"
-#include "xfs_m*/in.h"
-#include "xfs_quota.h"
-
-int
-vfs_m*/in(
-	s,* Ok,bhv_descs	*bdp,
-	d,* Ok,xfs_m*/in_args	*args,
-	d,* Ok,cred		*cr)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsom*/inoY-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsom*/ino(next, args, cr));p-}
-
-int
-vfs_parseargs(
-	s,* Ok,bhv_descs	*bdp,
-	char			*s,
-	d,* Ok,xfs_m*/in_args	*args,
-	int	d	f)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsoparseargsoY-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsoparseargso(next, s, args, f));p-}
-
-int
-vfs_showargs(
-	s,* Ok,bhv_descs	*bdp,
-	d,* Ok,seq_file		*m)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsoshowargsoY-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsoshowargso(next, m));p-}
-
-int
-vfs_unm*/in(
-	s,* Ok,bhv_descs	*bdp,
-	int	d	fl,
-	d,* Ok,cred		*cr)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsounm*/inoY-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsounm*/ino(next, fl, cr));p-}
-
-int
-vfs_mntupdatt(
-Ed,* Ok,bhv_descs	*bdp,
-	int	d	*fl,
-	d,* Ok,xfs_m*/in_args	*args)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsomntupdattoY-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsomntupdatto(next, fl, args));p-}
-
-int
-vfs_root(
-	s,* Ok,bhv_descs	*bdp,
-	d,* Ok,vnodh		**vpp)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsoroot)p-sEnext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsoroot)(next, vpp));p-}
-
-int
-vfs_s,atvfs(
-	s,* Ok,bhv_descs	*bdp,
-	xfs_statfs_,		*sp,
-	d,* Ok,vnodh		*vp)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsos,atvfsoY-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsos,atvfso(next, sp, vp));p-}
-
-int
-vfs_sync(
-	s,* Ok,bhv_descs	*bdp,
-	int	d	fl,
-	d,* Ok,cred		*cr)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsosync)m-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsosync)(next, fl, cr));p-}
-
-int
-vfs_vget(
-	s,* Ok,bhv_descs	*bdp,
-	d,* Ok,vnodh		**vpp,
-	d,* Ok,fid		*fidp)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsovget)m-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsovget)(next, vpp, fidp));p-}
-
-int
-vfs_dmapiops(
-	s,* Ok,bhv_descs	*bdp,
-	c dHr_t	d	 dHr)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsodmapiops)m-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsodmapiops)(next, adHr));p-}
-
-int
-vfs_quotactl(
-	s,* Ok,bhv_descs	*bdp,
-	int	d	cmd,
-	int	d	id,
-Ec dHr_t	d	 dHr)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsoquotactl)m-	snext =,BHV_NEXT(next);p-sr6dirt ((*bhvtovfsops(next)->vfsoquotactl)(next, cmd, c , adHr));p-}
-
-s,* Ok, nodh -
-vfs_get_inodh(
-	s,* Ok,bhv_descs	*bdp,
-	xfs_ no_n	sino,
-	int	d	fl)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-swHile (! (bhvtovfsops(next))->vfsoget_inodh)m-	snext =,BHV_NEXTct a(next);p-sr6dirt ((*bhvtovfsops(next)->vfsoget_inodh)(next, ino, fl));p-}
-
-tic 
-vfs_init_vnodh(
-	s,* Ok,bhv_descs	*bdp,
-	d,* Ok,vnodh		*vp,
-	d,* Ok,bhv_descs	*bp,
-	int	d	un12B,)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsoinit_vnodh)m-	snext =,BHV_NEXT(next);p-s((*bhvtovfsops(next)->vfsoinit_vnodh)(next, vp, bp, un12B,));p-}
-
-tic 
-vfs_force_deutdown(
-	s,* Ok,bhv_descs	*bdp,
-	int	d	fl,
-	char			*file,
-	int	d	line)m-{
-Ed,* Ok,bhv_descs	*next =,bdp;Y-m-sASSERT(next);p-swHile (! (bhvtovfsops(next))->vfsoforce_deutdown)m-	snext =,BHV_NEXT(next);p-s((*bhvtovfsops(next)->vfsoforce_deutdown)(next, fl, file, line));p-}
-
-tfs_, *
-tfs_a2_HW]ee( tic A)m-{
-Ed,* Ok,vfs		*vfsp;p-m-svfsp =,kmem_za2_HW(dnitof(tfs_,), KM_SLEEP);p-sbhv_H ad_init(VFS_BHVHEAD(vfsp), "vfs");p-Einit_wa  queue_H ad(&vfsp->vfsowa  osync_task);p-sr6dirt vfsp;p-}
-
-tic 
-vfs_dea2_HW]ee(
-Ed,* Ok,vfs		*vfsp)m-{
-Ebhv_H ad_destroy(VFS_BHVHEAD(vfsp));p-skmem_d/ho(vfsp, dnitof(tfs_,));p-}
-
-tic 
-vfs_insertops(
-Ed,* Ok,vfs		*vfsp,
-	d,* Ok,bhv_vfsops	*vfsops)m-{
-Ed,* Ok,bhv_descs	*bdp;Y-m-sbdp =,kmem_a2_HW(dnitof(d,* Ok,bhv_desc), KM_SLEEP);p-sbhv_desc_init(bdp, ct a, vfsp, vfsops);p-sbhv_insert(&vfsp->vfsobh,,bdp);p-}
-
-tic 
-vfs_insertbhv(
-Ed,* Ok,vfs		*vfsp,
-	d,* Ok,bhv_descs	*bdp,
-	d,* Ok,vfsops		*vfsops,p-stic s		*m*/inoY-{p-sbhv_desc_init(bdp, mo/in, vfsp, vfsops);p-sbhv_insert_initicl(&vfsp->vfsobh,,bdp);p-}
-
-tic 
-bhv_r6movg_vfsops(
-Ed,* Ok,vfs		*vfsp,
-	int	d	pos)m-{
-Ed,* Ok,bhv_descs	*bhv;Y-m-sbhv =,bhv_lookup_range(&vfsp->vfsobh,,pos,,pos);p-Eif (!bhv)
-		r6dirt;p-sbhv_r6movg(&vfsp->vfsobh,,bhv);p-skmem_d/ho(bhv, snitof(*bhv));p-}
-
-tic 
-bhv_r6movg_a2__vfsops(
-Ed,* Ok,vfs		*vfsp,
-	int	d	d/hobase)m-{
-Ed,* Ok,xfs_m*/in	*mp;Y-m-sbhv_r6movg_vfsops(vfsp, VFS_POSITION_QM);m-sbhv_r6movg_vfsops(vfsp, VFS_POSITION_DM);p-Eif (!d/hobase)m-		r6dirt;p-smp =,XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfsovfsops));p-EVFS_REMOVEBHV(vfsp, &mp->m_bhv);p-sxfs_m*/in_d/ho(mp, 0);p-}
-
-tic 
-bhv_ilsert_a2__vfsops(
-Ed,* Ok,vfs		*vfsp)m-{
-Ed,* Ok,xfs_m*/in	*mp;Y-m-smp =,xfs_m*/in_init();
-Evfs_insertbhv(vfsp, &mp->m_bhv, &xfsovfsops, mp);
-Evfs_insertdmapi(vfsp);
-Evfs_insertquota(vfspo;p-}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsovfs.h linux-2.4.27-rc4/fs/xfs/linux/xfsovfs.h
--- linux-2.4.26/fs/xfs/linux/xfsovfs.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsovfs.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,208 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--#ifndef __XFS_VFS_H__--# /home __XFS_VFS_H__--
-#include <linux/vfs.h>Y-#include "xfs_fs.h"
-
-s,* Ok,fid;
-s,* Ok,cred;
-s,* Ok,vnodh;p-s,* Ok,statfs;p-s,* Ok,seq_file;p-s,* Ok,sup r_b12B,;p-s,* Ok,xfs_m*/in_args;p-m-Oypedef s,* Ok,statfs xfs_statfs_,;p-m-Oypedef s,* Ok,vfs {I-Eu_int	d	vfsoflag;s4-++c ls -/
-	xfs_fsc _,dsvfs_fsc ;s4-++ile systemAID -/
-	xfs_fsc _,ds*tfs_a2tfsc ;s4-+AnAID fixedAfor-lifo(o++FS -/--Ebhv_H ad_,dsvfs_bh;sE4- H ad o++vfs beigaior-chain,-/--Ed,* Ok,sup r_b12B,	*vfsosup r;s4-+Ldnux,sup rb12B, d,* Okure,-/--Ed,* Ok,task_d,* Ok	*vfsosync_task;p-swa  oqueue_H ad_t	vfsowa  osync_task;p-},vfs_,;p-m-# /home vfs_fbhvdsvfs_bh.bh_firsts4-+1st onSvfs beigaior-chain,-/--m-# /home bhvtovfs(bdp)		( (s,* Ok,vfs *)BHV_VOBJ(bdp) )m-# /home bhvtovfsops(bdp)	( (s,* Ok,vfsops *)BHV_OPS(bdp) )m-# /home VFS_BHVHEAD(vfs)	( &(vfs)->vfsobh )m-# /home VFS_REMOVEBHV(vfs,,bdp)	( bhv_r6movg(VFS_BHVHEAD(vfs),,bdp) )--m-# /home VFS_POSITION_BASE	BHV_POSITION_BASE	4-+chain,bottomr-/--# /home VFS_POSITION_TOP	BHV_POSITION_TOP	4-+chain,topr-/--# /home VFS_POSITION_INVALID	BHV_POSITION_INVALID	4-+invalid,pos. num -/--
-Oypedef enum {I-EVFS_BHV_UNKNOWN,	4-+_tyispecifiBdt-/--EVFS_BHV_XFS,sE4- xfs -/--EVFS_BHV_DM,sE4- d]ea migratISF -/--EVFS_BHV_QM,sE4- quota managIS -/--EVFS_BHV_IO,sE4- IO panv2-/--EVFS_BHV_ENDsE4- Housekeepiig end-of-range(-/
-},vfsobhv_,;p-m-# /home VFS_POSITION_XFS	(BHV_POSITION_BASE)m-# /home VFS_POSITION_DM		(VFS_POSITION_BASE+10)m-# /home VFS_POSITION_QM		(VFS_POSITION_BASE+20)m-# /home VFS_POSITION_IO		(VFS_POSITION_BASE+30)--m-# /home VFS_RDONLY		0x0001E4- recH-only vfs -/--# /home VFS_GRPID		0x0002E4- group-ID assigted fromrdirectory -/
-# /home VFS_DMI			0x0004s4-++ilesystemAhaonOH uDMI,enabled -/
-# /home VFS_UMOUNT		0x0008s4-+unm*/in dn2progress -/--# /home VFS_ENDsE	0x0008s4-+max fc l -/--m-# /home SYNC_ATTR		0x0001E4- sync(attributes -/--# /home SYNC_CLOSE		0x0002E4- close++ile systemAdown -/--# /home SYNC_DELWRI		0x0004s4-+look(at delayed w    s -/--# /home SYNC_WAIT		0x0008s4-+wa  Afor-i/o0to(complete -/--# /home SYNC_BDFLUSH		0x0010s4-+BDFLUSHndsfcalliig -- don'k,b12B, -/--# /home SYNC_FSDATA		0x0020s4-++cushefs d]ea (e.g.,sup rb12B,s) -/--# /home SYNC_REFCACHE		0x0040  4- prume some o++OHeAnfs ref cache -/
-# /home SYNC_REMOUNT		0x0080  4- remo/in recHonly,2nordummynLRs -/--m-# /home IGET_NOALLOC		0x0001E4- vfsoget_inodh+may r6dirt ct a -/--
-Oypedef int	(*vfsom*/in_t)(bhv_desc_t *,
-				s,* Ok,xfs_m*/in_args -, s,* Ok,cred -);Y-Oypedef int	(*vfsoparseargs_t)(bhv_desc_t *, char *,p-				s,* Ok,xfs_m*/in_args -, dl );Y-Oypedef	int	(*vfsoshowargs_t)(bhv_desc_t *, s,* Ok,seq_file -);Y-Oypedef int	(*vfsounm*/in_t)(bhv_desc_t *, dl , s,* Ok,cred -);Y-Oypedef int	(*vfsomntupdatt_t)(bhv_desc_t *, dl  *,p-				s,* Ok,xfs_m*/in_args -);Y-Oypedef int	(*vfsoroot_t)(bhv_desc_t *, s,* Ok,vnodh --);Y-Oypedef int	(*vfsos,atvfs_t)(bhv_desc_t *, xfs_statfs_, *, s,* Ok,vnodh -);Y-Oypedef int	(*vfsosync_t)(bhv_desc_t *, dl , s,* Ok,cred -);Y-Oypedef int	(*vfsovget_t)(bhv_desc_t *, s,* Ok,vnodh --, d,* Ok,fid -);Y-Oypedef int	(*vfsodmapiops_t)(bhv_desc_t *, c dHr_t);Y-Oypedef int	(*vfsoquotactl_t)(bhv_desc_t *, dl , dl , c dHr_t);Y-Oypedef tic s(*vfsoinit_vnodh_t)(bhv_desc_t *,
-				s,* Ok,vnodh -, bhv_desc_t *,,dl );p-Oypedef tic s(*vfsoforce_deutdown_t)(bhv_desc_t *, dl , char *, dl );Y-Oypedef	s,* Ok, nodh - (*vfsoget_inodh_t)(bhv_desc_t *, xfs_ no_n, int);Y-m-Oypedef s,* Ok,vfsops {p-sbhv_positISF_,dsvf_positISF;s4-+beigaior-chain,positISF2-/--Evfsom*/in_t	Evfsom*/in;s4-+mo/in +ile systemA-/--Evfsoparseargs_t	Evfsoparseargs;s4-+parse+mo/in opSISFsA-/--Evfsoshowargs_t	Evfsoshowargs;s4-+unparse+mo/in opSISFsA-/--Evfsounm*/in_t	Evfsounm*/in;s4-+unm*/in +ile systemA-/--Evfsomntupdatt_t	Evfsomntupdatt;s4-+updatt +ile systemAopSISFsA-/--Evfsoroot_t	Evfsoroot;s4-+gen root vnodh -/--Evfsos,atvfs_t	Evfsos,atvfs;s4-++ile systemAs,aSIsyics -/--Evfsosync_t	Evfsosync;s4-++cushefiles -/--Evfsovget_t	Evfsovget;s4-+gen vnodh fromrfid -/--Evfsodmapiops_t	Evfsodmapiops;E4- d]ea migratISF -/--Evfsoquotactl_t	Evfsoquotactl;E4- disk quota -/--Evfsoget_inodh_t	Evfsoget_inodh;s4-+bhvispecific igen -/
-Evfs_init_vnodh_tEvfs_init_vnodh;	4-+initiclize a new vnodh -/--Evfsoforce_deutdown_tEvfsoforce_deutdown;	4-+crasheand birt -/
-},vfsops_t;--
-4-
-68 VFS's.  Op ratBs on vfs d,* Okure,poinStrs (s,artsnak,bhv H ad).
- -/--# /home VHEAD(v)			((v)->vfsofbhv)
-# /home VFS_MOUNT(v,+ma,cr, rv)		((rv) = vfs_m*/in(VHEAD(v),+ma,cr))m-# /home VFS_PARSEARGS(v,+o,ma,f, rv)	((rv) = vfs_parseargs(VHEAD(v),+o,ma,f))m-# /home VFS_SHOWARGS(v,+m, rv)		((rv) = vfs_showargs(VHEAD(v),+m))m-# /home VFS_UNMOUNT(v,+f, cr, rv)	((rv) = vfs_unm*/in(VHEAD(v),+f,cr))m-# /home VFS_MNTUPDATE(v,+fl, args, rv)	((rv) = vfs_mntupdatt(VHEAD(v),+fl, args))m-# /home VFS_ROOT(v,+vpp, rv)		((rv) = vfs_root(VHEAD(v),+vpp))m-# /home VFS_STATVFS(v, sp,vp, rv)	((rv) = vfs_s,atvfs(VHEAD(v),+sp,vp))m-# /home VFS_SYNC(v,+flag,cr, rv)	((rv) = vfs_sync(VHEAD(v),+flag,cr))m-# /home VFS_VGET(v,+vpp,fidp, rv)	((rv) = vfs_vget(VHEAD(v),+vpp,fidp))
-# /home VFS_DMAPIOPS(v,+p, rv)		((rv) = vfs_dmapiops(VHEAD(v),+p))
-# /home VFS_QUOTACTL(v,+c,id,p, rv)	((rv) = vfs_quotactl(VHEAD(v),+c,id,p))
-# /home VFS_GET_INODE(v,+ino, fl)	( vfsoget_inodh(VHEAD(v),+ino,fl) )m-# /home VFS_INIT_VNODE(v,+vp,b,ul)	( vfsoinit_vnodh(VHEAD(v),+vp,b,ul) )m-# /home VFS_FORCE_SHUTDOWN(v,+fl,f,l)	( vfsoforce_deutdown(VHEAD(v),+fl,f,l) )--m-4-
-68 PVFS's.  Op ratBs on beigaior-descriptor-poinStrs.
- -/--# /home PVFS_MOUNT(b,+ma,cr, rv)	((rv) = vfs_m*/in(b,+ma,cr))m-# /home PVFS_PARSEARGS(b,+o,ma,f, rv)	((rv) = vfs_parseargs(b,+o,ma,f))m-# /home PVFS_SHOWARGS(b,+m, rv)		((rv) = vfs_showargs(b,+m))m-# /home PVFS_UNMOUNT(b,+f,cr, rv)	((rv) = vfs_unm*/in(b,+f,cr))m-# /home PVFS_MNTUPDATE(b,+fl, args, rv)	((rv) = vfs_mntupdatt(b,+fl, args))m-# /home PVFS_ROOT(b,+vpp, rv)		((rv) = vfs_root(b,+vpp))m-# /home PVFS_STATVFS(b, sp,vp, rv)	((rv) = vfs_s,atvfs(b,+sp,vp))m-# /home PVFS_SYNC(b,+flag,cr, rv)	((rv) = vfs_sync(b,+flag,cr))m-# /home PVFS_VGET(b,+vpp,fidp, rv)	((rv) = vfs_vget(b,+vpp,fidp))
-# /home PVFS_DMAPIOPS(b,+p, rv)		((rv) = vfs_dmapiops(b,+p))
-# /home PVFS_QUOTACTL(b,+c,id,p, rv)	((rv) = vfs_quotactl(b,+c,id,p))
-# /home PVFS_GET_INODE(b,+ino,fl)	( vfsoget_inodh(b,+ino,fl) )m-# /home PVFS_INIT_VNODE(b,+vp,b2,ul)	( vfsoinit_vnodh(b,+vp,b2,ul) )m-# /home PVFS_FORCE_SHUTDOWN(b,+fl,f,l)	( vfsoforce_deutdown(b,+fl,f,l) )--m-extSrt ily vfs_m*/in(bhv_desc_t *, s,* Ok,xfs_m*/in_args -, s,* Ok,cred -);Y-extSrt ily vfs_parseargs(bhv_desc_t *, char *, s,* Ok,xfs_m*/in_args -, dl );Y-extSrt ily vfs_showargs(bhv_desc_t *, s,* Ok,seq_file -);Y-extSrt ily vfs_unm*/in(bhv_desc_t *, dl , s,* Ok,cred -);Y-extSrt ily vfs_mntupdatt(bhv_desc_t *, dl  *, s,* Ok,xfs_m*/in_args -);Y-extSrt ily vfs_root(bhv_desc_t *, s,* Ok,vnodh --);Y-extSrt ily vfs_s,atvfs(bhv_desc_t *, xfs_statfs_, *, s,* Ok,vnodh -);Y-extSrt ily vfs_sync(bhv_desc_t *, dl , s,* Ok,cred -);Y-extSrt ily vfs_vget(bhv_desc_t *, s,* Ok,vnodh --, d,* Ok,fid -);Y-extSrt ily vfs_dmapiops(bhv_desc_t *, c dHr_t);Y-extSrt ily vfs_quotactl(bhv_desc_t *, dl , dl , c dHr_t);Y-extSrt s,* Ok, nodh -vfsoget_inodh(bhv_desc_t *,,xfs_ no_n, int);Y-extSrt tic Avfsoinit_vnodh(bhv_desc_t *, s,* Ok,vnodh -, bhv_desc_t *,,dl );p-extSrt tic Avfsoforce_deutdown(bhv_desc_t *, dl , char *, dl );Y-m-Oypedef s,* Ok,bhv_vfsops {
-Ed,* Ok,vfsops		bhv_commot;p-stic A*			bhv_custom;p-},bhv_vfsops_,;p-m-# /home vfs_bhv_lookup(v,+id)	( bhv_lookup_range(&(v)->vfsobh,,(id),,(id)) )m-# /home vfs_bhv_custom(b)	( ((bhv_vfsops_, *)BHV_OPS(b))->bhv_custom )m-# /home vfs_bhv_set_custom(b,o)	( (b)->bhv_custom = (tic A*)(o))m-# /home vfs_bhv_clr_custom(b)	( (b)->bhv_custom = ct a )--m-extSrt vfs_, *tfs_a2_HW]ee(tic );Y-extSrt tic Avfs_dea2_HW]ee(vfs_, *);Y-extSrt tic Avfsoinsertops(vfs_t *, bhv_vfsops_, *);Y-extSrt tic Avfsoinsertbhv(vfs_t *, bhv_desc_t *,,vfsops_, *, tic A*);p-
-extSrt tic Abhv_ilsert_a2__vfsops(s,* Ok,vfs *);
-extSrt tic Abhv_r6movg_a2__vfsops(s,* Ok,vfs *,,dl );p-extSrt tic Abhv_r6movg_vfsops(s,* Ok,vfs *,,dl );p-
-#Snd(+	4- __XFS_VFS_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsovnodh.c linux-2.4.27-rc4/fs/xfs/linux/xfsovnodh.c
--- linux-2.4.26/fs/xfs/linux/xfsovnodh.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsovnodh.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,455 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -/--
-#include "xfs.h"
-
-
-uiit64_k,vnogeneratISF;sE4- vnodh generatISF numbIS -/--spin12B,_k,vnumbIS_12B, = SPIN_LOCK_UNLOCKED;--
-4-
-68 DediW]eed vnodh inacSIvg/reclaim sync(semaphores.
- - PrIme numbIS o++hashebuckets siiceA dHress donusedAaonOH ukey.
- -/--# /home NVSYNC                  37m-# /home vptosync(v)             (&vsync[((unsigted long)v) % NVSYNC])--sv_k,vsync[NVSYNC];--
-4-
-68 Translatt stat(2)n.ile Oypes to(vnodh Oypes and vice+versa.
- - Aware o++numeric ordIS o++S_IFMT and vnodh Oype values.
- -/--enum vOype iftovt_tab[] = {p-sVNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,p-sVREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
-};Y-Y-u_shork,vttoif_tab[] = {p-s0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 0, S_IFSOCK
-};Y-Y-
-tic 
-vn_init(tic )p-{I-Eregisct
 sv_k,*svp;I-Eregisct
 ily i;Y-m-sfor-(svp = vsync,n( = 0;n( < NVSYNC;n(++, svp++)m-		init_sv(svp, SV_DEFAULT, "vsy",n();p-}
-
-4-
-68 Clean,a+vnodh o+++ilesystem-specific d]ea and preparend Afor-reuse.
- -/--STATIC ily
-vn_reclaim(
-Ed,* Ok,vnodh	*vp)m-{
-Eint	derror;Y-m-sXFS_STATS_INC(vn_reclaim);
-Evn_Orace_entry(vp, "vn_reclaim",,(inst_, *)__r6dirt_ dHress);p-m-s4-
-s68 Only mak  OH uVOP_RECLAIMfcall+(++tH renarenbeigaiors
-s68 to(call.
-s68/p-Eif (vp->vofbhv)o{p-sdVOP_RECLAIM(vp, error);p-s	if (error)
-			r6dirt -error;Y-s}
-sASSERT(vp->vofbhv == ct a);p-m-sVN_LOCK(vp);
-Evp->vofc l &= (VRECLM|VWAIT);p-EVN_UNLOCK(vp, 0);p-m-svp->voOype = VNON;
-Evp->vofbhv =,ct a;
-
-#ifdef XFS_VNODE_TRACEp-skOrace_d/ho(vp->voOrace);
-Evp->voOrace =,ct a;
-#Snd(+
-
-Er6dirt 0;p-}
-
-STATIC tic 
-vn_wak up(
-Ed,* Ok,vnodh	*vp)m-{
-EVN_LOCK(vp);
-Eif (vp->vofc l & VWAIT)
-		sv_broadcast(tptosync(vp));p-svp->vofc l &= ~(VRECLM|VWAIT|VMODIFIED);p-EVN_UNLOCK(vp, 0);p-}
-
-int
-vnowa  (
-Ed,* Ok,vnodh	*vp)m-{
-EVN_LOCK(vp);
-Eif (vp->vofc l & (VINACT | VRECLM))o{p-sdvp->vofc l |= VWAIT;
-		sv_wa  (tptosync(vp), PINOD, &vp->vo12B,, 0);p-		r6dirt 1;Y-s}
-sVN_UNLOCK(vp, 0);p-Er6dirt 0;p-}
-
-s,* Ok,vnodh -
-vn_initiclize(
-Ed,* Ok,inodh	*inodh)m-{
-Ed,* Ok,vnodh	*vp =,LINVFS_GET_VP(inodh);Y-m-sXFS_STATS_INC(vn_acSIvg);p-EXFS_STATS_INC(vn_a2_HW);p-m-svp->vofc l = VMODIFIED;p-Espin12B,_init(&vp->vo12B,, "vo12B,");p-m-sspino12B,(&vnumbIS_12B,);p-Eif (!++vnogeneratISF)E4- v_numbIS deGuldn'k,be(zero -/
-		vn_generatISF++;p-svp->vonumbIS =,vnogeneratISF;m-sspinoun12B,(&vnumbIS_12B,);p-
-sASSERT(VN_CACHED(vp) == 0);p-m-s4- Initiclize OH ufirst beigaior-and OH ubeigaior-chain,H ad. -/
-	vnobhv_H ad_init(VN_BHV_HEAD(vp), "vnodh");p-m-#ifdef	XFS_VNODE_TRACEp-svp->voOrace =,kOrace_a2_HW(VNODE_TRACE_SIZE, KM_SLEEP);p-spriitk("A2_HW]eed VNODE_TRACEnak,0x%p\n", vp->voOrace);
-#Snd(+	4- XFS_VNODE_TRACE -/--
-	vn_Orace_ex  (tp, "vn_initiclize",,(inst_, *)__r6dirt_ dHress);p-sr6dirt vp;p-}
-
-4-
-68 G6t(  reft
eiceAon,a+vnodh.
- -/--vnodh_t -
-vn_get(
-	s,* Ok,vnodh	*vp,p-stmap_,ds*tmap)m-{
-Ed,* Ok,inodh	*inodh;Y-m-sXFS_STATS_INC(vn_get);p-Einodh =,LINVFS_GET_IP(vp);
-Eif (inodh->i_state & I_FREEING)m-		r6dirt,ct a;
-
-Einodh =,VFS_GET_INODE(vmap->vovfsp, vmap->voino, IGET_NOALLOC);p-Eif (!inodh)s4- Inodh _tyipresentr-/
-		r6dirt,ct a;
-
-E4- We,do+_tyiwant to(cre]ee new inodhs via,vnoget,
-s68 r6dirtiig ct a H rendsfOK.
-s68/p-Eif (inodh->i_state & I_NEW)o{p-sdr6movg_inodh_hash(inodh);Y-		mak _bad_inodh(inodh);Y-		un12B,_new_inodh(inodh);Y-		iput(inodh);Y-		r6dirt,ct a;
-s}
-
-Evn_Orace_ex  (tp, "vn_get",,(inst_, *)__r6dirt_ dHress);p-m-sr6dirt vp;p-}
-
-4-
-68 Revalida   OH uLdnux,inodh fromrOH uvnodh.
- -/--ily
-vn_revalida  (
-Ed,* Ok,vnodh	*vp)m-{
-Ed,* Ok,inodh	*inodh;Y-	vattr_t	Eva;
-Eint	derror;Y-m-svn_Orace_entry(vp, "vn_revalida  ",,(inst_, *)__r6dirt_ dHress);p-sASSERT(vp->vofbhv != ct a);p-m-sva.va_mask =,XFS_AT_STAT|XFS_AT_XFLAGS;p-EVOP_GETATTR(vp, &va, 0, ct a, error);p-sif (!error)o{p-sdinodh =,LINVFS_GET_IP(vp);
-E	inodh->i_rodh	    =,VTTOIF(va.va_Oype) | va.va_modh;Y-		inodh->i_nlink	    =,va.va_nlink;Y-		inodh->i_uid	    =,va.va_uid;
-		inodh->i_gid	    =,va.va_gid;
-		i_snit_w    (inodh,,va.va_snit);
-E	inodh->i_b12B,s	    =,va.va_nb12B,s;
-E	inodh->i_rSIme	    =,va.va_rSIme.tv_sec;
-E	inodh->i_cSIme	    =,va.va_cSIme.tv_sec;
-E	inodh->i_aSIme	    =,va.va_aSIme.tv_sec;
-E	if (va.va_x+c ls &,XFS_XFLAG_IMMUTABLE)
-			inodh->i_+c ls |= S_IMMUTABLE;
-E	e_HWp-			inodh->i_+c ls &= ~S_IMMUTABLE;
-E	if (va.va_x+c ls &,XFS_XFLAG_APPEND)
-			inodh->i_+c ls |= S_APPEND;
-E	e_HWp-			inodh->i_+c ls &= ~S_APPEND;
-E	if (va.va_x+c ls &,XFS_XFLAG_SYNC)
-			inodh->i_+c ls |= S_SYNC;
-E	e_HWp-			inodh->i_+c ls &= ~S_SYNC;
-E	if (va.va_x+c ls &,XFS_XFLAG_NOATIME)
-			inodh->i_+c ls |= S_NOATIME;
-E	e_HWp-			inodh->i_+c ls &= ~S_NOATIME;
-p-sdVUNMODIFY(vp);
-E}m-sr6dirt -error;Y-}
-
-4-
-68 purge a vnodh fromrOH ucache
- - At2OHdonpoinSrOH uvnodhndsfguaranteed SoAhgafRno reft
eices (vn_c*/in == 0)
-68 T/e callerAhaonOo mak  sure,tHatAOHerenarenno ways sometrercGuld
-68 g6t(  igndlt (via,vnoget)Aon,OH uvnodhn(usually strervia,a+mo/in/vfs 12B,).
- -/--vic 
-vn_purge(
-	s,* Ok,vnodh	*vp,p-stmap_,ds*tmap)m-{
-Evn_Orace_entry(vp, "vn_purge",,(inst_, *)__r6dirt_ dHress);p-m-again:m-s4-
-s68 Check wheOH rnvp haonalrecHyubeen(reclaimed siiceAour caller
-s68 sampled its+versISF wHile holdiig a filesystemAcache 12B, tHat
-s68 its+VOP_RECLAIMffunctISF acquires.
-s68/p-EVN_LOCK(vp);
-Eif (vp->vonumbIS != vmap->vonumbIS)o{p-sdVN_UNLOCK(vp, 0);p-E	r6dirt;p-s}p-m-s4-
-s68 Ifnvp is beiig reclaimed or-inacSIv]eed,+wa  A/inilAit,is-inert,
-s68 tHeinproceed.((Can'k,assume,tHatAvnodhndsfacSually r6claimed
-s68 just becauseAOHeAreclaimed fc l dsfasserted -- a vn_a2_HW
-s68 r6claim can,fail.
-s68/p-Eif (vp->vofc l & (VINACT | VRECLM))o{p-sdASSERT(vn_c*/in(vp) == 0);p-sdvp->vofc l |= VWAIT;
-		sv_wa  (tptosync(vp), PINOD, &vp->vo12B,, 0);p-		goto(agait;p-s}p-m-s4-
-s68 AnoOH rnprocessrcGuld igafRraced dn2and gotteinOHdsfvnodh...
-s68/p-Eif (vn_c*/in(vp) > 0)o{p-sdVN_UNLOCK(vp, 0);p-E	r6dirt;p-s}p-m-sXFS_STATS_DEC(vn_acSIvg);p-Evp->vofc l |= VRECLM;p-EVN_UNLOCK(vp, 0);p-m-s4-
-s68 Call+VOP_RECLAIMfand clean,vp. T/e FSYNC_INVAa fc l tells
-s68 vp's filesystemAto(+cusheand invalida   all cache }resources.
-s68 WHeinvn_reclaim r6dirts, vpAdeGuld igafRno priv]ee d]ea,
-s68 eiOH rdin a systemAcache or-attache }to(v_d]ea.
-s68/p-Eif (vn_reclaim(vp) != 0)
-		panic("vn_purge: can_tyireclaim");p-m-s4-
-s68 Wak up0 nytrerwa  iig for-vp to(beAreclaimed.
-s68/p-Evn_wak up(vp);p-}
-
-4-
-68 Add(  reft
eiceAto(a reft
eiceduvnodh.
- -/--s,* Ok,vnodh -
-vn_hold(
-Ed,* Ok,vnodh	*vp)m-{
-Ed,* Ok,inodh	*inodh;Y-m-sXFS_STATS_INC(vn_hold);p-m-sVN_LOCK(vp);
-Einodh =,igrab(LINVFS_GET_IP(vp));p-sASSERT(inodh);Y-	VN_UNLOCK(vp, 0);p-m-sr6dirt vp;p-}
-
-4-
-68  Call+VOP_INACTIVEAon,lastdreft
eice.
- -/--vic 
-vn_rel (
-Ed,* Ok,vnodh	*vp)m-{
-Eint	dvcnt;
-Eint	dcache;Y-m-sXFS_STATS_INC(vn_rele);p-m-sVN_LOCK(vp);
-m-svn_Orace_entry(vp, "vn_rel ",,(inst_, *)__r6dirt_ dHress);p-svcnt =,vnoc*/in(vp);p-m-s4-
-s68 SiiceAw  always g6t(called fromrput_inodh+we know
-s68 tHatAi_c*/in won'k,be(decremSntedAafct
 we
-s68 r6dirt.
-s68/p-Eif (!vcnt)o{p-sd4-
-ss68 As soSF as+we dirt OHdsfSF, notrercan,find us-in,vnoget
-ss68 /inilAwe dirt off VINACT or-VRECLM
-ss68/p-sdvp->vofc l |= VINACT;p-sdVN_UNLOCK(vp, 0);p-p-sd4-
-ss68 Do+_tyimak  OH uVOP_INACTIVEAcall+(++tH re
-ss68 arenno beigaiors-attache }to(OH uvnodhnto(call.
-ss68/p-sdif (vp->vofbhv)p-			VOP_INACTIVE(vp, ct a, cache);p-p-sdVN_LOCK(vp);
-EEif (vp->vofc l & VWAIT)
-			sv_broadcast(tptosync(vp));p-p-sdvp->vofc l &= ~(VINACT|VWAIT|VRECLM|VMODIFIED);p-E}p-m-sVN_UNLOCK(vp, 0);p-m-svn_Orace_ex  (tp, "vn_rel ",,(inst_, *)__r6dirt_ dHress);p-}
-
-4-
-68 FinishAOHeAremoval Sf( +vnodh.
- -/--vic 
-vn_removg(
-Ed,* Ok,vnodh	*vp)m-{
-Etmap_,dstmap;
-
-E4- Mak  sure,we don'k,dorOHdonto(OH usam uvnodhntwice+8/p-Eif (!(vp->vofbhv))m-		r6dirt;p-m-sXFS_STATS_INC(vn_removg);
-Evn_Orace_ex  (tp, "vn_removg",,(inst_, *)__r6dirt_ dHress);p-m-s4-
-s68 Afct
 OH ufo2_Hwiig purge OH uvnodh
-s68 will no longt
 ex st.
-s68/p-EVMAP(tp, tmap);
-Evn_purge(vp, &vmap);
-}Y-Y-
-#ifdef	XFS_VNODE_TRACEp-m-# /home KTRACE_ENTER(tp, tk, s, line,Rra)			\
-skOrace_Snter(	(vp)->voOrace,				\
-4-  068/		(tic A*)(__psiit_t)(vk),		\
-4-  168/		(tic A*)(s),				\
-4-  268/		(tic A*)(__psiit_t) line,		\
-4-  368/		(tic A*)(vnoc*/in(vp)), \
-4-  468/		(tic A*)(ra),				\
-4-  568/		(tic A*)(__psunsigted_t)(vp)->voflag,	\
-4-  668/		(tic A*)(__psiit_t)smp_processor_id(),	\
-4-  768/		(tic A*)(__psiit_t)(currhnt->pid),	\
-4-  868/		(tic A*)__r6dirt_ dHress,		\
-4-  968/		0, 0, 0, 0, 0, 0, 0)--m-4-
-68 Vnodhntraciig codh.
- -/--vic 
-vn_Orace_entry(vnodh_t -tp, char *func,,dlst_, *ra)m-{
-EKTRACE_ENTER(tp, VNODE_KTRACE_ENTRY, func,,0,Rra);p-}
-
-tic 
-vn_Orace_ex  (tnodh_t -tp, char *func,,dlst_, *ra)m-{
-EKTRACE_ENTER(tp, VNODE_KTRACE_EXIT, func,,0,Rra);p-}
-
-tic 
-vn_Orace_hold(tnodh_t -tp, char *file, intrline,,dlst_, *ra)m-{
-EKTRACE_ENTER(tp, VNODE_KTRACE_HOLD, file, line,Rra);p-}
-
-tic 
-vn_Orace_ref(tnodh_t -tp, char *file, intrline,,dlst_, *ra)m-{
-EKTRACE_ENTER(tp, VNODE_KTRACE_REF, file, line,Rra);p-}
-
-tic 
-vn_Orace_rel (tnodh_t -tp, char *file, intrline,,dlst_, *ra)m-{
-EKTRACE_ENTER(tp, VNODE_KTRACE_RELE, file, line,Rra);p-}
-#Snd(+	4- XFS_VNODE_TRACE -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux/xfsovnodh.h linux-2.4.27-rc4/fs/xfs/linux/xfsovnodh.h
--- linux-2.4.26/fs/xfs/linux/xfsovnodh.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux/xfsovnodh.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,650 +0,0 @@
-4-
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d- -
-68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
- - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
-68 publishe }byrOH uF/ho(Software FoundaSISF.p- -
-68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
- - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
- - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p- -
-68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
-68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
-68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp-f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
-68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp-f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p- -
-68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
-68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
-68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p- -
-68 CtrtactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
- - M*/inain,View, CA  94043,nor:
- -
-68 http://www.sgi.comp- -
-68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
- -
-68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
- -
- - PortISFs(Copyright (c) 1989, 1993
- -	T/e Regents o++OHeAUniversIty o+ California.  A2_irights res6rvBd.d- -
-68 Redid,*ibutISF and ush in sourceeand binary forms, winv2or0winvout
-68 modifiW]eISF, are permitted provided tHatAOHeufo2_Hwiig conditISFs
-68 are met:
- - 1. Redid,*ibutISFs o++sourceecodh+mustdrenain,OHeuabovg(copyright
-68   n_tyice, OHdonlist o++conditISFs-and OH ufo2_Hwiig didclaimer.p- - 2. Redid,*ibutISFs in,binary form+mustdreprod Oe,OHeuabovg(copyright
-68   n_tyice, OHdonlist o++conditISFs-and OH ufo2_Hwiig didclaimer dn2OH 
-68   ndocumSntatISF and/p_ oOH rnmaSerials provided winv2OHe did,*ibutISF.p- - 3. NeiOH rdOHeAname o++OHeAUniversIty nordOHeAnames o++its+cont*ibutors
-68   nmay benuse }to(Sndorse+ornpromotenprod Oksfderived fromrOHdonsoftware
-68   nwinvout specific prior-w   teinpermissISF.p- -
-68 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-68 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-68 IMPLIED WARRANTIES OF MERCHANTABILITY(AND FITNESS FOR A fsRTICULAR PURPOSE
-68 ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-68 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-68 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-68 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-68 HOWEVER CAUSED(AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-68 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-68 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED(OF THE POSSIBILITY(OF
-68 SUCH DAMAGE.
- -/--#ifndef __XFS_VNODE_H__--# /home __XFS_VNODE_H__----s,* Ok,uio;
-s,* Ok,file;p-s,* Ok,vattr;p-s,* Ok,xfs_iomap;
-s,* Ok,attrlist_cursor_kert;p-m-4-
-68 Vnodhntypes.  VNON meanon_tntype.
- -/--enum vOype	{ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VFIFO, VBAD, VSOCK };Y-Y-Oypedef xfs_ no_n,vnumbIS_t;
-Oypedef s,* Ok,dentry,vname_t;
-Oypedef bhv_H ad_, vnobhv_H ad_t;--
-4-
-68 MP 12B,iig protocols:
- -	voflag, vovfsp				VN_LOCK/VN_UNLOCK
- -	voOype					r6cH-only or0.s-depSndSnt
-68/m-Oypedef s,* Ok,vnodhn{
-E__u32		voflag;	sE4- vnodh +c ls (see be_Hw) -/--	enum vOype	voOype;	sE4- vnodh Oype -/--Ed,* Ok,vfs	*vovfsp;sE4- ptr0to(coinainiig VFS -/--EvnumbIS_t	vonumbIS;sE4- in-cor uvnodhnnumbIS -/--	vnobhv_H ad_t	vobh;sEs4-+beigaior-H ad -/--Edpin12B,_k	vo12B,;sEs4-+VN_LOCK/VN_UNLOCK -/--Ed,* Ok,inodh	v_inodh;ss4-+Ldnux,inodh -/--#ifdef XFS_VNODE_TRACEp-sd,* Ok,kOrace	*voOrace;ss4-+Orace H ad rns,* Okure,,,,-/--#Snd(+
-} tnodh_t;p-m-# /home v_fbhvds	vobh.bh_firsts       4-++irst beigaior--/--# /home v_fops			vobh.bh_first->bd_ops  4-++irst beigaior-ops */--m-# /home VNODE_POSITION_BASE	BHV_POSITION_BASE	4-+chain,bottomr-/--# /home VNODE_POSITION_TOP	BHV_POSITION_TOP	4-+chain,topr-/--# /home VNODE_POSITION_INVALID	BHV_POSITION_INVALID	4-+invalid,pos. num -/--
-Oypedef enum {I-EVN_BHV_UNKNOWN,		4-+_tyispecifiBdt-/--EVN_BHV_XFS,sE4- xfs -/--EVN_BHV_DM,sE4- d]ea migratISF -/--EVN_BHV_QM,sE4- quota managIS -/--EVN_BHV_IO,sE4- IO panv2-/--EVN_BHV_ENDsE4- Housekeepiig end-of-range(-/
-},vnobhv_,;p-m-# /home VNODE_POSITION_XFS	(VNODE_POSITION_BASE)m-# /home VNODE_POSITION_DM	(VNODE_POSITION_BASE+10)m-# /home VNODE_POSITION_QM	(VNODE_POSITION_BASE+20)m-# /home VNODE_POSITION_IO	(VNODE_POSITION_BASE+30)--m-4-
-68 Macros for-dea2iig winv2OHe beigaior-descriptor-inside o++OHeAvnodh.
- -/--# /home BHV_TO_VNODE(bdp)	((tnodh_t -)BHV_VOBJ(bdp))--# /home BHV_TO_VNODE_ct a(bdp)	((tnodh_t -)BHV_VOBJct a(bdp))--m-# /home VN_BHV_HEAD(vp)			((bhv_H ad_, *)(&((vp)->vobh)))m-# /home vnobhv_H ad_init(bhp,name)	bhv_H ad_init(bhp,name)m-# /home vnobhv_removg(bhp,bdp)		bhv_removg(bhp,bdp)m-# /home vnobhv_lookup(bhp,ops)		bhv_lookup(bhp,ops)m-# /home vnobhv_lookupoun12B,ed(bhp,ops) bhv_lookupoun12B,ed(bhp,ops)p-m-4-
-68 Vnodhnto+Ldnux,inodh mappiig.
- -/--# /home LINVFS_GET_VP(inodh)	((tnodh_t -)list_entry(inodh,,vnodh_t, voinodh))--# /home LINVFS_GET_IP(vp)	(&(vp)->voinodh)m-
-4-
-68 Convert betweeinvnodh Oypes and inodh formaSs (siiceAPOSIX.1
-68  /homes mode word o++statns,* Okure,in,tt
ms o++inodh formaSs).
- -/--extSrt enum vOype	iftovt_tab[];--extSrt u_shork		vttoif_tab[];m-# /home IFTOVT(modh)	(iftovt_tab[((modh) &+S_IFMT) >> 12])m-# /home VTTOIF(indx)	(vttoif_tab[(dl )(indx)])m-# /home MAKEIMODE(indx, modh)	(il )(VTTOIF(indx) | (modh))Y-Y-
-4-
-68 Vnodhn+c ls.
- -/--# /home VINACT	s       0x1E4- vnodh is beiig inacSIv]eed	-/--# /home VRECLM	s       0x2E4- vnodh is beiig reclaimed	-/--# /home VWAIT		       0x4s4-+wa  iig for-VINACT/VRECLM}to(Snd -/--# /home VMODIFIED	       0x8	4- XFS+inodh state possibly sifftrs 8/p-sdsEs4-+to(OH uLdnux,inodh state.	-/--
-4-
-68 Values for-OH uVOP_RWLOCK and VOP_RWUNLOCK +c ls parameter.p- -/
-Oypedef enum vrw12B, {I-EVRWLOCK_NONE,I-EVRWLOCK_READ,I-EVRWLOCK_WRITE,I-EVRWLOCK_WRITE_DIRECT,I-EVRWLOCK_TRY_READ,I-EVRWLOCK_TRY_WRITE
-},vrw12B,_t;--
-4-
-68 R6dirt values for-VOP_INACTIVE.  A r6dirt value o+
- - VN_INACTIVE_NOCACHEn mpliBs tHatAOHeufile systemAbeigaior
-68 hasfdidassoci]eed its+state and bhv_desc_t fromrOH uvnodh.
- -/--# /home	VN_INACTIVE_CACHE	0--# /home	VN_INACTIVE_NOCACHE	1--
-4-
-68 Values for-OH ucmdecodh+giveinOo-VOP_VNODE_CHANGE.
- -/--Oypedef enum vchange({I-EVCHANGE_FLAGS_FRLOCKS		= 0,I-EVCHANGE_FLAGS_ENF_LOCKING	= 1,I-EVCHANGE_FLAGS_TRUNCATED		= 2,I-EVCHANGE_FLAGS_PAGE_DIRTY	= 3,I-EVCHANGE_FLAGS_IOEXCL_COUNT	= 4
-},vchange_t;--
-Y-Oypedef int	(*vop_open_t)(bhv_desc_t *, s,* Ok,cred -);Y-Oypedef ssnit_t (*vop_r ad_,)(bhv_desc_t *, s,* Ok,file -, char *,p-				snit_t, 12ff_t *, dl , s,* Ok,cred -);Y-Oypedef ssnit_t (*vop_w    _,)(bhv_desc_t *, s,* Ok,file -, const char *,p-				snit_t, 12ff_t *, dl , s,* Ok,cred -);Y-Oypedef int	(*vop_ioctl_t)(bhv_desc_t *, s,* Ok, nodh -, s,* Ok,file -,p-				dl , unsigted dl , unsigted long);Y-Oypedef int	(*vop_getattr_t)(bhv_desc_t *, s,* Ok,vattr *, dl ,
-				s,* Ok,cred -);Y-Oypedef int	(*vop_setattr_t)(bhv_desc_t *, s,* Ok,vattr *, dl ,
-				s,* Ok,cred -);Y-Oypedef int	(*vop_access_t)(bhv_desc_t *, dl , s,* Ok,cred -);Y-Oypedef int	(*vop_lookupot)(bhv_desc_t *, vname_t *, vnodh_t --,p-				dl , vnodh_t -, s,* Ok,cred -);Y-Oypedef int	(*vop_cre]eeot)(bhv_desc_t *, vname_t *, s,* Ok,vattr *,p-				vnodh_t --, s,* Ok,cred -);Y-Oypedef int	(*vop_r6movg_t)(bhv_desc_t *, vname_t *, s,* Ok,cred -);Y-Oypedef int	(*vop_link_t)(bhv_desc_t *, vnodh_t -, vname_t *,
-				s,* Ok,cred -);Y-Oypedef int	(*vop_rename_t)(bhv_desc_t *, vname_t *, vnodh_t -, vname_t *,
-				s,* Ok,cred -);Y-Oypedef int	(*vop_mkdir_t)(bhv_desc_t *, vname_t *, s,* Ok,vattr *,p-				vnodh_t --, s,* Ok,cred -);Y-Oypedef int	(*vop_rmdir_t)(bhv_desc_t *, vname_t *, s,* Ok,cred -);Y-Oypedef int	(*vop_readdir_t)(bhv_desc_t *, s,* Ok,uio *, s,* Ok,cred -,p-				dl  -);Y-Oypedef int	(*vop_symlink_t)(bhv_desc_t *, vname_t *, s,* Ok,vattr *,p-				char *, vnodh_t --, s,* Ok,cred -);Y-Oypedef int	(*vop_r6adlink_t)(bhv_desc_t *, s,* Ok,uio *, dl ,
-				s,* Ok,cred -);Y-Oypedef int	(*vop_fsync_t)(bhv_desc_t *, dl , s,* Ok,cred -,
-				xfs_2ff_t,,xfs_2ff_t);Y-Oypedef int	(*vop_inacSIvg_t)(bhv_desc_t *, s,* Ok,cred -);Y-Oypedef int	(*vop_fid2_,)(bhv_desc_t *, s,* Ok,fid -);Y-Oypedef int	(*vop_r6leasg_t)(bhv_desc_t *);Y-Oypedef int	(*vop_rw12B,_t)(bhv_desc_t *, vrw12B,_t);Y-Oypedef tic s(*vop_rwun12B,_t)(bhv_desc_t *, vrw12B,_t);Y-Oypedef	int	(*vop_fr12B,_t)(bhv_desc_t *, dl , s,* Ok,file_12B, *,dl ,
-				xfs_2ff_t,,s,* Ok,cred -);Y-Oypedef int	(*vop_bmap_,)(bhv_desc_t *, xfs_2ff_t,,ssnit_t, dl ,
-				s,* Ok,xfs_iomap *, dl  *);Y-Oypedef int	(*vop_r6claim_t)(bhv_desc_t *);Y-Oypedef int	(*vop_attr_get_t)(bhv_desc_t *, char *, char *, dl  *, dl ,
-				s,* Ok,cred -);Y-Oypedef	int	(*vop_attr_set_t)(bhv_desc_t *, char *, char *, dl , dl ,
-				s,* Ok,cred -);Y-Oypedef	int	(*vop_attr_r6movg_t)(bhv_desc_t *, char *, dl , s,* Ok,cred -);Y-Oypedef	int	(*vop_attr_list_t)(bhv_desc_t *, char *, dl , dl ,
-				s,* Ok,attrlist_cursor_kert *, s,* Ok,cred -);Y-Oypedef tic s(*vop_link_r6movgd_,)(bhv_desc_t *, vnodh_t -, dl );p-Oypedef tic s(*vop_vnodh_change_t)(bhv_desc_t *, vchange_t, __psiit_t);p-Oypedef tic s(*vop_ptossvp_,)(bhv_desc_t *, xfs_2ff_t,,xfs_2ff_t,,dl );p-Oypedef tic s(*vop_p+cushinvalvp_,)(bhv_desc_t *, xfs_2ff_t,,xfs_2ff_t,,dl );p-Oypedef int	(*vop_p+cushvp_,)(bhv_desc_t *, xfs_2ff_t,,xfs_2ff_t,
-				uiit64_k,,dl );p-Oypedef int	(*vop_i+cush_t)(bhv_desc_t *, dl );--
-Y-Oypedef s,* Ok,vnodhops {p-sbhv_positISF_,  vnopositISF;    4-+positISF2winvin beigaior-chain,-/--Evop_open_t	Evop_open;--Evop_r ad_,dsvop_r ad;--Evop_w    _,	Evop_w    ;--Evop_ioctl_t	Evop_ioctl;--Evop_getattr_t	Evop_getattr;--Evop_setattr_t	Evop_setattr;--Evop_access_t	Evop_access;--Evop_lookupot	Evop_lookup;--Evop_cre]eeot	Evop_cre]ee;--Evop_r movg_t	Evop_r movg;--Evop_link_t	Evop_link;--Evop_r name_t	Evop_r name;--Evop_mkdir_t	Evop_mkdir;--Evop_rmdir_t	Evop_rmdir;--Evop_r addir_t	Evop_r addir;--Evop_symlink_t	Evop_symlink;--Evop_r adlink_t	Evop_r adlink;--Evop_fsync_t	Evop_fsync;--Evop_inacSIvg_t	Evop_inacSIvg;--Evop_fid2_,	Evop_fid2;--Evop_rw12B,_t	Evop_rw12B,;--Evop_rwun12B,_t	Evop_rwun12B,;--Evop_fr12B,_t	Evop_fr12B,;--Evop_bmap_,dstop_bmap;--Evop_r claim_t	Evop_r claim;--Evop_attr_get_t	Evop_attr_get;--Evop_attr_set_t	Evop_attr_set;--Evop_attr_r movg_t	vop_attr_r movg;--Evop_attr_list_t	Evop_attr_list;--Evop_link_r6movgd_,Evop_link_r6movgd;--Evop_vnodh_change_tEvop_vnodh_change;--Evop_ptossvp_,	Evop_tosspages;--Evop_p+cushinvalvp_,Evop_fcushinval_pages;--Evop_p+cushvp_,	Evop_+cush_pages;--Evop_r6leasg_t	Evop_r6leasg;--Evop_i+cush_t	Evop_i+cush;
-} tnodhops_t;--
-4-
-68 VOP's.
- -/--# /home _VOP_(op, tp)	(*((tnodhops_, *)(vp)->vofops)->op)--m-# /home VOP_READ(vp,file,buf,snit,2ffset,io+c ls,cr,rv)			\
-srv =,_VOP_(vop_r ad, tp)((vp)->vofbhv,file,buf,snit,2ffset,io+c ls,cr)m-# /home VOP_WRITE(vp,file,buf,snit,2ffset,io+c ls,cr,rv)		\
-srv =,_VOP_(vop_w    , tp)((vp)->vofbhv,file,buf,snit,2ffset,io+c ls,cr)m-# /home VOP_BMAP(tp,of,sz,rw,b,n,rv)					\
-srv =,_VOP_(vop_bmap, tp)((vp)->vofbhv,of,sz,rw,b,n)m-# /home VOP_OPEN(tp, cr, rv)						\
-srv =,_VOP_(vop_open, tp)((vp)->vofbhv, cr)m-# /home VOP_GETATTR(vp, vap, f, cr, rv)					\
-srv =,_VOP_(vop_getattr, tp)((vp)->vofbhv, vap, f, cr)--# /home	VOP_SETATTR(vp, vap, f, cr, rv)					\
-srv =,_VOP_(vop_setattr, tp)((vp)->vofbhv, vap, f, cr)--# /home	VOP_ACCESS(vp, modh,,cr, rv)					\
-srv =,_VOP_(vop_access, tp)((vp)->vofbhv, modh,,cr)--# /home	VOP_LOOKUP(tp,d,vpp,f,rdir,cr,rv)				\
-srv =,_VOP_(vop_lookup, tp)((vp)->vofbhv,d,vpp,f,rdir,cr)m-# /home VOP_CREATE(dtp,d,vap,vpp,cr,rv)					\
-srv =,_VOP_(vop_cre]ee, dtp)((dvp)->vofbhv,d,vap,vpp,cr)m-# /home VOP_REMOVE(dtp,d,cr,rv)						\
-srv =,_VOP_(vop_r movg, dtp)((dvp)->vofbhv,d,cr)--# /home	VOP_LINK(tdtp,ftp,d,cr,rv)					\
-srv =,_VOP_(vop_link, tdtp)((tdvp)->vofbhv,ftp,d,cr)--# /home	VOP_RENAME(ftp,fnm,tdtp,tnm,cr,rv)				\
-srv =,_VOP_(vop_r name, ftp)((fvp)->vofbhv,fnm,tdtp,tnm,cr)--# /home	VOP_MKDIR(dp,d,vap,vpp,cr,rv)					\
-srv =,_VOP_(vop_mkdir, dp)((dp)->vofbhv,d,vap,vpp,cr)m-# /home	VOP_RMDIR(dp,d,cr,rv)						\
-srv =,_VOP_(vop_rmdir, dp)((dp)->vofbhv,d,cr)--# /home	VOP_READDIR(tp,uiop,cr,eofp,rv)					\
-srv =,_VOP_(vop_r addir, tp)((vp)->vofbhv,uiop,cr,eofp)--# /home	VOP_SYMLINK(dtp,d,vap,tnm,vpp,cr,rv)				\
-srv =,_VOP_(vop_symlink, dtp) ((dvp)->vofbhv,d,vap,tnm,vpp,cr)--# /home	VOP_READLINK(tp,uiop,fl,cr,rv)					\
-srv =,_VOP_(vop_r adlink, tp)((vp)->vofbhv,uiop,fl,cr)--# /home	VOP_FSYNC(vp,f,cr,b,e,rv)					\
-srv =,_VOP_(vop_fsync,ntp)((vp)->vofbhv,f,cr,b,e)m-# /home VOP_INACTIVE(vp, cr, rv)					\
-srv =,_VOP_(vop_inacSIvg, tp)((vp)->vofbhv, cr)m-# /home VOP_RELEASE(vp, rv)						\
-srv =,_VOP_(vop_r leasg, tp)((vp)->vofbhv)m-# /home VOP_FID2(vp, fidp, rv)						\
-srv =,_VOP_(vop_fid2, tp)((vp)->vofbhv, fidp)m-# /home VOP_RWLOCK(vp,i)						\
-s(tic )_VOP_(vop_rw12B,, tp)((vp)->vofbhv, i)m-# /home VOP_RWLOCK_TRY(vp,i)						\
-s_VOP_(vop_rw12B,, tp)((vp)->vofbhv, i)m-# /home VOP_RWUNLOCK(vp,i)						\
-s(tic )_VOP_(vop_rwun12B,, tp)((vp)->vofbhv, i)m-# /home VOP_FRLOCK(vp,c,fl,+c ls,2ffset,fr,rv)				\
-srv =,_VOP_(vop_fr12B,, tp)((vp)->vofbhv,c,fl,+c ls,2ffset,fr)m-# /home VOP_RECLAIM(vp, rv)						\
-srv =,_VOP_(vop_r claim, tp)((vp)->vofbhv)m-# /home VOP_ATTR_GET(vp, name, val, vallenp,+fl, cred, rv)		\
-srv =,_VOP_(vop_attr_get, tp)((vp)->vofbhv,name,val,vallenp,fl,cred)--# /home	VOP_ATTR_SET(vp, name, val, vallen,+fl, cred, rv)		\
-srv =,_VOP_(vop_attr_set, tp)((vp)->vofbhv,name,val,vallen,fl,cred)--# /home	VOP_ATTR_REMOVE(vp, name, +c ls, cred, rv)			\
-srv =,_VOP_(vop_attr_r movg, tp)((vp)->vofbhv,name,+c ls,cred)--# /home	VOP_ATTR_LIST(vp, buf, buflen,+fl, cursor, cred, rv)		\
-srv =,_VOP_(vop_attr_list, tp)((vp)->vofbhv,buf,buflen,fl,cursor,cred)--# /home VOP_LINK_REMOVED(vp, dtp, linkzero)				\
-s(tic )_VOP_(vop_link_r6movgd, tp)((vp)->vofbhv, dtp, linkzero)--# /home VOP_VNODE_CHANGE(vp, cmd, val)					\
-s(tic )_VOP_(vop_vnodh_change, tp)((vp)->vofbhv,cmd,val)
-4-
-68 ThesenarenpageAcache functISFs tHatAnow go(OHru VOPs.
- - 'last' parameter donunusedAand lefn dn2for-IRIX(compatibility
- -/--# /home VOP_TOSS_PAGES(vp, first, last, fiopt)				\
-s_VOP_(vop_tosspages, tp)((vp)->vofbhv,first, last, fiopt)
-4-
-68 'last' parameter donunusedAand lefn dn2for-IRIX(compatibility
- -/--# /home VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt)			\
-s_VOP_(vop_fcushinval_pages, tp)((vp)->vofbhv,first,last,fiopt)
-4-
-68 'last' parameter donunusedAand lefn dn2for-IRIX(compatibility
- -/--# /home VOP_FLUSH_PAGES(vp, first, last, fc ls, fiopt, rv)		\
-srv =,_VOP_(vop_+cush_pages, tp)((vp)->vofbhv,first,last,fc ls,fiopt)
-# /home VOP_IOCTL(vp, inodh,,filp,+fl, cmd, arg, rv)			\
-srv =,_VOP_(vop_ioctl, tp)((vp)->vofbhv,inodh,filp,fl,cmd,arg)
-# /home VOP_IFLUSH(vp, fc ls, rv)					\
-srv =,_VOP_(vop_i+cush, tp)((vp)->vofbhv, fc ls)m-
-4-
-68 Fc ls for-read/w     calls -usam uvalues as-IRIX
- -/--# /home IO_ISDIRECT	0x00004Es4-+bypassnpageAcache -/--# /home IO_INVIS	0x00020sE4- don'k,updatt  nodh SImestamps */--# /home IO_ISLOCKED	0x00800sE4- don'k,do  nodh 12B,iig -/--
-4-
-68 Fc ls for-VOP_IFLUSH call
- -/--# /home FLUSH_SYNC		1s4-+wa   for-+cusheto(complete	-/--# /home FLUSH_INODE		2s4-++cusheOHe- nodh itself	-/--# /home FLUSH_LOG		4s4-+force OH ulastdlog entry forp-sdsEs68 tHis-inodh out to(disk	-/--
-4-
-68 Fcush/Invalida   opSISFsAfor-VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGESAand
- -	VOP_FLUSH_PAGES.
- -/--# /home FI_NONEsEs0	4-+_tne -/--# /home FI_REMAPF		1s4-+Do(a remapf prior-to(OH uoperatISF -/--# /home FI_REMAPF_LOCKED	2s4-+Do(a remapf prior-to(OH uoperatISF.p-sdsEs6  Preveit VM access-to(OH upages /inilp-sdsEs6  OH uoperatISF completes. -/--
-4-
-68 Vnodhnattributes.  va_mask indiW]ees tHoshnattributesrOH ucaller
-68 wants to(set or0exOract.
- -/--Oypedef s,* Ok,vattr {
-Eint	dva_mask;s4-+bit-mask Sf( ttributesrpresentr-/
-	enum vOype	vaoOype;	4- vnodh Oype (for-cre]ee) -/--	modh_t	Eva_modh;s4-++ile access-mode and Oype -/--Enlink_t	Eva_nlink;	4-+_umbIS o++reft
eices to(+ile -/--Euid_t	Eva_uid;sE4- ownIS user ddt-/--Egid_t	Eva_gid;sE4- ownIS group ddt-/--Exfs_ no_nEva_nodeid;s4-++ile ddt-/--Exfs_2ff_t	va_snit;s4-++ile size in bytes -/--Eu_long	Eva_b12B,snit;s4-+b12B,snitrpreft
red for-i/o -/--Ed,* Ok,SImespec	va_aSIme;s4-+SIme o++lastdaccess--/--Ed,* Ok,SImespec	va_mSIme;s4-+SIme o++lastdmodifiW]eISF--/--Ed,* Ok,SImespec	va_cSIme;s4-+SIme +ile changed -/--Eu_int	dva_geF;sE4- generatISF numbIS o+++ilet-/--Exfs_dev_t	va_rdev;E4- device+OH uspecial++iletrepresents--/--E__iit64_k	va_nb12B,s;	4-+_umbIS o++b12B,s a2_HW]eed -/--Eu_long	Eva_x+c ls;	4-+random0exOSndSd++ilet+c ls -/--Eu_long	Eva_exOsnit;s4-++ile exOSnt size -/--Eu_long	Eva_nexOSnts;	4-+_umbIS o++exOSnts dn2file -/--Eu_long	Eva_anexOSnts;	4-+_umbIS o++attr exOSnts dn2file -/--Eint	dva_projid;s4-+projece ddt-/--} vattr_t;--
-4-
-68 setattr or0getattr( ttributes
- -/--# /home XFS_AT_TYPEsE0x00000001--# /home XFS_AT_MODE		0x00000002--# /home XFS_AT_UID		0x00000004--# /home XFS_AT_GID		0x00000008--# /home XFS_AT_FSID		0x00000010--# /home XFS_AT_NODEID		0x00000020--# /home XFS_AT_NLINK		0x00000040--# /home XFS_AT_SIZE		0x00000080--# /home XFS_AT_ATIME		0x00000100--# /home XFS_AT_MTIME		0x00000200--# /home XFS_AT_CTIME		0x00000400--# /home XFS_AT_RDEV		0x00000800--# /home XFS_AT_BLKSIZE		0x00001000--# /home XFS_AT_NBLOCKS		0x00002000--# /home XFS_AT_VCODE		0x00004000--# /home XFS_AT_MAC		0x00008000--# /home XFS_AT_UPDATIME		0x00010000--# /home XFS_AT_UPDMTIME		0x00020000--# /home XFS_AT_UPDCTIME		0x00040000--# /home XFS_AT_ACL		0x00080000--# /home XFS_AT_CAP		0x00100000--# /home XFS_AT_INF		0x00200000--# /home XFS_AT_XFLAGS		0x00400000--# /home XFS_AT_EXTSIZE		0x00800000--# /home XFS_AT_NEXTENTS		0x01000000--# /home XFS_AT_ANEXTENTS	0x02000000--# /home XFS_AT_PROJID		0x04000000--# /home XFS_AT_SIZE_NOPERM	0x08000000--# /home XFS_AT_GENCOUNT		0x10000000--m-# /home XFS_AT_ALL	(XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
-s	XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
-s	XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
-s	XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|XFS_AT_MAC|\
-s	XFS_AT_ACL|XFS_AT_CAP|XFS_AT_INF|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|\
-s	XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_PROJID|XFS_AT_GENCOUNT)--m-# /home XFS_AT_STAT	(XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
-s	XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
-s	XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
-s	XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_PROJID)--m-# /home XFS_AT_TIMES	(XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME)--m-# /home XFS_AT_UPDTIMES	(XFS_AT_UPDATIME|XFS_AT_UPDMTIME|XFS_AT_UPDCTIME)--m-# /home XFS_AT_NOSET	(XFS_AT_NLINK|XFS_AT_RDEV|XFS_AT_FSID|XFS_AT_NODEID|\
-s	XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
-s	XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)--m-4-
-68  Modes.
- -/--# /home VSUID	S_ISUID		/8 set user ddtSF executISF -/--# /home VSGID	S_ISGID		/8 set group ddtSF executISF -/--# /home VSVTX	S_ISVTX		/8 sgafRswappe }texO eveinafct
 ush -/--# /home VREAD	S_IRUSR		/8 r ad, w    , executenpermissISFs */--# /home VWRITE	S_IWUSR--# /home VEXEC	S_IXUSR--m-# /home MODEMASK+S_IALLUGO	/8 mode bits+pcusnpermissISF bits+-/--
-4-
-68 Check wheOH rnmandaSory file 12B,iig is-enablBd.d- -/--# /home MANDLOCK(vp, modh)	\
-s((vp)->voOype == VREG && ((modh) &+(VSGID|(VEXEC>>3))) == VSGID)--m-extSrt vic svn_init(tic );Y-extSrt ily	vnowa  (s,* Ok,vnodh -);Y-extSrt vnodh_t	*vn_initiclize(s,* Ok, nodh -);--
-4-
-68 Acquiriig and invalida iig vnodhs:
- -
-68Eif (vn_get(vp, versISF, 0))
-68		...;
- -	vn_purge(vp, versISF);p- -
-68 vn_get and vn_purge+mustdbe(called winv2tmap_, argumSnts, sampled
-68 wHile a 12B, tHatrOH uvnodh's+VOP_RECLAIMffunctISF acquires,is
-68 held, to(Snsure,tHatAOHe,vnodh sampled winv2OHe 12B, held,isn't
-68 recycled (VOP_RECLAIMed) or-dea2_HW]eed betweeinOHeAreleasg o++OHeA12B,
-68( nd OH usubsequSnt vn_get or-vn_purge.d- -/--
-4-
-68 vnodh_map s,* Okures _must_nmaSch-vn_epoch and vnodh s,* Okure,sizes.
- -/--Oypedef s,* Ok,vnodh_map {
-Etfs_,ds*tovfsp;
-EvnumbIS_t	vonumbIS;sE4- in-cor uvnodhnnumbIS -/--	xfs_ no_nEv_ no;sEs4-+ nodh #	-/--} vmap_,;p-m-# /home VMAP(tp, tmap)	{(vmap).vovfsp	 = (tp)->vovfsp,	\
-s		 (vmap).vonumbIS =,(tp)->vonumbIS,	\
-s		 (vmap).vo no	 = (tp)->vo nodh.i_ no; }--m-extSrt vic svn_purge(s,* Ok,vnodh -,2tmap_, -);Y-extSrt vnodh_t	*vn_get(s,* Ok,vnodh -,2tmap_, -);Y-extSrt ily	vnorevalida  (s,* Ok,vnodh -);Y-extSrt vic svn_removg(s,* Ok,vnodh -);Y-
-s,a ic illine dl  vnoc*/in(s,* Ok,vnodh -vp)m-{
-Er6dirt aSomic_r ad(&LINVFS_GET_IP(vp)->i_c*/in);p-}
-
-4-
-68 Vnodhnreft
eiceAc*/iniig functISFs (and macros for-compatibility).
- -/--extSrt vnodh_t	*vn_hold(s,* Ok,vnodh -);Y-extSrt vic svn_relg(s,* Ok,vnodh -);Y-
-#if  /homed(XFS_VNODE_TRACE)m-# /home VN_HOLD(vp)		\
-s((vic )vn_hold(vp),	\
-s  vnoOrace_hold(tp, __FILE__, __LINE__, (inst_, *)__r6dirt_ dHress))m-# /home VN_RELE(vp)		\
-s  (vn_Orace_rel (tp, __FILE__, __LINE__, (inst_, *)__r6dirt_ dHress), \
-s6  iput(LINVFS_GET_IP(vp)))m-#e_HWp-# /home VN_HOLD(vp)		((vic )vn_hold(vp))m-# /home VN_RELE(vp)		(iput(LINVFS_GET_IP(vp)))m-#end(+
-
-4-
-68 Vnam uigndliig macros.
- -/--# /home VNAME(dentry)		((char *) (dentry)->d_nam .name)m-# /home VNAMELEN(dentry)	((dentry)->d_nam .len)m-# /home VNAME_TO_VNODE(dentry)	(LINVFS_GET_VP((dentry)->d_inodh))--
-4-
-68 Vnodhndpin12B,nmanipulaSISF.p- -/--# /home VN_LOCK(vp)		mutex_dpin12B,(&(vp)->vo12B,)--# /home VN_UNLOCK(vp, s)	mutex_dpinun12B,(&(vp)->vo12B,, s)--# /home VN_FLAGSET(vp,b)svn_+c lset(vp,b)--# /home VN_FLAGCLR(vp,b)svn_+c lclr(vp,b)--
-s,a ic __iiline__ vic  vn_+c lset(s,* Ok,vnodh -vp, uiitt+c l)m-{
-Edpino12B,(&vp->vo12B,);p-Evp->vofc l |= flag;
-sspinoun12B,(&vp->vo12B,);p-}--
-s,a ic __iiline__ vic  vn_+c lclr(s,* Ok,vnodh -vp, uiitt+c l)m-{
-Edpino12B,(&vp->vo12B,);p-Evp->vofc l &= ~flag;
-sspinoun12B,(&vp->vo12B,);p-}--
-4-
-68 Updatt modify/access/change(SImesAon,OH uvnodhp- -/--# /home VN_MTIMESET(vp, tvp)	\
-s	(LINVFS_GET_IP(vp)->i_rSIme = (__iit32_,)(tvp)->tv_sec)--# /home VN_ATIMESET(vp, tvp)	\
-s	(LINVFS_GET_IP(vp)->i_aSIme = (__iit32_,)(tvp)->tv_sec)--# /home VN_CTIMESET(vp, tvp)	\
-s	(LINVFS_GET_IP(vp)->i_cSIme = (__iit32_,)(tvp)->tv_sec)--
-4-
-68 SomenusefulrprediW]ees.
- -/--# /home	VN_MAPPED(vp)	((LINVFS_GET_IP(vp)->i_rappiig->i_rmap != ct a) || \
-s		 (LINVFS_GET_IP(vp)->i_rappiig->i_rmap_shared != ct a))--# /home	VN_CACHED(vp)	(LINVFS_GET_IP(vp)->i_rappiig->nrpages)--# /home VN_DIRTY(vp)	(!list_empty(&(LINVFS_GET_IP(vp)->i_dirty_d]ea_bufftrs)))m-# /home VMODIFY(vp)	VN_FLAGSET(vp, VMODIFIED)m-# /home VUNMODIFY(vp)	VN_FLAGCLR(vp, VMODIFIED)m-
-4-
-68 Fc ls Oo-VOP_SETATTR/VOP_GETATTR.
- -/--# /home	ATTR_UTIME	0x01	4-+_tn- /hault uSIme(2)nrequSst -/--# /home	ATTR_DMI	0x08	4-+invoW]eISF-fromra DMIffunctISF -/--# /home	ATTR_LAZY	0x80	/8 set/get attributesrlazily -/--# /home	ATTR_NONBLOCK	0x100	/8 r dirt EAGAIN+(++operatISF wGuld b12B, */--
-4-
-68 Fc ls Oo-VOP_FSYNC and VOP_RECLAIM.
- -/--# /home FSYNC_NOWAIT	0	/8 asynchronousn+cushe-/--# /home FSYNC_WAIT	0x1E4- synchronousn+sync or0.orced r6claim -/--# /home FSYNC_INVAL	0x2E4- +cusheand invalida   cache }d]ea -/--# /home FSYNC_DATA	0x4s4-+synchronousn+sync of}d]ea only */--
-4-
-68 Trackiig vnodh acSIvity.
- -/--#if  /homed(XFS_VNODE_TRACE)m---# /home	VNODE_TRACE_SIZE	16		4-+_umbIS o++Orace entries -/--# /home	VNODE_KTRACE_ENTRY	1--# /home	VNODE_KTRACE_EXIT	2--# /home	VNODE_KTRACE_HOLD	3--# /home	VNODE_KTRACE_REF	4--# /home	VNODE_KTRACE_RELE	5--m-extSrt vic  vnoOrace_entry(s,* Ok,vnodh -,2char *, dlst_, *);m-extSrt vic  vnoOrace_ex  (s,* Ok,vnodh -,2char *, dlst_, *);m-extSrt vic  vnoOrace_hold(s,* Ok,vnodh -, char *, dl , dlst_, *);m-extSrt vic  vnoOrace_ref(s,* Ok,vnodh -, char *, dl , dlst_, *);m-extSrt vic  vnoOrace_relg(s,* Ok,vnodh -, char *, dl , dlst_, *);m---# /home	VN_TRACE(vp)		\
-svn_Orace_ref(tp, __FILE__, __LINE__, (inst_, *)__r6dirt_ dHress)m-#e_HWp-# /homesvn_Orace_entry(a,b,c)--# /homeEvn_Orace_ex  (a,b,c)--# /homeEvn_Orace_hold(a,b,c,d)--# /homeEvn_Orace_ref(a,b,c,d)--# /homeEvn_Orace_relg(a,b,c,d)--# /homeEVN_TRACE(vp)m-#end(+
-
-#Snd(+	4- __XFS_VNODE_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/Mak file 1inux-2.4.27-rc4/fs/xfs/linux-2.4/Mak file
--- linux-2.4.26/fs/xfs/linux-2.4/Mak file	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/Mak file	2004-07-30 16:24:42.000000000 +0000
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+#
+# T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+# undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+# publishe }byrOH uF/ho(Software FoundaSISF.p+#
+# T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+# WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+# MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+#
+# FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+# d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+# oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+# oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+#  ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+# oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+#
+# YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+# winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+# Temple Place,- Su    330, Boston MA 02111-1307, USA.p+#
+# CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+# M*/inain,View, CA  94043,nor:
+#
+# http://www.sgi.comp+#
+# For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+#
+# http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+#
+# Mak file for-XFS+SF Ldnux.p+
+EXTRA_CFLAGS += -I.. -I. -funsigted-charp+
+ifeq ($(CONFIG_XFS_DEBUG),y)
+	EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG
+	EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
+end(+
+ifeq ($(CONFIG_XFS_TRACE),y)
+	EXTRA_CFLAGS += -DXFS_ALLOC_TRACEp+	EXTRA_CFLAGS += -DXFS_ATTR_TRACEp+	EXTRA_CFLAGS += -DXFS_BLI_TRACEp+	EXTRA_CFLAGS += -DXFS_BMAP_TRACEp+	EXTRA_CFLAGS += -DXFS_BMBT_TRACEp+	EXTRA_CFLAGS += -DXFS_DIR_TRACEp+	EXTRA_CFLAGS += -DXFS_DQUOT_TRACEp+	EXTRA_CFLAGS += -DXFS_ILOCK_TRACEp+	EXTRA_CFLAGS += -DXFS_LOG_TRACEp+	EXTRA_CFLAGS += -DXFS_RW_TRACEp+	EXTRA_CFLAGS += -DXFS_DIR2_TRACEp+	EXTRA_CFLAGS += -DPAGEBUF_TRACEp+	# EXTRA_CFLAGS += -DXFS_VNODE_TRACEp+end(+
+
+O_TARGET			:= linux_xfs.o
+ifneq ($(MAKECMDGOALS),modules_ nstall)
+  obj-m				:= $(O_TARGET)p+end(+
+
+obj-$(CONFIG_PROC_FS)		+= xfs_s,a s.o
+obj-$(CONFIG_SYSCTL)		+= xfs_sysctl.o
+obj-y				+= xfs_aops.o \p+	sEs6  xfs_.ile.o \p+	sEs6  xfs_.s_subr.o \p+	sEs6  xfs_globals.o \p+	sEs6  xfs_ioctl.o \p+	sEs6  xfs_iops.o \p+	sEs6  xfs_lrw.o \p+	sEs6  xfs_super.o \p+	sEs6  xfs_vfs.o \p+	sEs6  xfs_vnodh.o	\p+	sEs6  xfs_buf.o \p+	sEs6  mr12B,.o \p+	sEs6  kmem.o
+
+includh $(TOPDIR)/Rules.mak -diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/kmem.c linux-2.4.27-rc4/fs/xfs/linux-2.4/kmem.c
--- linux-2.4.26/fs/xfs/linux-2.4/kmem.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/kmem.c	2004-07-30 16:26:26.000000000 +0000
@@ -0,0 +1,185 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+
+#includh <linux/sche .h>
+#includh <linux/mm.h>
+#includh <linux/vma2_HW.h>
+#includh <linux/swap.h>
+
+#includh "SIme.h"
+#includh "kmem.h"
+
+# /home MAX_VMALLOCS	6
+# /home MAX_SLAB_SIZE	0x20000-+# /home MAX_SHAKE	8
+
+s,a ic kmem_shake_func_t	shake_list[MAX_SHAKE];
+s,a ic DECLARE_MUTEX(shake_sem);
+
+4-
+68 Old-school memory shakiig for-vanilla 2.4 kertels (whicvp+f* igafRno VM shake(callback/regid,*aSISF infras,* Okure).
+ -/-+
+kmem_shaker_t
+kmem_shake_regid,er(kmem_shake_func_t sfunc)p+{p+	ily	i;
+
+	down(&shake_sem);
+	for-(i = 0;+( < MAX_SHAKE;+(++)o{p+EEif (shake_list[i] == ct a) {p+EE	shake_list[i] = sfunc;p+EE	break;p+EE}p+E}p+Eif (i == MAX_SHAKE)
+		BUG();
+	up(&shake_sem);
+
+	r dirt (kmem_shaker_t)sfunc;p+}
+
+tic 
+kmem_shake_dISegid,er(kmem_shaker_t sfunc)p+{p+	ily	i;
+
+	down(&shake_sem);
+	for-(i = 0;+( < MAX_SHAKE;+(++)o{p+EEif (shake_list[i] == (kmem_shake_func_t)sfunc)p+EE	break;p+E}p+Eif (i == MAX_SHAKE)
+		BUG();
+	for-(;+( < MAX_SHAKE,- 1;+(++)o{p+EEshake_list[i] = shake_list[i+1];p+E}p+Eshake_list[i] = ct a;
+	up(&shake_sem);
+}
+
+s,a ic __iiline__ vic  kmem_shake(vic )p+{p+	ily	i;
+
+	down(&shake_sem);
+	for-(i = 0;+( < MAX_SHAKE && shake_list[i];+(++)p+EE(*shake_list[i])(0, 0);p+	up(&shake_sem);
+	delay(10);p+}
+
+tic  -
+kmem_a2_HW(snit_t snit, iitt+c ls)p+{p+	ily	r dries = 0, l+c ls = kmem_+c ls_convert(+c ls);
+	vic s*ptr;-+
+	doo{p+EEif (size < MAX_SLAB_SIZE || r dries > MAX_VMALLOCS)p+EE	ptr0= kma2_HW(snit, l+c ls);
+		e_HWp+EE	ptr0= __vma2_HW(snit, l+c ls, PAGE_KERNEL);
+		if (ptr0|| (+c ls &+(KM_MAYFAIL|KM_NOSLEEP)))m+EE	r dirt ptr;-+		kmem_shake();
+		if (!(++r dries % 100))m+EE	priitk(KERN_ERR "possible-dead12B, in,%s (modh:0x%x)\n",p+	sEs	__FUNCTION__, l+c ls);
+	} wHile (1);p+}
+
+tic  -
+kmem_za2_HW(snit_t snit, iitt+c ls)p+{p+	vic s*ptr;-+
+	ptr0= kmem_a2_HW(snit, fc ls);p+Eif (ptr)m+EEmemset((char *)ptr, 0, (int)snit);p+Er dirt ptr;-+}
+
+tic 
+kmem_d/ho(tic A*ptr, snit_t snit)p+{p+	if (((unsigted long)ptr0< VMALLOC_START) ||p+	    ((unsigted long)ptr0>= VMALLOC_END))o{p+EEkd/ho(ptr);
+	} e_HWo{p+EEvd/ho(ptr);
+	}p+}
+
+tic  -
+kmem_rea2_HW(tic A*ptr, snit_t newsnit, snit_t oldsnit, iitt+c ls)p+{p+	vic s*new;-+
+	new0= kmem_a2_HW(newsnit, fc ls);p+Eif (ptr)o{p+EEif (new)m+EE	memcpy(new, ptr,p+	sEs((oldsnit0< newsnit) ? oldsnit : newsnit));-+		kmem_d/ho(ptr, oldsnit);
+	}p+Er dirt new;-+}
+
+tic  -
+kmem_zone_a2_HW(kmem_zone_t *zone, iitt+c ls)p+{p+	ily	r dries = 0, l+c ls = kmem_+c ls_convert(+c ls);
+	vic s*ptr;-+
+	doo{p+EEptr0= kmem_cache_a2_HW(zone, l+c ls);
+		if (ptr0|| (+c ls &+(KM_MAYFAIL|KM_NOSLEEP)))m+EE	r dirt ptr;-+		kmem_shake();
+		if (!(++r dries % 100))m+EE	priitk(KERN_ERR "possible-dead12B, in,%s (modh:0x%x)\n",p+	sEs	__FUNCTION__, l+c ls);
+	} wHile (1);p+}
+
+tic  -
+kmem_zone_za2_HW(kmem_zone_t *zone, iitt+c ls)p+{p+	vic s*ptr;-+
+	ptr0= kmem_zone_a2_HW(zone, fc ls);p+Eif (ptr)m+EEmemset((char *)ptr, 0, kmem_cache_snit(zone));p+Er dirt ptr;-+}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/kmem.h linux-2.4.27-rc4/fs/xfs/linux-2.4/kmem.h
--- linux-2.4.26/fs/xfs/linux-2.4/kmem.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/kmem.h	2004-07-30 16:30:07.000000000 +0000
@@ -0,0 +1,152 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_KMEM_H__-+# /home __XFS_SUPPORT_KMEM_H__-+
+#includh <linux/slab.h>
+
+4-
+68 memory managImSnt routomes
+ -/-+# /home KM_SLEEP	0x0001-+# /home KM_NOSLEEP	0x0002-+# /home KM_NOFS		0x0004-+# /home KM_MAYFAIL	0x0008
+
+# /home	kmem_zone	kmem_cache_s-+# /home kmem_zone_t	kmem_cache_t
+
+Oypedef unsigted long xfs_p+c ls_t;
+
+# /home PFLAGS_TEST_NOIO()              (currSnt->+c ls &+PF_NOIO)
+# /home PFLAGS_TEST_FSTRANS()           (currSnt->+c ls &+PF_FSTRANS)
+
+# /home PFLAGS_SET_NOIO() doo{		\p+	currSnt->+c ls |=+PF_NOIO;	\p+} wHile (0)
+
+# /home PFLAGS_CLEAR_NOIO() doo{	\p+	currSnt->+c ls &= ~PF_NOIO;	\p+} wHile (0)
+
+4-+ShesencGuld benmestgd, so we sgafRstate -/-+# /home PFLAGS_SET_FSTRANS(STATEP) doo{	\p+	*(STATEP) = currSnt->+c ls;	\p+	currSnt->+c ls |=+PF_FSTRANS;	\p+} wHile (0)
+
+# /home PFLAGS_CLEAR_FSTRANS(STATEP) doo{ \p+	*(STATEP) = currSnt->+c ls;	\p+	currSnt->+c ls &= ~PF_FSTRANS;	\p+} wHile (0)
+
+/8 R6stor  OH uPF_FSTRANSRstate to(wHat was sgafd dn2STATEP -/-+# /home PFLAGS_RESTORE_FSTRANS(STATEP) doo{     		\p+	currSnt->+c ls = ((currSnt->+c ls &+~PF_FSTRANS) |	\p+	sE  (*(STATEP) &+PF_FSTRANS));		\p+} wHile (0)
+
+# /home PFLAGS_DUP(OSTATEP, NSTATEP) doo{ \p+	*(NSTATEP) = *(OSTATEP);	\p+} wHile (0)
+
+s,a ic __iiline unsigted dl  kmem_+c ls_convert(iitt+c ls)p+{p+        iittl+c ls;p+        -+#ifdef DEBUG
+	if (unlokely(+c ls &+~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL)))o{p+EEpriitk(KERN_WARNING
+		    "XFS: memory a2_HW]eISF2winv w ong +c ls (%x)\n", fc ls);p+E	BUG();
+	}
+#end(+
+
+	if (+c ls &+KM_NOSLEEP)o{p+EEl+c ls = GFP_ATOMIC;
+	} e_HWo{p+EEl+c ls = GFP_KERNEL;-+
+		/8 atic  recusive(callbacks to(+ilesystemAduriig transactISFs -/-+		if (PFLAGS_TEST_FSTRANS() || (+c ls &+KM_NOFS))m+EE	l+c ls &= ~__GFP_FS;
+	}
+        -+        r dirt l+c ls;p+}
+
+s,a ic __iiline kmem_zone_t *
+kmem_zone_init(int snit, char *zone_name)m+{p+	r dirt kmem_cache_cre]ee(zone_name, snit, 0, 0, ct a, ct a);
+}
+
+s,a ic __iiline tic 
+kmem_zone_d/ho(kmem_zone_t *zone, tic A*ptr)m+{p+	kmem_cache_d/ho(zone, ptr);
+}
+
+s,a ic __iiline tic 
+kmem_zone_d6stroy(kmem_zone_t *zone)p+{p+	if (zone && kmem_cache_d6stroy(zone))p+E	BUG();
+}
+
+s,a ic __iiline int
+kmem_zone_shriik(kmem_zone_t *zone)p+{p+	r dirt kmem_cache_shriik(zone);
+}
+
+extSrt vic s,,,,-kmem_zone_za2_HW(kmem_zone_t *, dl );-+extSrt vic s,,,,-kmem_zone_a2_HW(kmem_zone_t *, dl );-+-+extSrt vic s,,,,-kmem_a2_HW(snit_t, dl );-+extSrt vic s,,,,-kmem_rea2_HW(tic A*, snit_t, snit_t, dl );-+extSrt vic s,,,,-kmem_za2_HW(snit_t, dl );-+extSrt vic          kmem_d/ho(tic A*, snit_t);-+-+Oypedef tic s,,,,-kmem_shaker_t;-+Oypedef ily	    (-kmem_shake_func_t)(dl , unsigted dl );-+-+extSrt kmem_shaker_t	kmem_shake_regid,er(kmem_shake_func_t);-+extSrt vic s,,,,kmem_shake_dISegid,er(kmem_shaker_t);-+-+s,a ic __iiline int
+kmem_shake_a2_Hw(unsigted dl  gfp_mask)p+{p+	r dirt (gfp_mask &+__GFP_WAIT);
+}
+
+#end(+ 4- __XFS_SUPPORT_KMEM_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/mr12B,.c linux-2.4.27-rc4/fs/xfs/linux-2.4/mr12B,.c
--- linux-2.4.26/fs/xfs/linux-2.4/mr12B,.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/mr12B,.c	2004-07-30 16:30:39.000000000 +0000
@@ -0,0 +1,274 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+
+#includh <linux/SIme.h>
+#includh <linux/sche .h>
+#includh <asm/system.h>
+#includh <linux/dl errupt.h>
+#includh <asm/currSnt.h>
+
+#includh "mr12B,.h"
+
+-+#if USE_RW_WAIT_QUEUE_SPINLOCK
+#  /home wq_w    _12B,	w    _12B,
+#e_HWp+#  /home wq_w    _12B,	dpino12B,
+#end(+
+
+4-
+68 We don'k,seem0to(need loB,_type (only one supported), name, orp+f* sequSnce. Buy, XFS+wi2_ipassnit,so let's legafROH m H re for-now.
+ -/-+4- ARGSUSED -/-+tic 
+mr12B,_init(mr12B,_t *mrp, iittloB,_type, char *name, long sequSnce)p+{p+	mrp->mr_c*/in = 0;p+	mrp->mr_r adsowa  iig = 0;p+	mrp->mr_w    sowa  iig = 0;p+	initowa  quSue_h ad(&mrp->mr_r aderq);p+	initowa  quSue_h ad(&mrp->mr_w    rq);p+	mrp->mr_12B, = SPIN_LOCK_UNLOCKED;
+}
+
+4-
+68 Macros to(12B,/un12B, OH umr12B,_t.
+ -/-+
+# /home MRLOCK(m)	Edpino12B,(&(m)->mr_12B,);p+# /home MRUNLOCK(m)	Edpinoun12B,(&(m)->mr_12B,);p+
+
+4-
+68 12B,_wa   deGuld nmverdbe(called in,at ilyerrupt(OHr ad.p+ -
+68 mr12B,sAcan,sleep (i.e. call sche ule)eand so(OH yAcan't everp+f* be(called fromrat ilyerrupt(OHr ad.p+ -
+68 OHr ads tHatAwake-up deGuld also nmverdbe(invoked fromrilyerrupt(OHr ads.p+ -
+68 Buy, wa  quSue_12B, is 12B,ed fromrilyerrupt(OHr ads,- and wenare
+68 called winv2ilyerruptsfdidablBd, so it,is a2_ OK.
+ -/-+
+4- ARGSUSED -/-+tic 
+12B,_wa  (wa  _quSue_h ad_t *q,ndpin12B,_t *12B,, iittrw)p+{p+	DECLARE_WAITQUEUE( wa  , currSnt );
+
+	__set_currSnt_s,a e(TASK_UNINTERRUPTIBLE);
+
+	wq_w    _12B,(&q->12B,);p+	if (rw)o{p+EE__ dH_wa  _quSue_nail(q,n&wa  );
+	} e_HWo{p+EE__ dH_wa  _quSue(q,n&wa  );
+	}
+
+	wq_w    _un12B,(&q->12B,);p+	dpinoun12B,(12B,);p+
+	sche ule();
+
+	wq_w    _12B,(&q->12B,);p+	__r movg_wa  _quSue(q,n&wa  );
+	wq_w    _un12B,(&q->12B,);p+p+	dpino12B,(12B,);p+
+	/8 r dirt winv212B, held,-/-+}-+
+4- ARGSUSED -/-+tic 
+mrd/ho(mr12B,_t *mrp)p+{p+}-+
+4- ARGSUSED -/-+tic 
+mr12B,(mr12B,_t *mrp, iitttype, iitt+c ls)p+{p+	if (Oype == MR_ACCESS)m+EEmraccess(mrp);
+	e_HWp+EEmrupdatt(mrp);
+}-+
+4- ARGSUSED -/-+tic 
+mraccessf(mr12B,_t *mrp, iitt+c ls)p+{p+	MRLOCK(mrp);
+	if(mrp->mr_w    sowa  iig > 0)o{p+EEmrp->mr_r adsowa  iig++;p+E	12B,_wa  (&mrp->mr_r aderq,n&mrp->mr_12B,, 0);p+	Emrp->mr_r adsowa  iig--;
+	}p+EwHile (mrp->mr_c*/in < 0)o{p+EEmrp->mr_r adsowa  iig++;p+E	12B,_wa  (&mrp->mr_r aderq,n&mrp->mr_12B,, 0);p+	Emrp->mr_r adsowa  iig--;
+	}p+Emrp->mr_c*/in++;p+EMRUNLOCK(mrp);
+}-+
+4- ARGSUSED -/-+tic 
+mrupdattf(mr12B,_t *mrp, iitt+c ls)p+{p+	MRLOCK(mrp);
+	wHile(mrp->mr_c*/in)o{p+EEmrp->mr_w    sowa  iig++;p+E	12B,_wa  (&mrp->mr_w    rq,n&mrp->mr_12B,, 1);p+	Emrp->mr_w    sowa  iig--;
+	}p+p+	mrp->mr_c*/in = -1; 4- w    r+SF it -/-+	MRUNLOCK(mrp);
+}-+
+int
+mrtryaccess(mr12B,_t *mrp)p+{p+	MRLOCK(mrp);
+	4-
+s68 If( nyone is wa  iig for-updatt access-oS OH ul2B, is held,for-updatt
+s68 failnOHeArequSst.
+s68/
+	if(mrp->mr_w    sowa  iig > 0 || mrp->mr_c*/in < 0)o{p+EEMRUNLOCK(mrp);
+E	r dirt 0;
+	}p+Emrp->mr_c*/in++;p+EMRUNLOCK(mrp);
+	r dirt 1;
+}-+
+int
+mrtrypromoto(mr12B,_t *mrp)p+{p+	MRLOCK(mrp);
+
+	if(mrp->mr_c*/in == 1) { 4- WenarenOH uonly OHr ad winv2OHe 12B, -/-+		mrp->mr_c*/in = -1; 4- w    r+SF it -/-+	EMRUNLOCK(mrp);
+E	r dirt 1;
+	}p+p+	MRUNLOCK(mrp);
+	r dirt 0;
+}-+
+int
+mrtryupdatt(mr12B,_t *mrp)p+{p+	MRLOCK(mrp);
+
+	if(mrp->mr_c*/in)o{p+EEMRUNLOCK(mrp);
+E	r dirt 0;
+	}p+p+	mrp->mr_c*/in = -1; 4- w    r+SF it -/-+	MRUNLOCK(mrp);
+	r dirt 1;
+}-+
+s,a ic __iiline__ vic  mrwake(mr12B,_t *mrp)p+{p+	4-
+s68 First, i++OHeAc*/in don_tw 0, we(need to(wake-up  nyone wa  iig.
+s68/
+	if (!mrp->mr_c*/in)o{p+EEif (mrp->mr_w    sowa  iig)o{	/8 Wake-up first w    r+wa  iig -/-+	E	wake_up(&mrp->mr_w    rq);p+		} e_HWoif (mrp->mr_r adsowa  iig)o{	/8 Wakeup  ny r aders+wa  iig -/-+	E	wake_up(&mrp->mr_r aderq);p+	E}p+E}p+}
+
+tic 
+mraccun12B,(mr12B,_t *mrp)p+{p+	MRLOCK(mrp);
+	mrp->mr_c*/in--;
+	mrwake(mrp);
+	MRUNLOCK(mrp);
+}-+
+tic 
+mrun12B,(mr12B,_t *mrp)p+{p+	MRLOCK(mrp);
+	if (mrp->mr_c*/in < 0)o{p+EEmrp->mr_c*/in = 0;p+	} e_HWo{p+EEmrp->mr_c*/in--;
+	}
+	mrwake(mrp);
+	MRUNLOCK(mrp);
+}-+
+int
+ismr12B,ed(mr12B,_t *mrp, iitttype)	/8 No(need to(12B, siiceAinfoAcan,change(-/-+{p+	if (Oype == MR_ACCESS)m+EEr dirt (mrp->mr_c*/in > 0); 4- R ad 12B, -/-+	e_HWoif (Oype == MR_UPDATE)m+EEr dirt (mrp->mr_c*/in < 0); 4- W     12B, -/-+	e_HWoif (Oype == (MR_UPDATE | MR_ACCESS))m+EEr dirt (mrp->mr_c*/in);s4-+AnyrOype o++l2B, held,-/-+	e_HWo4-+Anyrwa  ers+-/-+	Er dirt (mrp->mr_r adsowa  iig | mrp->mr_w    sowa  iig);
+}
+
+4-
+68 Demoto fromrupdatt to(access. Wenbetterdbe(OH uonly OHr ad winv2OHe
+68 12B, in,updatt mode so it,deGuld be(easy to(set to(1.
+68 Wake-up  ny r aders+wa  iig.
+ -/-+
+tic 
+mrdemoto(mr12B,_t *mrp)p+{p+	MRLOCK(mrp);
+Emrp->mr_c*/in = 1;
+	if (mrp->mr_r adsowa  iig)o{	/8 Wakeup  2_ r aders+wa  iig -/-+	Ewake_up(&mrp->mr_r aderq);p+	}
+	MRUNLOCK(mrp);
+}-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/mr12B,.h linux-2.4.27-rc4/fs/xfs/linux-2.4/mr12B,.h
--- linux-2.4.26/fs/xfs/linux-2.4/mr12B,.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/mr12B,.h	2004-07-30 16:32:05.000000000 +0000
@@ -0,0 +1,87 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_MRLOCK_H__-+# /home __XFS_SUPPORT_MRLOCK_H__-+
+#includh <linux/SIme.h>
+#includh <linux/wa  .h>
+#includh <asm/aSomic.h>
+#includh <asm/semaphore.h>
+
+4-
+68 ImplemSnt mr12B,sASF Ldnux tHatAwork for-XFS.p+ -
+68 T/esenarensleep 12B,s and+_tyidpin12B,s. If(one wants read/w     dpin12B,s,
+ - ush read_12B,, w    _12B,, ... see dpin12B,.h.
+ -/-+
+Oypedef s,* Ok,mr12B,_so{p+Eint	d	mr_c*/in;p+	unsigted deGrtd	mr_r adsowa  iig;p+	unsigted deGrtd	mr_w    sowa  iig;
+	wa  _quSue_h ad_t	mr_r aderq;
+	wa  _quSue_h ad_t	mr_w    rq;p+	dpin12B,_td	mr_12B,;
+}umr12B,_t;-+
+# /home MR_ACCESS	1
+# /home MR_UPDATE	2-+
+# /home MRLOCK_BARRIER		0x1
+# /home MRLOCK_ALLOW_EQUAL_PRI	0x8
+
+4-
+68 mraccessf/mrupdattf take(fc ls Oo-beipassed dn2wHile sleepiig;
+f* only PLTWAITndsfcurrSntly supported.
+ -/-+
+extSrt vic smraccessf(mr12B,_t *, dl );-+extSrt vic smrupdattf(mr12B,_t *, dl );-+extSrt vic      mr12B,(mr12B,_t *, dl , dl );-+extSrt vic      mrun12B,(mr12B,_t *);-+extSrt vic      mraccun12B,(mr12B,_t *);-+extSrt iitt     mrtryupdatt(mr12B,_t *);-+extSrt iitt     mrtryaccess(mr12B,_t *);-+extSrt iit	mrtrypromoto(mr12B,_t *);-+extSrt vic      mrdemoto(mr12B,_t *);-+-+extSrt ily	ismr12B,ed(mr12B,_t *, dl );-+extSrt vic      mr12B,_init(mr12B,_t *, iitttype, char *name, long sequSnce);-+extSrt vic      mrd/ho(mr12B,_t *);-+
+# /home mrinit(mrp, name)	mr12B,_init(mrp, MRLOCK_BARRIER, name, -1)
+# /home mraccess(mrp)	smraccessf(mrp, 0)o4-+grab for-READ/ACCESS -/-+# /home mrupdatt(mrp)	smrupdattf(mrp, 0)o4-+grab for-WRITE/UPDATE -/-+# /home mris12B,ed_access(mrp)	((mrp)->mr_c*/in > 0)-+# /home mris12B,ed_updatt(mrp)	((mrp)->mr_c*/in < 0)
+
+#end(+ 4- __XFS_SUPPORT_MRLOCK_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/mutex.h linux-2.4.27-rc4/fs/xfs/linux-2.4/mutex.h
--- linux-2.4.26/fs/xfs/linux-2.4/mutex.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/mutex.h	2004-07-30 16:29:20.000000000 +0000
@@ -0,0 +1,53 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_MUTEX_H__-+# /home __XFS_SUPPORT_MUTEX_H__-+
+#includh <linux/spin12B,.h>
+#includh <asm/semaphore.h>
+
+4-
+68 Map OH umutex'es fromrIRIX0to(Ldnux semaphores.p+ -
+68 D6stroy justds mply initiclizes Oo--99 whicv,deGuld b12B,  2_ oOH r
+68 callers.
+ -/-+# /home MUTEX_DEFAULT		0x0
+Oypedef s,* Ok,semaphore	mutex_t;-+
+# /home mutex_init(12B,, type, name)		sema_init(12B,, 1)
+# /home mutex_d6stroy(12B,)			sema_init(12B,, -99)
+# /home mutex_12B,(12B,,+_um)			down(12B,)
+# /home mutex_try12B,(12B,)sEs(down_try12B,(12B,) ? 0 : 1)
+# /home mutex_un12B,(12B,)sEsup(12B,)
+
+#end(+ 4- __XFS_SUPPORT_MUTEX_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/sema.h linux-2.4.27-rc4/fs/xfs/linux-2.4/sema.h
--- linux-2.4.26/fs/xfs/linux-2.4/sema.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/sema.h	2004-07-30 16:31:15.000000000 +0000
@@ -0,0 +1,67 @@
+4-
+68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_SEMA_H__-+# /home __XFS_SUPPORT_SEMA_H__-+
+#includh <linux/SIme.h>
+#includh <linux/wa  .h>
+#includh <asm/aSomic.h>
+#includh <asm/semaphore.h>
+
+4-
+68 sema_t s,* Okure,justdmaps Oo-s,* Ok,semaphore dn2Ldnux kertel.
+ -/-+
+Oypedef s,* Ok,semaphore sema_t;-+
+# /home initosema(sp, tal, c, d)	sema_init(sp, tal)
+# /home initsema(sp, tal)		sema_init(sp, tal)
+# /home initnsema(sp, tal, name)	sema_init(sp, tal)
+# /home psema(sp, b)			down(sp)
+# /home vsema(sp)sEsup(sp)
+# /home valusema(sp)sEs(aSomic_r ad(&(sp)->c*/in))
+# /home d/hosema(sema)
+
+4-
+68 Map cpsema (try Oo-get OH usema) Oo-down_try12B,. Wenneed to(swincvp+f* OHeAredirt valuBs siiceAcpsema redirts 1 (acquired) 0 (failed) andp+f* down_try12B, redirts OHeAreverse 0 (acquired) 1 (failed).
+ -/-+
+# /home cpsema(sp)sEs(down_try12B,(sp) ? 0 : 1)
+
+4-
+68 Didn't do+cvsema(sp). Ntyidure,how to(map OHis Oo-up/down/...
+68 It doBs a vsema i++OHeAvaluBs is < 0 oOH rnwisen_tyhiig.
+ -/-+
+#end(+ 4- __XFS_SUPPORT_SEMA_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/spin.h linux-2.4.27-rc4/fs/xfs/linux-2.4/spin.h
--- linux-2.4.26/fs/xfs/linux-2.4/spin.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/spin.h	2004-07-30 16:32:15.000000000 +0000
@@ -0,0 +1,56 @@
+4-
+68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_SPIN_H__-+# /home __XFS_SUPPORT_SPIN_H__-+
+#includh <linux/sche .h>	/8 p/homptnneeds OHdon-/-+#includh <linux/spin12B,.h>
+
+4-
+68 Map 12B,_t fromrIRIX0to(Ldnux spin12B,s.
+ -
+68 We do+_tyimak  ush o++l2B,_t fromrilyerrupt(context, so we do+_ty
+68 hgafROoAworry about didabliigdinyerruptsfatA 2_ (unlokerIRIX).
+ -/-+
+Oypedef spin12B,_t 12B,_t;-+
+# /home SPLDECL(s)sEsunsigted long s-+
+# /home spin12B,_init(12B,, name)	spino12B,_init(12B,)
+# /home	dpin12B,_d6stroy(12B,)
+# /home mutex_dpin12B,(12B,)sE({ dpino12B,(12B,); 0;+})
+# /home mutex_dpinun12B,(12B,, s)	doo{ dpinoun12B,(12B,); (vic )s;+} wHile (0)
+# /home mestgd_dpin12B,(12B,)sEdpino12B,(12B,)
+# /home mestgd_dpinun12B,(12B,)sEdpinoun12B,(12B,)-+
+#end(+ 4- __XFS_SUPPORT_SPIN_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/sv.h linux-2.4.27-rc4/fs/xfs/linux-2.4/sv.h
--- linux-2.4.26/fs/xfs/linux-2.4/sv.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/sv.h	2004-07-30 16:30:40.000000000 +0000
@@ -0,0 +1,89 @@
+4-
+68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_SV_H__-+# /home __XFS_SUPPORT_SV_H__-+
+#includh <linux/wa  .h>
+#includh <linux/sche .h>
+#includh <linux/spin12B,.h>
+
+4-
+68 SynchronidaSISF variablBs.
+ -
+68 (Parame ers+"pri", "svf" and+"rts"naren_tyiimplemSnte )p+ -/-+
+Oypedef s,* Ok,sv_so{p+Ewa  _quSue_h ad_t wa  ers;
+}usv_t;-+
+# /home SV_FIFO		0x0		/8 sv_tndsfFIFOrOype -/-+# /home SV_LIFO		0x2		/8 sv_tndsfLIFOrOype -/-+# /home SV_PRIO		0x4		/8 sv_tndsfPRIOrOype -/-+# /home SV_KEYED	0x6		/8 sv_tndsfKEYEDrOype -/-+# /home SV_DEFAULTt     SV_FIFOp+
+
+s,a ic iiline tic  _sv_wa  (sv_tn*sv,ndpin12B,_t *12B,, iitts,a e,p+	sE     unsigted long SImeout)p+{p+	DECLARE_WAITQUEUE(wa  , currSnt);
+
+	 dH_wa  _quSue_exclusive(&sv->wa  ers,n&wa  );
+	__set_currSnt_s,a e(s,a e);p+	dpinoun12B,(12B,);p+
+	sche ule_SImeout(SImeout);
+
+	r movg_wa  _quSue(&sv->wa  ers,n&wa  );
+}-+
+# /home initosv(sv,type,name,fc l) \p+	initowa  quSue_h ad(&(sv)->wa  ers)
+# /home sv_init(sv,fc l,name) \p+	initowa  quSue_h ad(&(sv)->wa  ers)
+# /home sv_d6stroy(sv) \p+	/*NOTHING-/-+# /home sv_wa  (sv,npri, 12B,, s) \p+	_sv_wa  (sv,n12B,, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)-+# /home sv_wa  _sig(sv,npri, 12B,, s)   \p+	_sv_wa  (sv,n12B,, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT)-+# /home sv_SImedwa  (sv,npri, 12B,, s, svf,(Os, rts) \p+	_sv_wa  (sv,n12B,, TASK_UNINTERRUPTIBLE, SImespec_to_jiffiBs(ts))-+# /home sv_SImedwa  _sig(sv,npri, 12B,, s, svf,(Os, rts) \p+	_sv_wa  (sv,n12B,, TASK_INTERRUPTIBLE, SImespec_to_jiffiBs(ts))-+# /home sv_sigtal(sv) \p+	wake_up(&(sv)->wa  ers)
+# /home sv_broadcast(sv) \p+	wake_up_a2_(&(sv)->wa  ers)
+
+#end(+ 4- __XFS_SUPPORT_SV_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/SIme.h linux-2.4.27-rc4/fs/xfs/linux-2.4/SIme.h
--- linux-2.4.26/fs/xfs/linux-2.4/SIme.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/SIme.h	2004-07-30 16:27:15.000000000 +0000
@@ -0,0 +1,55 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.  AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+#ifndef __XFS_SUPPORT_TIME_H__-+# /home __XFS_SUPPORT_TIME_H__-+
+#includh <linux/sche .h>
+#includh <linux/SIme.h>
+
+Oypedef s,* Ok,SImespec SImespec_t;
+
+s,a ic iiline tic  delay(long SIcks)p+{p+	set_currSnt_s,a e(TASK_UNINTERRUPTIBLE);
+	sche ule_SImeout(SIcks);
+}-+
+s,a ic iiline tic  na_tyime(s,* Ok,SImespec *tvp)p+{p+	s,* Ok,SImeval tv;-+
+	do_getSImeofday(&tv);
+	tvp->tv_sec = tv.tv_sec;
+	tvp->tv_nsec = tv.tv_usec * 1000;
+}-+
+#end(+ 4- __XFS_SUPPORT_TIME_H__ -/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_aops.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_aops.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_aops.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_aops.c	2004-07-30 16:31:48.000000000 +0000
@@ -0,0 +1,1312 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  A2_iRights Res6rvBd.d+ -
+68 T/donprogramndsfd/ho(software; youAcan,redid,*ibute ittand/p_ modify it
+ - undIS OH uct
ms o++versISF 2 o++OHeAGNU General Public LicenseAas
+68 publishe }byrOH uF/ho(Software FoundaSISF.p+ -
+68 T/donprogramndsfdid,*ibuted dn2OH uhopfROHatAit,wGuld benuseful, but
+ - WITHOUT ANY WARRANTY;0winvout eveinOHe- mpliBdtwarranty o+
+ - MERCHANTABILITY(p_ FITNESS FOR A fsRTICULAR PURPOSE.p+ -
+68 FurOH r,(OHdonsoftwarendsfdid,*ibuted winvout any warranty OHatAit,is
+68 d/ho(o++OHeArightful}claim Sf( nyrOHdrd persSF regardiigdinfriigemSnt
+68 oS OH uloke.	 AnyrlicenseAprovided H rein, wheOH rn mpliBdtorp+f* oOH rwise, appliBs only OorOHdonsoftwaren.ile.  Patentrlicenses,n(+
+68( ny,nprovided H rein,do+_tyiapply0to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.p+ -
+68 YouAdeGuld igafRreceivedAa(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;+(++_ty, w     OH uF/ho(Software FoundaSISF, Inc., 59
+68 Temple Place,- Su    330, Boston MA 02111-1307, USA.p+ -
+68 CortactdinformaSISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain,View, CA  94043,nor:
+ -
+68 http://www.sgi.comp+ -
+68 For0.urOH rdinformaSISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projeces/GenInfo/SGIGPLNtyiceExplan/
+ -/-+
+#includh "xfs.h"
+#includh "xfs_inum.h"
+#includh "xfs_log.h"
+#includh "xfs_sb.h"
+#includh "xfs_dir.h"
+#includh "xfs_dir2.h"
+#includh "xfs_trans.h"
+#includh "xfs_dmapi.h"
+#includh "xfs_m*/in.h"
+#includh "xfs_bmap_btree.h"
+#includh "xfs_a2_HW_btree.h"
+#includh "xfs_ia2_HW_btree.h"
+#includh "xfs_a2_HW.h"
+#includh "xfs_btree.h"
+#includh "xfs_attr_sf.h"
+#includh "xfs_dir_sf.h"
+#includh "xfs_dir2_sf.h"
+#includh "xfs_dinode.h"
+#includh "xfs_inode.h"
+#includh "xfs_error.h"
+#includh "xfs_rw.h"
+#includh "xfs_iomap.h"
+#includh <linux/iobuf.h>
+
+STATIC tic  xfs_c*/in_page_s,a e(s,* Ok,page *, iitt*, iitt*, iitt*);
+STATIC tic  xfs_c*nvert_page(s,* Ok,inodeA*, s,* Ok,page *,p+	sE	xfs_iomap_t *, tic A*, dl , dl );-+-+#if  /homed(XFS_RW_TRACE)m+tic 
+xfs_page_trace(p+Eint	dtag,p+	s,* Ok,inode	*inode,p+	s,* Ok,page	*page,p+Eint	dmask)p+{p+	xfs_inode_t	*ip;
+	bhv_d6sc_t	*bdp;
+	vnode_t		*vp = LINVFS_GET_VP(inode);
+	loff_t		isnit = i_snit_r ad(inode);
+	loff_t		offset =,page->indIx << PAGE_CACHE_SHIFT;p+Eint	ddela2_HW = -1, unmapped = -1, unw   ten = -1;
+
+	if (page_has_buffers(page))m+EExfs_c*/in_page_s,a e(page, &dela2_HW, &unmapped, &unw   ten);
+
+	bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
+	ip = XFS_BHVTOI(bdp);
+	if (!ip->i_rwtrace)m+EEr dirt;
+
+	ktrace_Snter(ip->i_rwtrace,p+	s(tic A*)((unsigted long)tag),p+	s(tic A*)ip,p+	s(tic A*)inode,p+	s(tic A*)page,p+Es(tic A*)((unsigted long)mask),p+Es(tic A*)((unsigted long)((ip->i_d.di_snit >> 32) &+0xffffffff)),p+Es(tic A*)((unsigted long)(ip->i_d.di_snit &+0xffffffff)),p+Es(tic A*)((unsigted long)((isnit >> 32) &+0xffffffff)),p+Es(tic A*)((unsigted long)(isnit &+0xffffffff)),p+Es(tic A*)((unsigted long)((offset >> 32) &+0xffffffff)),p+Es(tic A*)((unsigted long)(offset &+0xffffffff)),p+Es(tic A*)((unsigted long)dela2_HW),p+Es(tic A*)((unsigted long)unmapped),p+Es(tic A*)((unsigted long)unw   ten),p+Es(tic A*)ct a,p+Es(tic A*)ct a);
+}-+#e_HWp+# /home xfs_page_trace(tag,,inode, page, mask)p+#end(+
+
+tic 
+1invfs_unw   ten_stre(p+Es,* Ok,buffer_h ad	*bh,p+Eint	d	uptodatt)p+{p+	xfs_buf_t		*pb = (xfs_buf_tA*)bh->b_privatt;
+
+	ASSERT(buffer_unw   ten(bh));p+Ebh->b_end_io = ct a;p+Eclear_buffer_unw   ten(bh);
+	if (!uptodatt)p+		pagebuf_ioerror(pb, EIO);
+	if (aSomic_dec_and_test(&pb->pb_io_r mainiig)o== 1) {p+		pagebuf_iostre(pb, 1, 1);p+	}
+	end_buffer_io_async(bh, uptodatt);
+}
+
+4-
+68 Issue transactISFs to(convertAa(buffer range(fromrunw   ten
+68 OoAw   ten extSnts.
+ -/-+STATIC tic 
+1invfs_unw   ten_convert(p+	xfs_buf_t	*bp)p+{p+	vnode_t		*vp = XFS_BUF_FSPRIVATE(bp, tnode_tt*);
+Eint	derror;
+
+	BUG_ON(aSomic_r ad(&bp->pb_hold) < 1);p+	VOP_BMAP(vp, XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp),p+	sEBMAPI_UNWRITTEN, ct a, ct a, error);p+	XFS_BUF_SET_FSPRIVATE(bp, ct a);
+	XFS_BUF_CLR_IODONE_FUNC(bp);
+	XFS_BUF_UNDATAIO(bp);
+	iput(LINVFS_GET_IP(vp));p+Epagebuf_iostre(bp, 0, 0);p+}
+
+STATIC int
+xfs_map_b12B,s(p+Es,* Ok,inode		*inode,p+	loff_t			offset,p+	ssnit_t			c*/in,p+	xfs_iomap_t		*iomapp,p+Eint	d	+c ls)p+{p+	vnode_t			*vp = LINVFS_GET_VP(inode);
+	int	d	error, niomaps = 1;
+p+	VOP_BMAP(vp, offset,Ac*/in, fc ls,,iomapp, &niomaps, error);p+	if (!error && (+c ls &+(BMAPI_WRITE|BMAPI_ALLOCATE)))m+EEVMODIFY(vp);
+	r dirt -error;
+}
+
+4-
+68 Finds OHeAcorrespondiig mappiigdin b12B, @map array o++OHe
+68 givein@offset winvin,a @page.
+ -/-+STATIC xfs_iomap_t *
+xfs_offset_to_map(p+Es,* Ok,page		*page,p+Exfs_iomap_t		*iomapp,p+Eunsigted long		offset)p+{p+	loff_t			full_offset;s4-+offset fromrs,artAo++.ile -/-+
+	ASSERT(offset < PAGE_CACHE_SIZE);
+
+	full_offset =,page->indIx;		/8 NB: usiigd64bit+_umber -/-+	full_offset <<= PAGE_CACHE_SHIFT;s4-+offset fromr.ile s,artA-/-+	full_offset += offset;s	s4-+offset fromrpage s,artA-/-+p+	if (full_offset <,iomapp->iomap_offset)p+	Er dirt ct a;p+Eif (iomapp->iomap_offset + (iomapp->iomap_bsnit -1) >= full_offset)p+	Er dirt iomapp;
+	r dirt ct a;p+}
+
+STATIC tic 
+xfs_map_at_offset(p+Es,* Ok,page		*page,p+Es,* Ok,buffer_h ad	*bh,p+Eunsigted long		offset,p+Eint	d	b12B,_bits,p+Exfs_iomap_t		*iomapp)p+{p+	xfs_daddr_t		bn;
+	loff_t		ddelta;
+	int	d	sector_shift;
+
+	ASSERT(!(iomapp->iomap_+c ls &+IOMAP_HOLE));p+EASSERT(!(iomapp->iomap_+c ls &+IOMAP_DELAY));p+EASSERT(iomapp->iomap_bn !=+IOMAP_DADDR_ct a);
+
+	delta =,page->indIx;
+	delta <<= PAGE_CACHE_SHIFT;
+	delta += offset;
+	delta -=,iomapp->iomap_offset;
+	delta >>= b12B,_bits;p+
+	sector_shift = b12B,_bits - BBSHIFT;
+	bn = iomapp->iomap_bn >> sector_shift;
+	bn += delta;
+	ASSERT((bn << sector_shift) >= iomapp->iomap_bn);
+
+	12B,_buffer(bh);
+	bh->b_b12B,nr = bn;
+	bh->b_dev = iomapp->iomap_,arget->pbr_kdev;p+	set_buffer_mapped(bh);
+	clear_buffer_delay(bh);
+}
+
+4-
+68 Look for-arpage atAindIx whicv,is un12B,edAand(contains our
+ - unw   ten extSnt fc lge }buffers atAits head.  Redirts page
+ - 12B,edAand(winv2an extra refereiceAc*/in, and(lengnv2o++OHe
+68 unw   ten extSnt componSnt on2OHdonpage tHatAweAcan,w    ,
+ - in,unitsAo++.ilesystemAb12B,s.
+ -/-+STATIC s,* Ok,page *
+xfs_probe_unw   ten_page(p+Es,* Ok,address_space	*mappiig,p+Epgoff_t		dindIx,p+Exfs_iomap_t		*iomapp,p+Exfs_buf_t		*pb,p+Eunsigted long		max_offset,p+Eunsigted long		*fsbs,p+Eunsigted iitt           bbits)p+{p+	s,* Ok,page		*page;
+
+	page = find_try12B,_page(mappiig,AindIx);p+	if (!page)p+	Er dirt 0;
+
+	if (page->mappiigd&& page_has_buffers(page)) {p+		s,* Ok,buffer_h ad	*bh, *h ad;p+	Eunsigted long		p_offset =,0;
+
+		*fsbs = 0;p+		bh = h ad =,page_buffers(page);p+		doo{p+	sEif (!buffer_unw   ten(bh) || !buffer_uptodatt(bh))p+	sE	br ak;p+	sEif (!xfs_offset_to_map(page, iomapp, p_offset))p+	sE	br ak;p+	sEif (p_offset >= max_offset)p+	sE	br ak;p+	sExfs_map_at_offset(page, bh, p_offset, bbits, iomapp);p+			set_buffer_unw   ten_io(bh);
+			bh->b_privatt =,pb;
+			p_offset += bh->b_snit;
+			(*fsbs)++;p+E	} wHile ((bh = bh->b_OHdo_page) !=+h ad);
+
+	Eif (p_offset)p+	sEr dirt page;
+	}p+p+	un12B,_page(page);p+	r dirt ct a;p+}
+
+4-
+68 Look for-arpage atAindIx whicv,is un12B,edAand(_tyimapped
+68 yet - clusteriig for-mmap w     case.
+ -/-+STATIC unsigted iit
+xfs_probe_unmapped_page(p+Es,* Ok,address_space	*mappiig,p+Epgoff_t		dindIx,p+Eunsigted iit		pg_offset)p+{p+	s,* Ok,page		*page;
+	int	d	ret =,0;
+
+	page = find_try12B,_page(mappiig,AindIx);p+	if (!page)p+	Er dirt 0;
+
+	if (page->mappiigd&& PageDirty(page)) {p+		if (page_has_buffers(page))o{p+	sEs,* Ok,buffer_h ad	*bh, *h ad;p+
+			bh = h ad =,page_buffers(page);p+			doo{p+	sE	if (buffer_mapped(bh) || !buffer_uptodatt(bh))p+	sE		br ak;p+	sE	ret += bh->b_snit;
+				if (ret >= pg_offset)p+	sE		br ak;p+	sE} wHile ((bh = bh->b_OHdo_page) !=+h ad);
+		} e_HWp+	sEr d = PAGE_CACHE_SIZE;
+	}p+p+	un12B,_page(page);p+	r dirt ret;
+}
+
+STATIC unsigted iit
+xfs_probe_unmapped_cluster(p+Es,* Ok,inode		*inode,p+	s,* Ok,page		*s,artpage,p+Es,* Ok,buffer_h ad	*bh,p+Es,* Ok,buffer_h ad	*h ad)p+{p+	pgoff_t		dtindIx, tlast, tloff;p+Eunsigted iit		pg_offset,(len, total = 0;p+	s,* Ok,address_space	*mappiig = inode->i_mappiig;p+
+	/8 First sum forwards in2OHdonpage -/-+	doo{p+	sif (buffer_mapped(bh))p+	sEbr ak;p+	stotal += bh->b_snit;
+	} wHile ((bh = bh->b_OHdo_page) !=+h ad);
+
+	/8 If(wh reache  OHeAend(o++OHeApage, sum forwards in
+s68 fo2_Hwiig pages.
+s68/
+	if (bh ==+h ad)o{p+	stlast = i_snit_r ad(inode) >> PAGE_CACHE_SHIFT;
+		/8 Prune2OHdonbaB, Oo atic Apathological behavior -/-+		tloff = min(tlast, s,artpage->indIx +d64);
+		for-(tindIx = s,artpage->indIx +d1; tindIx < tloff; tindIx++)o{p+	sElen = xfs_probe_unmapped_page(mappiig,AtindIx,p+EEEEEEEPAGE_CACHE_SIZE);
+	sEif (!len)p+	sE	retirt total;
+	sEtotal += len;
+		}p+	sif (tindIx == tlastd&&p+	s    (pg_offset = i_snit_r ad(inode) & (PAGE_CACHE_SIZE - 1)))o{p+	sEtotal += xfs_probe_unmapped_page(mappiig,p+EEEEEEEtindIx, pg_offset);
+		}p+	}p+	r dirt total;
+}
+
+4-
+68 Probe for-argiveinpage (indIx) dn2OH uinodeAand(test+(++it,is delayed
+68 and(winvout unw   ten buffers.  Redirts page 12B,edAand(winv2an extra
+68 refereiceAc*/in.
+ -/-+STATIC s,* Ok,page *
+xfs_probe_dela2_HW_page(p+Es,* Ok,inode		*inode,p+	pgoff_t		dindIx)p+{p+	s,* Ok,page		*page;
+
+	page = find_try12B,_page(inode->i_mappiig,AindIx);p+	if (!page)p+	Er dirt ct a;p+
+	if (page->mappiigd&& page_has_buffers(page)) {p+		s,* Ok,buffer_h ad	*bh, *h ad;p+	Eint	d	acceptablB =,0;
+
+		bh = h ad =,page_buffers(page);p+		doo{p+	sEif (buffer_unw   ten(bh))o{p+	sE	acceptablB =,0;
+sE		br ak;p+	sE} e_HWoif (buffer_delay(bh))o{p+	sE	acceptablB =,1;p+	sE}p+E	} wHile ((bh = bh->b_OHdo_page) !=+h ad);
+
+	Eif (acceptablB)p+	sEr dirt page;
+	}p+p+	un12B,_page(page);p+	r dirt ct a;p+}
+
+STATIC int
+xfs_map_unw   ten(p+Es,* Ok,inode		*inode,p+	s,* Ok,page		*s,art_page,p+Es,* Ok,buffer_h ad	*h ad,p+Es,* Ok,buffer_h ad	*curr,p+Eunsigted long		p_offset,p+Eint	d	b12B,_bits,p+Exfs_iomap_t		*iomapp,p+Eint	d	s,artio,p+Eint	d	a2__bh)p+{p+	s,* Ok,buffer_h ad	*bh = curr;p+Exfs_iomap_t		*tmp;p+Exfs_buf_t		*pb;
+	loff_t		doffset,(snit;
+	unsigted long		nb12B,s =,0;
+
+	offset = s,art_page->indIx;
+	offset <<= PAGE_CACHE_SHIFT;
+	offset += p_offset;
+
+	/8 get an "ompty" pagebuf to(manage IO completISF
+s68 ProperAvaluBs wi2_ibe(set before r dirtiig -/-+	pb = pagebuf_lookup(iomapp->iomap_,arget, 0, 0, 0);p+	if (!pb)p+	Er dirt -EAGAIN;
+
+	/8 Tak  a refereiceAOorOH uinodeAOorpreventAit,from
+s68 beiig reclaimed wHile wh igafRouts,andiig unw   ten
+s68 extSnt IO SF it.
+s68/
+	if ((igrab(inode)) !=+inode) {p+	spagebuf_d/ho(pb);p+	Er dirt -EAGAIN;
+	}p+p+	/8 Set OH uc*/in to(1 initiclly,(OHdonwi2_istop  n I/O
+s68 completISF callout whicv,happets before wh igafRs,arted
+s68  2_ OH uI/O fromrcalliig pagebuf_iostre too early.
+s68/
+	aSomic_set(&pb->pb_io_r mainiig, 1);p+
+	/8 First map forwards in2OHeApage(consecutive buffers
+s68 coveriig OHdonunw   ten extSnt
+s68/
+	doo{p+	sif (!buffer_unw   ten(bh))p+	sEbr ak;p+	stmp = xfs_offset_to_map(s,art_page, iomapp, p_offset);p+	sif (!tmp)p+	sEbr ak;p+	sxfs_map_at_offset(s,art_page, bh, p_offset, b12B,_bits, iomapp);p+		set_buffer_unw   ten_io(bh);
+		bh->b_privatt =,pb;
+		p_offset += bh->b_snit;
+		nb12B,s++;p+E} wHile ((bh = bh->b_OHdo_page) !=+h ad);
+
+	aSomic_add(nb12B,s, &pb->pb_io_r mainiig);
+
+	/8 If(wh reache  OHeAend(o++OHeApage, map forwards in2any
+s68 fo2_Hwiig pages whicv,are also covere }byrOHdonextSnt.
+s68/
+	if (bh ==+h ad)o{p+	ss,* Ok,address_space	*mappiig = inode->i_mappiig;p+		pgoff_t		dtindIx, tloff, tlast;p+	Eunsigted long		bs;p+	Eunsigted iit		pg_offset,(bbits = inode->i_blkbits;p+		s,* Ok,page		*page;
+
+	stlast = i_snit_r ad(inode) >> PAGE_CACHE_SHIFT;
+		tloff = (iomapp->iomap_offset + iomapp->iomap_bsnit) >> PAGE_CACHE_SHIFT;
+		tloff = min(tlast, tloff);
+		for-(tindIx = s,art_page->indIx +d1; tindIx < tloff; tindIx++)o{p+	sEpage = xfs_probe_unw   ten_page(mappiig,p+EEEEEEtindIx, iomapp, pb,p+EEEEEEPAGE_CACHE_SIZE, &bs,(bbits);
+	sEif (!page)p+	E		br ak;p+	sEnb12B,s += bs;p+			aSomic_add(bs, &pb->pb_io_r mainiig);
+	EExfs_c*nvert_page(inode, page, iomapp, pb,p+EEEEEE	s,artio, a2__bh);
+	EE/8 stop if c*nvertiig OHe mexk,page might add
+	EE68 enoughAb12B,s tHatAOHeAcorrespondiig byte
+	EE68 c*/in won't fit,in our ulong page buf lengnv2-/-+	E	if (nb12B,s >= ((ULONG_MAX - PAGE_SIZE) >> b12B,_bits))p+	sE	goto(enough;
+		}p+p+	sif (tindIx == tlastd&&p+	s    (pg_offset = (i_snit_r ad(inode) & (PAGE_CACHE_SIZE - 1))))o{p+	sEpage = xfs_probe_unw   ten_page(mappiig,p+EEEEEEEtindIx, iomapp, pb,p+EEEEEE	pg_offset,(&bs,(bbits);
+	sEif (page) {p+	sE	nb12B,s += bs;p+				aSomic_add(bs, &pb->pb_io_r mainiig);
+	EEExfs_c*nvert_page(inode, page, iomapp, pb,p+EEEEEE	s,artio, a2__bh);
+	EE	if (nb12B,s >= ((ULONG_MAX - PAGE_SIZE) >> b12B,_bits))p+	sE		goto(enough;
+		E}p+E	}
+	}p+p+enough:p+	snit = nb12B,s;		/8 NB: usiigd64bit+_umber H re2-/-+	snit <<= b12B,_bits;	/8 convertAfsb's Oo-byte range(-/-+p+	XFS_BUF_DATAIO(pb);p+	XFS_BUF_ASYNC(pb);p+	XFS_BUF_SET_SIZE(pb, snit);p+	XFS_BUF_SET_COUNT(pb, snit);p+	XFS_BUF_SET_OFFSET(pb, offset);p+	XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode));p+	XFS_BUF_SET_IODONE_FUNC(pb, 1invfs_unw   ten_convert);
+
+	if (aSomic_dec_and_test(&pb->pb_io_r mainiig)o== 1) {p+		pagebuf_iostre(pb, 1, 1);p+	}
+
+	r dirt 0;
+}-+
+STATIC tic 
+xfs_submit_page(p+Es,* Ok,page		*page,p+Es,* Ok,buffer_h ad	*bh_arr[],p+Eint	d	cnt)p+{p+	s,* Ok,buffer_h ad	*bh;
+	int	d	i;
+
+	if (cin)o{p+EEfor-(i =,0; i < cin; i++)o{p+	sEbh = bh_arr[i];p+			set_buffer_async_io(bh);
+			if (buffer_unw   ten(bh))p+	sE	set_buffer_unw   ten_io(bh);
+			set_buffer_uptodatt(bh);
+			clear_buffer_dirty(bh);
+		}p+p+	sfor-(i =,0; i < cin; i++)o{p+	sErefile_buffer(bh_arr[i]);
+			submit_bh(WRITE, bh_arr[i]);
+		}
+	} e_HWp+	sun12B,_page(page);p+}
+
+4-
+68 A2_HWatt & map buffers for-page giveinOHeAextSnt map. W     it+out.
+68 except for-OHeAoriginal-page Sf(  w    page, OHdondsfcalled(on
+68 dela2_HW/unw   ten pages only, for-OHeAoriginal-page it,is possible
+68 tHatAOHeApage haon_t mappiigdatA 2_.
+ -/-+STATIC tic 
+xfs_c*nvert_page(p+Es,* Ok,inode		*inode,p+	s,* Ok,page		*page,p+Exfs_iomap_t		*iomapp,p+Evic s		*privatt,p+Eint	d	s,artio,p+Eint	d	a2__bh)p+{p+	s,* Ok,buffer_h ad	*bh_arr[MAX_BUF_PER_PAGE], *bh, *h ad;p+	xfs_iomap_t		*mp = iomapp, *tmp;p+Eunsigted long		end, offset;
+	pgoff_t		dend_indIx;
+	int	d	i =,0,AindIx =,0;
+sint	d	bbits = inode->i_blkbits;p+
+dend_indIx = i_snit_r ad(inode) >> PAGE_CACHE_SHIFT;
+	if (page->indIx < end_indIx)o{p+	send(= PAGE_CACHE_SIZE;
+	} e_HWo{p+EEend(= i_snit_r ad(inode) & (PAGE_CACHE_SIZE-1);p+	}
+	bh = h ad =,page_buffers(page);p+	doo{p+	soffset = i << bbits;p+		if (!(PageUptodatt(page) || buffer_uptodatt(bh)))p+	sEcontinue;p+		if (buffer_mapped(bh) && a2__bhd&&p+	s    !buffer_unw   ten(bh) && !buffer_delay(bh))o{p+	sEif (s,artio && (offset <,end))o{p+	sE	12B,_buffer(bh);
+		sEbh_arr[indIx++] = bh;
+		E}p+E	Econtinue;p+		}p+	stmp = xfs_offset_to_map(page, mp, offset);p+	sif (!tmp)p+	sEcontinue;p+		ASSERT(!(tmp->iomap_+c ls &+IOMAP_HOLE));p+E	ASSERT(!(tmp->iomap_+c ls &+IOMAP_DELAY));p+
+		/8 If OHdondsfa mew unw   ten extSnt buffer (i.e.(onep+	s * tHatAweAigafn't passed dn2privatt data for,AweAmustp+	s * now(map OHis buffer too.p+	s */p+		if (buffer_unw   ten(bh) && !bh->b_end_io)o{p+	sEASSERT(tmp->iomap_+c ls &+IOMAP_UNWRITTEN);
+	EExfs_map_unw   ten(inode, page, h ad, bh,p+E			doffset,(bbits, tmp, s,artio, a2__bh);
+	E} e_HWoif (! (buffer_unw   ten(bh) && buffer_12B,ed(bh)))o{p+	sExfs_map_at_offset(page, bh, offset,(bbits, tmp);
+			if (buffer_unw   ten(bh))o{p+	sE	set_buffer_unw   ten_io(bh);
+				bh->b_privatt =,privatt;
+		sEASSERT(privatt);
+		E}p+E	}
+	Eif (s,artio && (offset <,end))o{p+	sEbh_arr[indIx++] = bh;
+		} e_HWo{p+EEsun12B,_buffer(bh);
+		smark_buffer_dirty(bh);
+		}p+E} wHile (i++, (bh = bh->b_OHdo_page) !=+h ad);
+
+	if (s,artio)o{p+	sxfs_submit_page(page, bh_arr,AindIx);p+	} e_HWo{p+EEun12B,_page(page);p+	}p+}
+
+4-
+68 ConvertA& w     out a cluster Sf(pages in2OHeAsameAextSnt as  /homed
+68 by mpAand(fo2_Hwiig OHeAs,artApage.
+ -/-+STATIC tic 
+xfs_cluster_w    (p+Es,* Ok,inode		*inode,p+	pgoff_t		dtindIx,p+Exfs_iomap_t		*iomapp,p+Eint	d	s,artio,p+Eint	d	a2__bh,p+	pgoff_t		dtlast)p+{p+	s,* Ok,page		*page;
+
+	for-(; tindIx <= tlast; tindIx++)o{p+	spage = xfs_probe_dela2_HW_page(inode, tindIx);p+	Eif (!page)p+	E	br ak;p+	sxfs_c*nvert_page(inode, page, iomapp, ct a, s,artio, a2__bh);
+	}p+}
+
+4-
+68 Calliig OHdonwinvout s,artio set meansAweAare beiig asked to(mak  a dirty
+68 page r ady for-d/hoiigdit's buffers.  Whenfcalled(winv2s,artio set OHen
+68 weAare comiig fromrw    page.
+ -
+68 Whenfcalled(winv2s,artio set it,is importain tHatAweAw     OH uWHOLE
+68 page if possible.
+68 T/e bh->b_s,a e'sfcan_tyiknow(if( nyro++OHeAb12B,s or-whicv,b12B, forp+f* tHatAmatter are dirty dueAOormmap w    s, and(OH refore bh uptodatt,is
+68 only vaild i++OHeApage itself,isn't completely uptodatt.  SomeAlayers
+68 may clear+OHeApage dirty +c l,prior-Oorcalliig w     page, undIS OH 
+68 assumptISF OHeAentireApage wi2_ibe(w   ten out; by _tyiw   iig out OH 
+68 wholenpage tHeApage(canibe(reused before  2_ valc  dirty data is
+68 w   ten out.  Note: in2OHeAcase Sf(  page tHatAhaonbeen dirty' }by
+68 mapw     and(buk,particlly setup by b12B,_pr pare_w     OH 
+68 bh->b_s,a es'onwi2_i_tyiag/ho(and(only ones setup by BPW/BCWnwi2_iigaf
+68 valc  s,a e, OHus OHeAwholenpage mustibe(w   ten out yhiig.
+ -/-+
+STATIC int
+xfs_page_s,a e_convert(p+	s,* Ok,inode	*inode,p+	s,* Ok,page	*page,p+Eint	ds,artio,p+Eint	dunmapped) 4- also  mpliBs page uptodatt,-/-+{p+	s,* Ok,buffer_h ad	*bh_arr[MAX_BUF_PER_PAGE], *bh, *h ad;p+	xfs_iomap_t		*iomp, iomap;
+	loff_t		doffset;p+Eunsigted long           p_offset =,0;
+	__uint64_tt             end_offset;
+	pgoff_t                 end_indIx, last_indIx, tlast;p+	int	d	len, err,Ai, cin =,0,Auptodatt,=,1;p+	int	d	+c ls = s,artio ? 0 : BMAPI_TRYLOCK;p+	int	d	page_dirty =,1;p+	int                     dela2_HW = 0;
+
+
+	/8 Are wh off OHeAend(o++OHeA.ile ? */p+	offset = i_snit_r ad(inode);
+dend_indIx = offset >> PAGE_CACHE_SHIFT;
+	last_indIx = (offset - 1) >> PAGE_CACHE_SHIFT;
+	if (page->indIx >= end_indIx)o{p+	sif ((page->indIx >= end_indIx +d1) ||p+	s    !(i_snit_r ad(inode) & (PAGE_CACHE_SIZE - 1)))o{p+EEserr = -EIO;
+		sgoto(error;
+E	}
+	}p+p+	offset = (loff_t)page->indIx << PAGE_CACHE_SHIFT;p+Eend_offset = min_t(unsigted long long,p+E		offset + PAGE_CACHE_SIZE, i_snit_r ad(inode));
+
+	bh = h ad =,page_buffers(page);p+	iomp = ct a;p+
+	len = bh->b_snit;
+	doo{p+	sif (offset >= end_offset)p+	E	br ak;p+	sif (!buffer_uptodatt(bh))p+	sEuptodatt,=,0;p+		if (!(PageUptodatt(page) || buffer_uptodatt(bh)) && !s,artio)p+	sEcontinue;p+p+		if (iomp)o{p+	sEiomp = xfs_offset_to_map(page, &iomap, p_offset);p+	s}p+
+		/8p+	s * First case, map an unw   ten extSnt and(pr pare forp+	s68 extSnt s,a e conversISF transactISF SF completISF.p+	s */p+		if (buffer_unw   ten(bh))o{p+	sEif (!s,artio)p+	sEEcontinue;p+			if (!iomp)o{p+	sEserr = xfs_map_b12B,s(inode, offset,(len, &iomap,p+E			dEBMAPI_READ|BMAPI_IGNSTATE);
+	sE	if (err)o{p+	sEssgoto(error;
+E		E}p+E	EEiomp = xfs_offset_to_map(page, &iomap,p+E			dE		p_offset);
+		E}p+E		if (iomp)o{p+	sEsif (!bh->b_end_io)o{p+	sEEserr = xfs_map_unw   ten(inode, page,p+E			dE	h ad, bh, p_offset,p+EEEEEEEinode->i_blkbits, iomp,p+EEEEEE	s,artio, unmapped);
+E		E	if (err)o{p+	sEsssgoto(error;
+E		EE}p+E	EE} e_HWo{p+EEsE	set_bit(BH_L2B,, &bh->b_s,a e);
+E		E}p+E	EEBUG_ON(!buffer_12B,ed(bh));
+		sEbh_arr[cin++] = bh;
+		E	page_dirty =,0;
+		E}p+E	/8p+	s * Second case, a2_HWatt space for-ardela2_HW buffer.p+	s * We can,redirt EAGAIN H re2in2OHeAreleaseApage(case.
+	s */p+		} e_HWoif (buffer_delay(bh))o{p+	sEif (!iomp)o{p+	sEsdela2_HW = 1;p+	sEserr = xfs_map_b12B,s(inode, offset,(len, &iomap,p+E			dEBMAPI_ALLOCATE | fc ls);
+	sE	if (err)o{p+	sEssgoto(error;
+E		E}p+E	EEiomp = xfs_offset_to_map(page, &iomap,p+E			dE		p_offset);
+		E}p+E		if (iomp)o{p+	sEsxfs_map_at_offset(page, bh, p_offset,p+E			dEinode->i_blkbits, iomp);
+	sE	if (s,artio)o{p+	s	sEbh_arr[cin++] = bh;
+		E	} e_HWo{p+EEsE	un12B,_buffer(bh);
+		s	smark_buffer_dirty(bh);
+			E}p+E	EEpage_dirty =,0;
+		E}p+E	} e_HWoif ((buffer_uptodatt(bh) || PageUptodatt(page))d&&p+	ss   (unmapped || s,artio))o{p+p+	sEif (!buffer_mapped(bh))o{p+	sEsint	snit;
+p+	sEs/8p+	s	s * GetSIng H re2impliBs an unmapped bufferp+	s	s * was found, and(weAare in,a path where whp+	s	s * need to(w     OH uwholenpage out.
+	s	s */p+	sEsif (!iomp)o{p+	sEs	snit = xfs_probe_unmapped_cluster(p+EE			dEinode, page, bh, h ad);
+		sEserr = xfs_map_b12B,s(inode, offset,p+EEEEEE	snit, &iomap,p+E			dE	BMAPI_WRITE|BMAPI_MMAP);
+E		E	if (err)o{p+	sEsssgoto(error;
+E		EE}p+E	EEEiomp = xfs_offset_to_map(page, &iomap,p+E			dE		     p_offset);
+			E}p+E	EEif (iomp)o{p+	sEssxfs_map_at_offset(page,p+E			dE	bh, p_offset,p+EEEEEEEinode->i_blkbits, iomp);
+E		E	if (s,artio)o{p+	s	sEEbh_arr[cin++] = bh;
+		E		} e_HWo{p+EEsE		un12B,_buffer(bh);
+		s	ssmark_buffer_dirty(bh);
+			EE}p+E	EEEpage_dirty =,0;
+		EE}p+E	E} e_HWoif (s,artio)o{p+	s	sif (buffer_uptodatt(bh) &&p+	sss    !test_and_set_bit(BH_L2B,, &bh->b_s,a e))o{p+	s	sEbh_arr[cin++] = bh;
+		E	Epage_dirty =,0;
+		EE}p+E	E}
+E	}
+	} wHile (offset += len, p_offset += len,
+E	((bh = bh->b_OHdo_page) !=+h ad));
+
+	if (uptodatt,&& bh ==+h ad)
+E	SetPageUptodatt(page);
+
+	if (s,artio)
+	sxfs_submit_page(page, bh_arr,Acnt);
+
+	if (iomp)o{p+	stlast = (iomp->iomap_offset + iomp->iomap_bsnit - 1) >>
+		E	EPAGE_CACHE_SHIFT;
+		if (dela2_HW && (tlast > last_indIx))p+	sEtlast = last_indIx;p+	sxfs_cluster_w    (inode, page->indIx +d1, iomp,p+EEEEEs,artio, unmapped, tlast);p+	}
+
+	r dirt page_dirty;
+
+error:p+	for-(i =,0; i < cin; i++)o{p+	sun12B,_buffer(bh_arr[i]);
+	}p+p+	/8
+s68 Ifdit's dela2_HW and(weAigafRnowhere Oorput it,
+s68 throw(it away, unless OHeAlowerAlayers Oold
+s68 us Oo-try again.
+s68/
+	if (err != -EAGAIN)o{p+	sif (!unmapped) {p+	sEb12B,_flushpage(page, 0);
+		}p+E	ClearPageUptodatt(page);
+	}p+	r dirt err;
+}
+
+STATIC int
+1invfs_get_b12B,_cor (p+Es,* Ok,inode		*inode,p+	long			ib12B,,p+Es,* Ok,buffer_h ad	*bh_result,p+Eint	d	cr att,p+Eint	d	direct,p+Ebmapi_+c ls_t		+c ls)p+{p+	vnode_t			*vp = LINVFS_GET_VP(inode);
+	xfs_iomap_t		iomap;
+	int	d	retpbbm,=,1;p+	int	d	error;
+Essnit_t			snit;
+	loff_t		doffset = (loff_t)ib12B, << inode->i_blkbits;p+
+dsnit = 1 << inode->i_blkbits;p+	VOP_BMAP(vp, offset,Asnit,p+E	cr att ? fc ls : BMAPI_READ, &iomap, &retpbbm, error);p+	if (error)p+E	r dirt -error;
+p+	if (retpbbm,==,0)p+	Er dirt 0;
+
+	if (iomap.iomap_bn !=+IOMAP_DADDR_ct a)o{p+	sxfs_daddr_t		bn;
+		loff_t		ddelta;
+p+E	/8 For0unw   ten extSnts,do+_tyir portAa(disk,address(on
+	s * tHe r adAcase (tr at as if(wh're r adiigdinyoAa(hole).p+	s */p+		if (cr att || !(iomap.iomap_+c ls &+IOMAP_UNWRITTEN)) {p+	sEdelta =,offset - iomap.iomap_offset;
+			delta >>= inode->i_blkbits;p+
+d		bn = iomap.iomap_bn >> (inode->i_blkbits - BBSHIFT);
+			bn += delta;
+
+			bh_result->b_b12B,nr = bn;
+			set_buffer_mapped(bh_result);
+		}p+E	if (cr att && (iomap.iomap_+c ls &+IOMAP_UNWRITTEN)) {p+	sEset_buffer_unw   ten(bh_result);
+		Eset_buffer_delay(bh_result);
+		}p+E}p+p+	/8 If OHdondsfa r alSImeA.ile, data might be SF a mew device2-/-+	bh_result->b_dev = iomap.iomap_,arget->pbr_kdev;p+
+	/8 If(wh previously a2_HWattdAa(b12B, out beyond eSf( nd
+s68 weAare now(comiig baB, Oo ush it OHenAweAwi2_i_eed to
+s68 +c l,it as mew evein(++it,haona(disk,address.
+s68/
+	if (cr att &&
+s6   ((!buffer_mapped(bh_result) && !buffer_uptodatt(bh_result)) ||p+	     (offset >= i_snit_r ad(inode)))) {p+		set_buffer_mew(bh_result);
+	}
+
+	if (iomap.iomap_+c ls &+IOMAP_DELAY)o{p+	sif (unlokely(direct))p+	sEBUG();p+	Eif (cr att) {p+	sEset_buffer_mapped(bh_result);
+		}p+E	set_buffer_delay(bh_result);
+	}
+
+	r dirt 0;
+}-+
+int
+1invfs_get_b12B,(p+Es,* Ok,inode		*inode,p+	long			ib12B,,p+Es,* Ok,buffer_h ad	*bh_result,p+Eint	d	cr att)p+{p+	r dirt 1invfs_get_b12B,_cor (inode, ib12B,, bh_result,p+E		d	cr att,,0,ABMAPI_WRITE);p+}
+
+STATIC int
+1invfs_get_b12B,_sync(p+Es,* Ok,inode		*inode,p+	long			ib12B,,p+Es,* Ok,buffer_h ad	*bh_result,p+Eint	d	cr att)p+{p+	r dirt 1invfs_get_b12B,_cor (inode, ib12B,, bh_result,p+E		d	cr att,,0,ABMAPI_SYNC|BMAPI_WRITE);p+}
+
+STATIC int
+1invfs_get_b12B,_direct(p+Es,* Ok,inode		*inode,p+	long			ib12B,,p+Es,* Ok,buffer_h ad	*bh_result,p+Eint	d	cr att)p+{p+	r dirt 1invfs_get_b12B,_cor (inode, ib12B,, bh_result,p+E		d	cr att,,1,ABMAPI_WRITE|BMAPI_DIRECT);p+}
+
+STATIC int
+1invfs_bmap(p+Es,* Ok,address_space	*mappiig,p+Elong			b12B,)-+{p+Es,* Ok,inode		*inode = (s,* Ok,inodeA*)mappiig->host;p+	vnode_t			*vp = LINVFS_GET_VP(inode);
+	int	d	error;p+
+	vn_trace_Sntry(vp, "1invfs_bmap", (inst_tt*)__r dirt_address);
+
+	VOP_RWLOCK(vp, VRWLOCK_READ);p+	VOP_FLUSH_PAGES(vp, (xfs_off_t)0,A-1, 0,AFI_REMAPF, error);p+	VOP_RWUNLOCK(vp, VRWLOCK_READ);p+	r dirt generic_b12B,_bmap(mappiig,Ab12B,, 1invfs_get_b12B,_direct);p+}
+
+STATIC int
+1invfs_r adpage(p+Es,* Ok,.ile		*unused,p+	s,* Ok,page		*page)p+{p+	r dirt b12B,_r ad_full_page(page, 1invfs_get_b12B,);p+}
+
+STATIC tic 
+xfs_c*/in_page_s,a e(p+	s,* Ok,page		*page,p+Eint	d	*dela2_HW,p+Eint	d	*unmapped,p+Eint	d	*unw   ten)-+{p+	s,* Ok,buffer_h ad	*bh, *h ad;p+
+	*dela2_HW = *unmapped = *unw   ten =,0;
+
+	bh = h ad =,page_buffers(page);p+	doo{p+	sif (buffer_uptodatt(bh) && !buffer_mapped(bh))p+E		(*unmapped) = 1;p+	se_HWoif (buffer_unw   ten(bh) && !buffer_delay(bh))p+E		clear_buffer_unw   ten(bh);
+	se_HWoif (buffer_unw   ten(bh))p+E		(*unw   ten) = 1;p+	se_HWoif (buffer_delay(bh))p+E		(*dela2_HW) = 1;p+	} wHile ((bh = bh->b_OHdo_page) !=+h ad);
+}
+
+
+4-
+68 w    page: Called fromrtre o++Oworplaces:
+ -
+68 1. weAare flushiig ardela2_HW buffer head.
+ -
+68 2. weAare w   iig out a dirtyApage. Typically+OHeApage dirty
+68    s,a e dsfcleared before weAget here. In2OHdoncase dondt
+68    conceivablB weAigafRno buffer heads.
+ -
+68 For0dela2_HW space on2OHeApage(we need to(a2_HWatt space  nd
+68 +cush it. For0unmapped buffer heads on2OHeApage(we deGuld
+68 a2_HWatt space i++OHeApage is uptodatt. For0 nyroOH rndirty
+68 buffer heads on2OHeApage(we deGuld +cush OHem.
+ -
+68 If(wh detecn tHatAa transactISF wGuld benrequired to(+cushp+f* tH  page, weAigafROorcheB, OheAprocess(+c ls first, if(wh
+68 are  2r ady in,a transactISF Sr(disk,I/O duriig a2_HWatISFs
+ - isAo+f,(we need to(fai_ OH uw    page and(redirty+OHeApage.
+ -/-+
+STATIC int
+1invfs_w    page(p+	s,* Ok,page		*page)-+{p+	int	d	error;
+Eint	d	need_trans;
+Eint	d	dela2_HW, unmapped, unw   ten;p+Es,* Ok,inode		*inode = page->mappiig->host;p+
+	xfs_page_trace(XFS_WRITEPAGE_ENTER,,inode, page, 0);
+
+	/8
+s68 We need a transactISF if:
+s68  1. There are dela2_HW buffers on2OHeApage
+s68  2. TheApage is uptodatt and(weAigafRunmapped buffers
+s68  3. TheApage is uptodatt and(weAigafRno buffers
+s68  4. There are unw   ten buffers on2OHeApage
+s68/-+p+	if (!page_has_buffers(page)) {p+		unmapped = 1;p+	sneed_trans = 1;p+	} e_HWo{p+EExfs_c*/in_page_s,a e(page, &dela2_HW, &unmapped, &unw   ten);
+	sif (!PageUptodatt(page))p+E		unmapped = 0;p+	sneed_trans = dela2_HW +Runmapped + unw   ten;p+E}p+p+	/8
+s68 Ifdwe need a transactISF and(OH Aprocess(+c ls say
+s68 weAare  2r ady in,a transactISF,nor0no IOndsfa2_Hwed
+s68 OHenAmark+OHeApage dirty again and(legafROHeApage
+s68 as is.
+s68/
+p+	if ((PFLAGS_TEST_FSTRANS() || PFLAGS_TEST_NOIO()) && need_trans)p+E	goto(out_fai_;
+
+	/8
+s68 Delay hookiig up buffer heads /ini_ weAigaf
+s68 made our go/no-go decisISF.p+	68/
+	if (!page_has_buffers(page))p+E	cr att_ompty_buffers(page, inode->i_dev, 1 << inode->i_blkbits);
+
+	/8
+s68 ConvertAdelayed a2_HWatt, unw   ten or0unmapped space
+s68 Oo r al space  nd +cush out yo(disk.p+	68/
+	if (need_trans)p+E	PFLAGS_SET_NOIO();p+Eerror = xfs_page_s,a e_convert(inode, page, 1, unmapped);
+Eif (need_trans)p+E	PFLAGS_CLEAR_NOIO();p+Eif (error,==,-EAGAIN)p+E	goto(out_fai_;
+
+	if (unlokely(error,< 0))o{p+	sun12B,_page(page);p+		r dirt error;
+E}
+
+	r dirt 0;
+
+out_fai_:
+sSetPageDirty(page);
+Eun12B,_page(page);p+	r dirt 0;
+}-+
+4-
+68 Called to(move(  page inyoAcleanablB s,a e -  nd +romrOH re
+68 OoAbeAreleased. Possibly+OHeApage is  2r ady clean. We always
+ - igafRbuffer heads in2OHdonca2_.
+ -
+ - Redirts 0 i++OHeApage is ok Oo r lease, 1 oOH rwise.
+ -
+ - PossiblB scenariosAare:
+ -
+68 1. WeAare beiig called to(releaseA  page whicv,haonbeen w   ten
+68    to(via r gular,I/O.Rbuffer heads wi2_ibe(dirty and(possibly
+68    dela2_HW. Ifdnordela2_HW buffer heads in2OHdoncase OHenAwe
+68    can justir dirt zero.
+ -
+68 2. WeAare called to(releaseA  page whicv,haonbeen w   ten(via
+68    mmap,  2_ we need to(doodonensurerOH re don_trdela2_HW
+68    s,a e dn2OHeAbuffer heads,+(++_tyAweAcan,let OH ucaller
+68    d/ho(OHem and(weAdeGuld comeAbaB, later via w    page.
+ -/
+STATIC int
+1invfs_r lease_page(p+Es,* Ok,page		*page,p+Eint	d	gfp_mask)p+{p+	s,* Ok,inode		*inode = page->mappiig->host;p+Eint	d	dirty, dela2_HW, unmapped, unw   ten;p+
+	xfs_page_trace(XFS_RELEASEPAGE_ENTER,,inode, page, gfp_mask);p+
+	xfs_c*/in_page_s,a e(page, &dela2_HW, &unmapped, &unw   ten);
+	if (!dela2_HW && !unw   ten)-+		r dirt 1;
+
+	if (!(gfp_mask & __GFP_FS))p+	Er dirt 0;
+
+	/8 If(wh are  2r ady insideAa transactISF Sr(OH uchr adAcan_ty
+s68 dooI/O,AweAcan_tyir leaseAOHdonpage.p+	68/
+	if (PFLAGS_TEST_FSTRANS() || PFLAGS_TEST_NOIO())p+	Er dirt 0;
+
+	/8
+s68 ConvertAdela2_HW space Oo r al space,,do+_tyi+cush OHe
+s68 data out yo(disk, tHatAwi2_ibe(dtre byrOH ucaller.p+	68 Nmver need to(a2_HWatt space H re -AweAwi2_ialways
+s68 come baB, Oo w    page dn2OHat(case.
+	68/
+	dirty =,xfs_page_s,a e_convert(inode, page, 0, 0);p+	r dirt (dirty == 0 && !unw   ten) ? 1 : 0;
+}-+
+STATIC int
+1invfs_pr pare_w    (p+Es,* Ok,.ile		*.ile,p+Es,* Ok,page		*page,p+Eunsigted iit		+rom,p+Eunsigted iit		to)-+{p+	if (file && (+ile->f_+c ls &+O_SYNC))o{p+	sr dirt b12B,_pr pare_w    (page, +rom, Oo,p+EEEEEE1invfs_get_b12B,_sync);p+	} e_HWo{p+EEr dirt b12B,_pr pare_w    (page, +rom, Oo,p+EEEEEE1invfs_get_b12B,);
+	}p+}
+
+4-
+68 Initict uI/O SF a kiobuf o++user memory
+ -/
+STATIC int
+1invfs_direct_IO(p+Eint	d	rw,p+	s,* Ok,inode		*inode,p+	s,* Ok,kiobuf		*iobuf,p+Eunsigted long		b12B,nr,p+Eint	d	b12B,snit)p+{p+	s,* Ok,page		**maplist;p+Esnit_t			page_offset;
+	xfs_buf_t		*pb;
+	xfs_iomap_t		iomap;
+	int	d	niomap, error = 0;
+sint	d	pb_fc ls,,map_+c ls, pg_indIx =,0;
+ssnit_t			lengnv, total;
+	loff_t		doffset,(map_snit;
+	snit_t			snit;
+	vnode_t			*vp = LINVFS_GET_VP(inode);
+
+	/8 Note -  lnvoughrOH uiomap c*/ld igafRa 64-bit+snit,p+E68 kiobuf->lengnv2is only an,dl , sorOH umin(map_snit, lengnv)
+s68 Oest+wi2_ikeep us fromrtverf_Hwiig OHeApagebuf snit_t snit.
+	68/
+	total = lengnv2= iobuf->lengnv;
+	offset = b12B,nr;
+	offset <<= inode->i_blkbits;p+
+dmaplist2= iobuf->maplist;p+Epage_offset2= iobuf->offset;
+
+	map_+c ls = (rw ? BMAPI_WRITE : BMAPI_READ) | BMAPI_DIRECT;p+Epb_+c ls = (rw ? PBF_WRITE : PBF_READ) | PBF_FORCEIOn| PBF_DIRECTIO;
+	wHile (lengnv)o{p+EEniomap = 1;p+	sVOP_BMAP(vp, offset,Alengnv, map_+c ls, &iomap, &niomap, error);
+	sif (unlokely(!error && niomap &&p+	sss(iomap.iomap_+c ls &+IOMAP_DELAY)))o{p+#ifdef DEBUGp+	ssprdl ,(p+E"XFS: %s - direct IOn(%lld:%ld) inyoAa(delayed a2_HWatt extSnt?\n",p+EEEE__FUNCTION__, (long long)offset,A(long)lengnv);
+		Exfs_staB,_trace();
+#end(+
+		sVOP_BMAP(vp, offset,Alengnv, BMAPI_ALLOCATE,p+EEEEE&iomap, &niomap, error);
+	s}p+E	if (error)p+E		br ak;p+p+E	if (rw == WRITE)
+		sVMODIFY(vp);
+
+		BUG_ON(niomap != 1);p+		BUG_ON(iomap.iomap_+c ls &+IOMAP_DELAY);
+
+		map_snit = iomap.iomap_bsnit - iomap.iomap_delta;
+	dsnit = (snit_t)min(map_snit, (loff_t)lengnv);
+p+E	if ((iomap.iomap_+c ls &+IOMAP_HOLE) ||p+	s    ((iomap.iomap_+c ls &+IOMAP_UNWRITTEN) && rw == READ)) {p+	sEsnit_t	zero_len = snit;
+p+	sEif (rw == WRITE)
+		s	br ak;p+p+E		/8 Need to(zero,it a2_i*/p+	sEwHile (zero_len)o{p+	sE	s,* Ok,page	*page;p+	sE	snit_t		pg_len;p+
+				pg_len = min((snit_t)p+EEEEEE(PAGE_CACHE_SIZE - page_offset),p+EEEEEEzero_len);p+
+				page = maplist[pg_indIx];p+
+				memset(kmap(page) + page_offset, 0, pg_len);
+			E+cush_dcache_page(page);p+				kunmap(page);
+
+	EEEzero_len -=,pg_len;p+			sif ((pg_len + page_offset)o== PAGE_CACHE_SIZE)o{p+	s	sEpg_indIx++;p+E				page_offset =,0;
+		EE} e_HWo{p+EEsE	page_offset =,(page_offset + pg_len) &p+EEEEEE	~PAGE_CACHE_MASK;
+		EE}
+E	E}
+E	} e_HWo{p+EEsint	pg_c*/in;
+
+	EEpg_c*/in = (snit + page_offset + PAGE_CACHE_SIZE - 1)p+EEEEE>> PAGE_CACHE_SHIFT;
+		sif ((pb = pagebuf_lookup(iomap.iomap_,arget, offset,p+EEEEEEsnit, pb_+c ls))o== ct a)o{p+	s	Eerror = ENOMEM;
+		s	br ak;p+	EE}
+E	E/8 Need to(hook up pagebuf to(kiobuf pagesi*/p+	sEpb->pb_pagesi= &maplist[pg_indIx];p+	sEpb->pb_offset =,page_offset;
+	sEpb->pb_page_c*/in = pg_c*/in;
+	sEpb->pb_bn = iomap.iomap_bn + (iomap.iomap_delta >> BBSHIFT);
+
+	sEerror = pagebuf_ios,art(pb, pb_+c ls);
+		sif (!error && (iomap.iomap_+c ls &+IOMAP_UNWRITTEN)) {p+	sE	VOP_BMAP(vp, XFS_BUF_OFFSET(pb),p+EEEEEXFS_BUF_SIZE(pb),p+EEEEEBMAPI_UNWRITTEN, ct a, ct a, error);p+		s}p+
+			pagebuf_r le(pb);p+
+		sif (error)p+E			br ak;p+p+E		page_offset =,(page_offset + snit) & ~PAGE_CACHE_MASK;
+		Eif (page_offset)p+	sE	pg_c*/in--;
+	EEpg_indIx += pg_c*/in;
+	s}p+
+		offset += snit;
+		lengnv2-= snit;
+	}
+
+	if (error)p+E	r dirt -error;
+	r dirt (dl )(total - lengnv);
+}
+
+
+s,* Ok,address_space_operatISFs 1invfs_aops = {p+	.r adpage		= 1invfs_r adpage,p+E.w    page		= 1invfs_w    page,p+E.sync_page		= b12B,_sync_page,p+E.r leasepage		= 1invfs_r lease_page,p+E.pr pare_w    		= 1invfs_pr pare_w    ,p+E.commit_w    		= generic_commit_w    ,p+E.bmap			= 1invfs_bmap,p+E.direct_IO		= 1invfs_direct_IO,p+};
d(+f -Naur -p -X /home/marcelo/lib/dontd(+f linux-2.4.26/fs/xfs/linux-2.4/xfs_buf.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_buf.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_buf.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_buf.c	2004-07-30 16:26:01.000000000 +0000
@@ -0,0 +1,2306 @@
+4-
+68 Copyright (c) 2000-2004 SilicSF Graphics, Inc.  A2_ Rights Reserved.
+ -
+68 THdonprogram2is d/ho(software; you can,redistribu   it+and/or-mod(+yndt
+68 undIS OH  OermsAo++versISF 2(o++OHeAGNU General Public LicenseA s
+ - publishe }byrOHe F/ho(Software FoundatISF.p+ -
+68 THdonprogram2is distribu  d dn2OHeAhope2OHat(it wGuld benuseful,(buk
+68 WITHOUT ANY WARRANTY;nwinvout eveinOHeAimpliBd warrantyro+
+68 MERCHANTABILITY Sr(FITNESS FOR A PARTICULAR PURPOSE.
+ -
+68 FurOH r, OHdonsoftware2is distribu  d winvout  nyrwarrantyrOHat(it is
+68 d/ho(o++OHeArightful claim Sf( nyrOHdrd person,regardiigdinfriigemSnt
+68 oS OH  loke.  AnyrlicenseAprovid d H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only OorOHdonsoftware2+ile.  PatSnt licenses,+(+
+68 any,Aprovid d H rein,do+_tyiapply to(combinatISFs of OHdonprogram2winvp+f* oOH rnsoftware,nor0 nyroOH rnprod Ok,wHatsomver.
+ -
+68 You deGuld igafRreceived a copy(o++OHeAGNU General Public LicenseA long
+68 winv2OHdonprogram;+(++_ty,(w     OH uF/ho(Software FoundatISF, Inc., 59
+68 Temple Place - Su    330,ABos,on,MA 02111-1307, USA.
+ -
+68 ContaOk,informatISF: SilicSF Graphics, Inc., 1600 AmphiOH atre Pkwy,
+ - M*/inain View, CA  94043,nor:
+ -
+68 http://www.sgi.com
+ -
+68 For0furOH r,informatISF,regardiigdOHdon_tyice,,see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/-+
+4-
+68	TheAxfs_buf.c code provid s an abstract buffer cache-model on2Oop
+68	o++OHeALinuxApage(cache.  Cache  metadata b12B,s for-ar.ile system
+68	are hashe }OorOH uinodeAfor-OHeAb12B, device.  xfs_buf.c assembles
+68	buffers (xfs_buf_t) on2demand(Oo aggregatt such(cached pagesifor-I/O.
+ -
+68      W   ten by Stmve Lord, Jim Mos,ek, Russe2_ Cattelan
+68	s    and(Rajagopal Ananthanarayanat ("ananth")datASGI.
+ -
+68/-+
+#includeA<linux/stddef.h>
+#includeA<linux/errno.h>
+#includeA<linux/slab.h>
+#includeA<linux/pagemap.h>
+#includeA<linux/init.h>
+#includeA<linux/vma2_HW.h>
+#includeA<linux/blkdev.h>
+#includeA<linux/12B,s.h>
+#includeA<linux/sysctl.h>
+#includeA<linux/proc_fs.h>
+
+#includeA"xfs_linux.h"
+
+# /home BN_ALIGN_MASK	((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)p+p+#ifndef GFP_READAHEAD
+# /home GFP_READAHEAD	0
+#end(+
+
+4-
+68 A baB,portAo++OHeA2.5 schedul r,is used by(many+vendors of 2.4-based
+68 distribu ISFs.
+68 We can,only guess(it's pr seices}byrOHe laB, o++OHeASCHED_YIELD(+c l.
+68 If(OHeAheuristic doesn't work, change(OHdon /home byrhand.
+ -/
+#ifndef SCHED_YIELD
+# /home __HAVE_NEW_SCHEDULER	1
+#end(+
+
+4-
+68 cpumask_t,is used for-supportiigdNR_CPUS > BITS_PER_LONG.
+68 If(supportAfor-OHdondsfpr seit,(migrate_to_cpu exists and(provid s
+68 a(w apper around OHeAset_cpus_a2_Hwed routiie.
+ -/
+#ifdef copy_cpumask
+# /home __HAVE_CPUMASK_T	1
+#end(+
+
+#ifndef __HAVE_CPUMASK_T
+# ifndef __HAVE_NEW_SCHEDULER
+# n /home migrate_to_cpu(cpu)	\
+	doo{ curreit->cpus_a2_Hwed = 1UL << (cpu); } wHile (0)p+# e_HWp+# n /home migrate_to_cpu(cpu)	\
+	set_cpus_a2_Hwed(curreit, 1UL << (cpu))p+# end(+
+#end(+
+
+#ifndef VM_MAP
+# /home VM_MAP	VM_ALLOC
+#end(+
+
+4-
+68 File wideAglobals
+ -/-+
+STATIC kmem_cache_t *pagebuf_cache;
+STATIC kmem_shaker_t pagebuf_shake;
+
+# /home MAX_IO_DAEMONS		NR_CPUS
+# /home CPU_TO_DAEMON(cpu)	(cpu)
+STATIC int pb_logio_daemSFs[MAX_IO_DAEMONS];-+STATIC s,* Ok,list_h ad pagebuf_logiostre_tq[MAX_IO_DAEMONS];-+STATIC wait_queue_h ad_t pagebuf_logiostre_wait[MAX_IO_DAEMONS];-+STATIC int pb_dataio_daemSFs[MAX_IO_DAEMONS];-+STATIC s,* Ok,list_h ad pagebuf_dataiostre_tq[MAX_IO_DAEMONS];-+STATIC wait_queue_h ad_t pagebuf_dataiostre_wait[MAX_IO_DAEMONS];-+
+4-
+68 For-pre-a2_HWattdAbuffer head pool
+68/-+
+# /home NR_RESERVED_BH	64
+s,atic wait_queue_h ad_tEpb_r sv_bh_wait;
+s,atic spin12B,_t	Epb_r sv_bh_12B, = SPIN_LOCK_UNLOCKED;
+s,* Ok,buffer_h ad		*pb_r sv_bh = ct a;E/8 list2o++bv2-/-+int	d	Epb_r sv_bh_cin =,0;E/8 #2o++bv2availablB -/-+
+STATIC tic A_pagebuf_ioapply(xfs_buf_t *);-+STATIC int pagebuf_daemSF_wakeup(iit, unsigted iit);-+STATIC tic Apagebuf_delw  _queue(xfs_buf_t *, iit);-+STATIC tic Apagebuf_runa2__queues(s,* Ok,list_h ad[]);-+
+4-
+68 Pagebuf debugging
+68/-+
+#ifdef PAGEBUF_TRACE
+tic 
+pagebuf_trace(
+	xfs_buf_t	*pb,p+Echar		*id,p+Evic s	*data,p+Evic s	*ra)p+{p+	ktrace_Snter(pagebuf_trace_buf,p+E	pb, id,p+E	(tic A*)(unsigted long)pb->pb_+c ls,p+E	(tic A*)(unsigted long)pb->pb_hold.c*/iner,p+E	(tic A*)(unsigted long)pb->pb_sema.c*/in.c*/iner,p+E	(tic A*)curreit,p+E	data, ra,p+E	(tic A*)(unsigted long)((pb->pb_+ile_offset>>32) & 0xffffffff),p+E	(tic A*)(unsigted long)(pb->pb_+ile_offset & 0xffffffff),p+E	(tic A*)(unsigted long)pb->pb_buffer_1engnv,p+E	ct a, ct a, ct a, ct a, ct a);
+}
+ktrace_t *pagebuf_trace_buf;
+# /home PAGEBUF_TRACE_SIZE	4096
+# /home PB_TRACE(pb, id, data)	\
+	pagebuf_trace(pb, id, (tic A*)data, (tic A*)__builtii_r dirt_address(0))p+#e_HWp+# /home PB_TRACE(pb, id, data)	doo{ } wHile (0)p+#end(+
+
+#ifdef PAGEBUF_LOCK_TRACKINGp+#  /home PB_SET_OWNER(pb)	((pb)->pb_last_holder = curreit->pid)p+#  /home PB_CLEAR_OWNER(pb)	((pb)->pb_last_holder = -1)p+#  /home PB_GET_OWNER(pb)	((pb)->pb_last_holder)p+#e_HWp+#  /home PB_SET_OWNER(pb)	doo{ } wHile (0)p+#  /home PB_CLEAR_OWNER(pb)	doo{ } wHile (0)p+#  /home PB_GET_OWNER(pb)	doo{ } wHile (0)p+#end(+
+
+4-
+68 Pagebuf a2_HWatISF /-d/hoiig.
+68/-+
+# /home pb_to_gfp(+c ls) \
+	(((+c ls) & PBF_READ_AHEAD) ? GFP_READAHEAD : \
+	 ((+c ls) & PBF_DONT_BLOCK) ? GFP_NOFS : GFP_KERNEL)-+
+# /home pb_to_km(+c ls) \
+	 (((+c ls) & PBF_DONT_BLOCK) ? KM_NOFS : KM_SLEEP)
+
+
+# /home pagebuf_a2_HWatt(+c ls) \
+	kmem_ztre_a2_HW(pagebuf_cache, pb_to_km(+c ls))
+# /home pagebuf_dea2_HWatt(pb) \
+	kmem_ztre_d/ho(pagebuf_cache, (pb));-+
+4-
+68 Pagebuf hashing
+68/-+
+# /home NBITS	8
+# /home NHASH	(1<<NBITS)
+
+typedef s,* Ok,{p+	s,* Ok,list_h adEpb_hash;
+	spin12B,_t	Epb_hash_12B,;
+} pb_hash_n;
+
+STATIC pb_hash_nEpbhash[NHASH];
+# /home pb_hash(pb)	&pbhash[pb->pb_hash_indIx]-+
+STATIC int
+_bhash(p+Es,* Ok,b12B,_device2-bdev,
+	loff_t		base)-+{p+	int	dbit, hva_;
+
+	base >>= 9;
+	base ^= (unsigted long)bdev /-L1_CACHE_BYTES;
+	for-(bit+= hva_ =,0; base && bit <,snitof(base)68 8; bit += NBITS) {p+	shva_ ^= (iit)base & (NHASH-1);p+		base >>= NBITS;
+	}
+	r dirt hva_;
+}
+
+4-
+68 Mappiigdo++multi-page(buffers inyoAcontiguous virtual space
+68/-+
+typedef s,* Ok,a_list2{p+Evic s	*vm_addr;p+Es,* Ok,a_list	*mexk;
+} a_list_n;
+
+STATIC a_list_ns	*as_d/ho_h ad;p+STATIC int		as_list_len;p+STATIC spin12B,_t	as_l2B, = SPIN_LOCK_UNLOCKED;
+
+4-
+68 Try to(batch vunmaponbecause OHeyAare costly.
+ -/-+STATIC tic 
+d/ho_address(p+Evic s	*addr)-+{p+	a_list_ns*aSntry;
+
+	aSntry = kma2_HW(snitof(a_list_n), GFP_ATOMIC);
+	if (aSntry) {p+		spin_l2B,(&as_l2B,);p+		aSntry->mexk,= as_d/ho_h ad;p+		aSntry->vm_addr,= addr;p+E	as_d/ho_h ad,= aSntry;
+		as_list_len++;p+E	spin_un12B,(&as_l2B,);p+	} e_HWo{p+EEvunmap(addr);
+	}p+}
+
+STATIC tic 
+purgo_addresses(tic )-+{p+	a_list_ns*aSntry, *old;
+
+	if (as_d/ho_h ad,== ct a)p+E	r dirt;
+
+	spin_l2B,(&as_l2B,);p+	aSntry = as_d/ho_h ad;p+	as_d/ho_h ad,= ct a;p+	as_list_len =,0;
+sspin_un12B,(&as_l2B,);p+
+	wHile ((old,= aSntry) !=+ct a)o{p+	svunmap(aSntry->vm_addr);p+		aSntry,= aSntry->mexk;p+		kd/ho(old);
+	}p+}
+
+4-
+68	Iinernal-pagebuf object(manipulatISF
+ -/-+
+STATIC tic 
+_pagebuf_initiclnit(
+	xfs_buf_t		*pb,p+Exfs_buf,arg_t		*target,
+	loff_t			range_base,p+	snit_t			range_1engnv,p+Epage_buf_+c ls_t	+c ls)p+{p+	/8
+s68 We don't wain cernain +c ls Oo appear+dn2pb->pb_+c ls.
+	68/
+	+c ls &= ~(PBF_LOCK|PBF_MAPPED|PBF_DONT_BLOCK|PBF_READ_AHEAD);
+
+	memset(pb, 0,,snitof(xfs_buf_t));p+	aSomic_set(&pb->pb_hold, 1);p+	init_MUTEX_LOCKED(&pb->pb_iostresema);p+	INIT_LIST_HEAD(&pb->pb_list);p+	INIT_LIST_HEAD(&pb->pb_hash_1ist);p+	init_MUTEX_LOCKED(&pb->pb_sema); 4- held, no waiters 8/
+	PB_SET_OWNER(pb);p+Epb->pb_target,= target;p+Epb->pb_+ile_offset = range_base;p+	/8
+s68 Set buffer_1engnv and(c*/in_desired to(OHeAsameAvaluB initiclly.p+	68 I/O routiies deGuld use c*/in_desired, whicv,wi2_ibe(OHeAsameAin
+s68 most cases(buk,may beAreset (e.g. XFSRrectvery).
+	68/
+	pb->pb_buffer_1engnv = pb->pb_c*/in_desired = range_lengnv;
+	pb->pb_+c ls = +c ls | PBF_NONE;
+	pb->pb_bn = XFS_BUF_DADDR_ct a;p+	aSomic_set(&pb->pb_pin_c*/in, 0);p+	init_waitqueue_h ad(&pb->pb_waiters);
+
+	XFS_STATS_INC(pb_cr att);
+	PB_TRACE(pb, "initiclnit", target);
+}
+
+4-
+68 A2_HWatt   page array capablB o++holdiig arspecifiBd _umberp+f* of pages, and(pointAOHeApage buf at it.
+ -/
+STATIC int
+_pagebuf_get_pages(
+	xfs_buf_t		*pb,p+Eint	d	page_c*/in,p+Epage_buf_+c ls_t	+c ls)p+{p+	/8 Makt sure tHatAweAigaf   page list28/
+	if (pb->pb_pagesi==+ct a)o{p+	spb->pb_offset =,page_buf_poff(pb->pb_+ile_offset);p+		pb->pb_page_c*/in = page_c*/in;p+		if (page_c*/in <= PB_PAGES)o{p+	sEpb->pb_pagesi= pb->pb_page_array;
+	s} e_HWo{p+EEspb->pb_pagesi= kmem_a2_HW(snitof(s,* Ok,pageA*) 8p+	s	s	page_c*/in, pb_to_km(+c ls));
+		Eif (pb->pb_pagesi==+ct a)p+	s	sr dirt -ENOMEM;
+		}
+E	memset(pb->pb_pages, 0,,snitof(s,* Ok,pageA*) 8 page_c*/in);
+	}p+	r dirt 0;
+}-+
+4-
+68	F/hos pb_pagesi(++it,was ma2_HWed.
+ -/-+STATIC tic 
+_pagebuf_d/ho_pages(
+	xfs_buf_t	*bp)-+{p+	if (bp->pb_pagesi!=+bp->pb_page_array)o{p+	skmem_d/ho(bp->pb_pages,p+EEE +bp->pb_page_c*/in *,snitof(s,* Ok,pageA*));
+	}p+}
+
+4-
+68	R leases OHeAspecifiBd buffer.p+ -
+68 	TheAmod(+iWatISF s,a e Sf( nyrassociattdApagesi(s left unchanged.
+ - 	TheAbuffer most _tyibe SF any hash - use pagebuf_r le inst ad,forp+f* 	hashe }and(refc*/ined buffers
+ -/-+tic 
+pagebuf_d/ho(
+	xfs_buf_t		*bp)-+{p+	PB_TRACE(bp, "d/ho", 0);
+
+	ASSERT(list_ompty(&bp->pb_hash_1ist));
+
+	if (bp->pb_+c ls &+_PBF_PAGE_CACHE)o{p+	suint	di;
+p+E	if ((bp->pb_+c ls &+PBF_MAPPED) && (bp->pb_page_c*/in > 1))p+EEEd/ho_address(bp->pb_addr,-+bp->pb_offset);p+p+EEfor-(i =,0; i < bp->pb_page_c*/in; i++)
+E		page_cache_r lease(bp->pb_pages[i]);
+		_pagebuf_d/ho_pages(bp);p+	} e_HWoif (bp->pb_+c ls &+_PBF_KMEM_ALLOC)o{p+	s /8p+	s f* XXX(hch): bp->pb_c*/in_desired might be incorreOk,(seep+	s f* pagebuf_associatt_memoryAfor-denails),(bukAfortunatelyp+	s f* OHeALinuxAversISF Sf(kmem_d/ho igtores OHeAlen argumSnt..p+	s f*/p+	skmem_d/ho(bp->pb_addr, bp->pb_c*/in_desired);
+		_pagebuf_d/ho_pages(bp);p+	}p+p+Epagebuf_dea2_HWatt(bp);p+}-+
+4-
+68	Findsfa2_ pagesifor-buffer dn2questISF and(builds(it's page list.
+ -/
+STATIC int
+_pagebuf_lookup_pages(
+	xfs_buf_t		*bp,p+Euint	d	+c ls)p+{p+	s,* Ok,address_space	*mappiig =+bp->pb_,arget->pbr_mappiig;p+	snit_t			b12B,snit =+bp->pb_,arget->pbr_bsnit;
+	int	d	gfp_maski= pb_to_gfp(+c ls);
+	unsigted deGrts	page_c*/in, i;
+	pgoff_t		dfirst;
+	loff_t			end;
+	int	d	error;p+
+	end(= bp->pb_+ile_offset + bp->pb_buffer_1engnv;p+Epage_c*/in = page_buf_btHW(end) - page_buf_btHWt(bp->pb_+ile_offset);p+p+Eerror = _pagebuf_get_pages(bp, page_c*/in, +c ls);
+	if (unlokely(error))p+	Er dirt error;
+	bp->pb_+c ls |=+_PBF_PAGE_CACHE;p+p+Efirst(= bp->pb_+ile_offset >> PAGE_CACHE_SHIFT;
+
+	for-(i =,0; i < bp->pb_page_c*/in; i++) {p+		s,* Ok,page	*page;p+	suint	dr driesi= 0;
+
+	      r dry:p+		page = find_or_cr att_page(mappiig,Afirst(+Ai, gfp_mask);p+	sif (unlokely(page ==+ct a))o{p+	sEif (+c ls &+PBF_READ_AHEAD) {p+	sE	bp->pb_page_c*/in = i;
+		EEfor-(i =,0; i < bp->pb_page_c*/in; i++)
+E			sun12B,_page(bp->pb_pages[i]);
+			sr dirt -ENOMEM;
+		s}p+
+			/8p+	s	68 THdonc*/ld dead12B,.p+	s	68p+	s	68 But /ini_ a2_ OHeAXFSRlowlevel code donrevamped to
+ss	68 handleAbuffer a2_HWatISF fai_ures weAcan't do much.p+	s	68/p+	sEif (!(++r driesi% 100))p+	sE	prdl ,(KERN_ERR
+E			s"possible dead12B, dn2%s (mode:0x%x)\n",p+EEEEE__FUNCTION__, gfp_mask);p+
+			XFS_STATS_INC(pb_page_r dries);
+			pagebuf_daemSF_wakeup(0, gfp_mask);p+	s	set_curreit_s,a e(TASK_UNINTERRUPTIBLE);
+	sEschedul _SImeout(10);
+			goto(r dry;
+		}
+
+		XFS_STATS_INC(pb_page_found);p+
+		/8 if we need to(dooI/O SF a page rectrd OHeAfact */p+		if (!Page_Uptodatt(page))d{
+E		page_c*/in--;
+	EEif (b12B,snit == PAGE_CACHE_SIZE && (+c ls &+PBF_READ))p+	sE	bp->pb_12B,ed = 1;p+	s}
+
+		bp->pb_pages[i] = page;p+	}p+p+Eif (!bp->pb_12B,ed)d{
+E	for-(i =,0; i < bp->pb_page_c*/in; i++)
+E		un12B,_page(bp->pb_pages[i]);
+	}p+p+Eif (page_c*/in)d{
+E	/8 if we igaf  ny uptodatt pages, mark+OHat in2OHeAbuffer */p+		bp->pb_+c ls &= ~PBF_NONE;
+
+E	/8 if some pagesiarfn't uptodatt, mark+OHat in2OHeAbuffer */p+		if (page_c*/in !=+bp->pb_page_c*/in)
+E		bp->pb_+c ls |=+PBF_PARTIAL;
+	}p+p+EPB_TRACE(bp, "lookup_pages",A(long)page_c*/in);
+	r dirt error;
+}-+
+4-
+68	Map-buffer dnto(kernel address-space i++nessecary.
+ -/-+STATIC int
+_pagebuf_map_pages(
+	xfs_buf_t		*bp,p+Euint	d	+c ls)p+{p+	/8 A,snngleApage buff r,is always mappablB -/-+	if (bp->pb_page_c*/in == 1)d{
+E	bp->pb_addr,= page_address(bp->pb_pages[0]) + bp->pb_offset;
+	sbp->pb_+c ls |=+PBF_MAPPED;p+	} e_HWoif (+c ls &+PBF_MAPPED) {p+		if (as_list_len > 64)
+E		purgo_addresses();
+E	bp->pb_addr,= vmap(bp->pb_pages,+bp->pb_page_c*/in,p+EEEEVM_MAP, PAGE_KERNEL);p+	sif (unlokely(bp->pb_addr,==+ct a))p+EEEr dirt -ENOMEM;
+		bp->pb_addr,+= bp->pb_offset;
+	sbp->pb_+c ls |=+PBF_MAPPED;p+	}
+
+	r dirt 0;
+}-+
+4-
+68	Pre-a2_HWatISF Sf(a pool2o++buffer heads for-ush in
+68	low-memoryAsitua ISFs.
+68/-+
+4-
+68	_pagebuf_prea2_HW_bhp+ -
+68	Pre-a2_HWate(a pool2o++"c*/in"+buffer heads at s,artup.
+68	Puts(OHem SF a list2at "pb_r sv_bh"
+68	R dirts _umber2o++bv2actually a2_HWattdAOorpool.
+ -/-+STATIC int
+_pagebuf_prea2_HW_bh(p+Eint	d	c*/in)
+{p+	s,* Ok,buffer_h ad	*bh;
+	int	d	i;
+
+	for-(i =,0; i < c*/in; i++) {p+		bh = kmem_cache_a2_HW(bh_cachep, SLAB_KERNEL);p+	sif (!bh)p+	E	br ak;p+	sbh->b_pprevi= &pb_r sv_bh;p+	sbh->b_mexk,= pb_r sv_bh;p+	spb_r sv_bh = bh;p+	spb_r sv_bh_cin++;
+	}p+	r dirt i;
+}-+
+4-
+68	_pagebuf_get_prea2_HW_bhp+ -
+68	Get tre buffer head fromrtur-pre-a2_HWattdApool.
+ -	If pool2donempty, sleep 'ni_ tre comes baB, iF.p+ -	R dirts aforemSntISFtdAbuffer head.
+ -/-+STATIC s,* Ok,buffer_h ad -
+_pagebuf_get_prea2_HW_bh(tic )-+{p+	unsigted long		+c ls;p+	s,* Ok,buffer_h ad	*bh;
+	DECLARE_WAITQUEUE	(wait, curreit);
+
+	spin_l2B,_irqsgaf(&pb_r sv_bh_12B,, +c ls);
+p+Eif (pb_r sv_bh_cin < 1)d{
+E	add_wait_queue(&pb_r sv_bh_wait, &wait);p+	sdoo{p+	s	set_curreit_s,a e(TASK_UNINTERRUPTIBLE);
+	sEspin_un12B,_irqr stor (&pb_r sv_bh_12B,, +c ls);
+EEErun_,ask_queue(&tq_disk);
+	sEschedul ();
+	sEspin_l2B,_irqsgaf(&pb_r sv_bh_12B,, +c ls);
+		} wHile (pb_r sv_bh_cin < 1);
+		__set_curreit_s,a e(TASK_RUNNING);p+		r move_wait_queue(&pb_r sv_bh_wait, &wait);p+	}
+
+	BUG_ON(pb_r sv_bh_cin < 1);
+	BUG_ON(!pb_r sv_bh);
+p+Ebh,= pb_r sv_bh;p+	pb_r sv_bh = bh->b_mexk;p+	pb_r sv_bh_cin--;
+
+Espin_un12B,_irqr stor (&pb_r sv_bh_12B,, +c ls);
+Er dirt bh;
+}-+
+4-
+68	_pagebuf_d/ho_bhp+ -
+68	Takt care o++buffer heads tHatAwe're2+inishe }winv.p+ -	Ca2_ OHdondnst ad,o++justikmem_cache_d/ho(bh_cachep, bh)p+ -	wHenAyou're2dtre winv2a bh.p+ -
+68	If tur-pre-a2_HWattdApool2is dull,+justid/ho(OHeAbuffer head.
+ -	OOH rwise, put it baB, iFAOHeApool, and(wakt up anybodyp+ -	wa  iig for-one.
+ -/
+STATIC inlome tic 
+_pagebuf_d/ho_bh(p+Es,* Ok,buffer_h ad	*bh)-+{p+	unsigted long		+c ls;p+	int	d	+/ho;
+p+Eif (! (+/ho(= pb_r sv_bh_cin >= NR_RESERVED_BH)) {p+		spin_l2B,_irqsgaf(&pb_r sv_bh_12B,, +c ls);
+p+EEif (! (+/ho(= pb_r sv_bh_cin >= NR_RESERVED_BH)) {p+		sbh->b_pprevi= &pb_r sv_bh;p+	ssbh->b_mexk,= pb_r sv_bh;p+	sspb_r sv_bh = bh;p+	sspb_r sv_bh_cin++;
+
+	EEif (waitqueue_actIve(&pb_r sv_bh_wait)) {p+	sE	wakt_up(&pb_r sv_bh_wait);
+		s}p+	s}
+
+		spin_un12B,_irqr stor (&pb_r sv_bh_12B,, +c ls);
+E}p+Eif (+/ho)o{p+	skmem_cache_d/ho(bh_cachep, bh);
+	}p+}
+
+4-
+68	Findiig and(R adiigdBuffers
+ -/-+
+4-
+68	_pagebuf_dind
+68
+68	Looks up, and(cr attsi(++abseit,(a l2B,ablB buffer forp+f*	a giveinrange Sf( nuinode.  TheAbuffer donredirted
+68	12B,ed.	 If(oOH rntverlappiig buffers exist, OHeyAare
+68	released before OHeAmew buffer doncr att }and(12B,ed,p+ -	wHicv,may implyrOHat(OHdonca2_,wi2_ib12B, /ini_ those buffers
+ -	are un12B,ed.  NooI/O dondmpliBd byrOHdonca2_.
+ -/
+STATIC xfs_buf_t *
+_pagebuf_dind(	E	E/8 dind buffer forib12B,	-/-+	xfs_buf,arg_t		*target,/8 target,forib12B,		-/-+	loff_t			io+f,E/8 s,artiigdo+fset Sf(range	-/-+	snit_t			isnit,E/8 lengnv Sf(range		-/-+	page_buf_+c ls_t	+c ls,E/8 PBF_TRYLOCK			-/-+	xfs_buf_t		*mew_pb)/* newly a2_HWattdAbuffer	-/-+{
+	loff_t			range_base;p+	snit_t			range_lengnv;
+	int	d	hva_;
+Epb_hash_t		*v;
+	xfs_buf_t		*pb, *n;
+	int	d	not_12B,ed;
+
+	range_base = (ioff << BBSHIFT);
+	range_lengnv = (isnit << BBSHIFT);
+p+	/8 Ensurerwe never dooIOs smallerrOHan OHeAsector-snit -/-+	BUG_ON(range_lengnv < (1 << ,arget->pbr_sshift));
+
+	/8 Ensurerwe never dooIOs tHatAare notAsector-aligted -/-+	BUG_ON(range_base & (loff_t),arget->pbr_smask);p+
+	hva_ =,_bhash(,arget->pbr_bdev, range_base);
+	hi= &pbhash[hva_];
+
+	spin_l2B,(&h->pb_hash_12B,);p+
+	list_for_each_Sntry_safe(pb, n, &h->pb_hash, pb_hash_1ist) {p+		if (pb->pb_target,== target &&p+	s    pb->pb_+ile_offset == range_base &&p+	s    pb->pb_buffer_1engnv == range_lengnv) {p+	sE/8 If(wh look at somethiig briig it to(OHe
+ss	68 frontAo++OHeAlist2forimexk,SIme
+	s	68/p+	sEaSomic_inc(&pb->pb_hold);
+		slist_move(&pb->pb_hash_1ist, &h->pb_hash);
+			goto(found;p+	s}
+E}p+p+	/8 Noomatch found68/
+	if (new_pb) {p+	s_pagebuf_initiclnit(new_pb, target, range_base,p+EEEErange_1engnv, +c ls);
+		new_pb->pb_hash_indIx+= hva_;
+		list_add(&new_pb->pb_hash_1ist, &h->pb_hash);
+	} e_HWo{p+EEXFS_STATS_INC(pb_miss_12B,ed);p+	}
+
+	spin_un12B,(&h->pb_hash_12B,);p+	r dirt (new_pb);p+
+found:
+	spin_un12B,(&h->pb_hash_12B,);p+p+	/8 Attempt to(get OH usemaphore winvout sleepiig,p+E * i++OHdon oes+_tyAwork+OHen we need to(drop OHe
+s68 spin12B,}and(doAa(har }attempt on OH usemaphore.
+	68/
+	not_12B,ed = down_try12B,(&pb->pb_sema);
+	if (not_12B,ed)o{p+	sif (!(+c ls &+PBF_TRYLOCK)) {p+	sE/8 waitifor-buffer ownership68/p+	sEPB_TRACE(pb, "get_12B,", 0);
+			pagebuf_12B,(pb);p+EEEXFS_STATS_INC(pb_get_12B,ed_waited);
+		} e_HWo{p+EEs/8 We asked for-a try12B,}and(fai_ed, no need
+ss	68 to(look at .ile offset and(lengnv H re, whp+	s	68 know(OHat(OHdonpagebuf at(leastntverlaps turp+	s	68 pagebuf and((s l2B,ed,rOH refore tur-bufferp+	s	68 eiOH rndoes+_tyAexist, or donOHdonbufferp+	s	68/p+
+			pagebuf_r le(pb);p+EEEXFS_STATS_INC(pb_busy_12B,ed);p+	EEr dirt (ct a);
+E	}
+	} e_HWo{p+EE/8 try12B,}worked -/-+		PB_SET_OWNER(pb);p+E}p+p+Eif (pb->pb_+c ls &+PBF_STALE)
+		pb->pb_+c ls &=+PBF_MAPPED;p+	PB_TRACE(pb, "got_12B,", 0);
+	XFS_STATS_INC(pb_get_12B,ed);p+	r dirt (pb);p+}
+
+
+4-
+68	pagebuf_dind
+68
+68	pagebuf_dindnredirtona(buffer matchiig OHeAspecifiBd range Sf
+68	data for-OHeAspecifiBd target, if( nyro++OHeAr levain b12B,s
+ -	are iFAmemory.  TheAbuffer may igafRuna2_HWattdAholes,+(+
+68	some,(bukA_tyiall,+o++OHeAb12B,s are iFAmemory.  EveinwH re
+68	pagesiarffpr seit in2OHeAbuffer,A_tyiall+o++everyApage,may be
+68	va_id.
+ -/-+xfs_buf_t *
+pagebuf_dind(	E	E/8 dind buffer forib12B,	-/-+		E	E/8 i++OHeAb12B, dondFAmemory	-/-+	xfs_buf,arg_t		*target,/8 target,forib12B,		-/-+	loff_t			io+f,E/8 s,artiigdo+fset Sf(range	-/-+	snit_t			isnit,E/8 lengnv Sf(range		-/-+	page_buf_+c ls_t	+c ls)E/8 PBF_TRYLOCK			-/-+{p+	r dirt _pagebuf_dind(target, io+f,(isnit, +c ls, ct a);
+}
+
+4-
+68	pagebuf_get
+68
+68	pagebuf_get,assemblesna(buffer ctveriig OHeAspecifiBd range.
+ -	Some or-all+o++OHeAb12B,s in2OHeArange may beAva_id.  Storage
+68	dFAmemory for-a2_ portiSFs of OHeAbuffer wi2_ibe(a2_HWattd,p+ -	 lnvoughrbaB,iig storage may _tyibe.  If(PBF_READ donset in
+68	+c ls, pagebuf_ios,art donca2_ed a2so.
+ -/-+xfs_buf_t *
+pagebuf_get(	E	E/8 a2_HWate(a buffer		-/-+	xfs_buf,arg_t		*target,/8 target,foribuffer		-/-+	loff_t			io+f,E/8 s,artiigdo+fset Sf(range	-/-+	snit_t			isnit,E/8 lengnv Sf(range		-/-+	page_buf_+c ls_t	+c ls)E/8 PBF_TRYLOCK			-/-+{p+	xfs_buf_t		*pb, *new_pb;
+	int	d	error = 0, i;
+
+	new_pb = pagebuf_a2_HWatt(+c ls);
+	if (unlokely(!new_pb))p+	Er dirt ct a;p+
+Epb = _pagebuf_dind(target, io+f,(isnit, +c ls, new_pb);p+Eif (pb == new_pb) {p+	serror = _pagebuf_lookup_pages(pb, +c ls);
+		if (unlokely(error))d{
+E		prdl ,(KERN_WARNINGp+			       "pagebuf_get:(fai_ed to(lookup pages\n");
+			goto(no_buffer;
+E	}
+	} e_HWo{p+EEpagebuf_dea2_HWatt(new_pb);p+Esif (unlokely(pb,==+ct a))p+EEEr dirt ct a;p+	}
+
+	for-(i =,0; i < pb->pb_page_c*/in; i++)
+E	mark_page_accessed(pb->pb_pages[i]);
+p+Eif (!(pb->pb_+c ls &+PBF_MAPPED)) {p+	serror = _pagebuf_map_pages(pb, +c ls);
+		if (unlokely(error))d{
+E		prdl ,(KERN_WARNINGp+			       "pagebuf_get:(fai_ed to(map pages\n");
+			goto(no_buffer;
+E	}
+	}
+
+	XFS_STATS_INC(pb_get);p+p+E/8
+s68 Always fi2_iin2OHeAb12B, _umber2now,rOH umapped cases(can,do
+s68 OH ir ownntverlay of OHdonlater.
+	68/
+	pb->pb_bn = ioff;
+	pb->pb_c*/in_desired = pb->pb_buffer_1engnv;
+p+Eif (+c ls &+PBF_READ)o{p+	sif (PBF_NOT_DONE(pb))d{
+E		PB_TRACE(pb, "get_r ad",A(unsigted long)+c ls);
+EEEXFS_STATS_INC(pb_get_r ad);
+			pagebuf_ios,art(pb, +c ls);
+		} e_HWoif (+c ls &+PBF_ASYNC)d{
+E		PB_TRACE(pb, "get_r ad_async",A(unsigted long)+c ls);
+EEE/8p+	s	68 R ad ah adAca2_,wHicv,is  2r ady satisfiBd,p+	s	68 drop OHenbufferp+	s	68/p+			goto(no_buffer;
+E	} e_HWo{p+EEsPB_TRACE(pb, "get_r ad_dtre",A(unsigted long)+c ls);
+EEE/8 We do+_tyAwain r adAin2OHeA+c ls */p+	sEpb->pb_+c ls &= ~PBF_READ;
+E	}
+	} e_HWo{p+EEPB_TRACE(pb, "get_w    ",A(unsigted long)+c ls);
+E}
+
+	r dirt pb;
+
+no_buffer:p+Eif (+c ls &+(PBF_LOCK | PBF_TRYLOCK))p+EEpagebuf_un12B,(pb);p+Epagebuf_r le(pb);p+Er dirt ct a;p+}-+
+4-
+68 Cr att a skeletal-pagebuf (no pagesiassociattdAwinv2it).
+ -/-+xfs_buf_t *
+pagebuf_lookup(-+	xfs_buf,arg_t		*target,-+	loff_t			io+f,-+	snit_t			isnit,-+	page_buf_+c ls_t	+c ls)-+{p+	xfs_buf_t		*pb;
+p+E+c ls |=+_PBF_PRIVATE_BH;
+Epb = pagebuf_a2_HWatt(+c ls);
+	if (pb) {p+	s_pagebuf_initiclnit(pb, target, io+f,(isnit, +c ls);
+	}p+	r dirt pb;
+}
+
+4-
+68 If(wh are _tyAlow(oFAmemory OHen do+OHeAr adah adAin,a dead12B,
+68 safe(manner.p+ -/-+tic 
+pagebuf_r adah ad(-+	xfs_buf,arg_t		*target,-+	loff_t			io+f,-+	snit_t			isnit,-+	page_buf_+c ls_t	+c ls)-+{p+	+c ls |=+(PBF_TRYLOCK|PBF_READ|PBF_ASYNC|PBF_READ_AHEAD);
+	pagebuf_get(target, io+f,(isnit, +c ls);
+}
+
+xfs_buf_t *
+pagebuf_get_ompty(-+	snit_t			1en,p+Exfs_buf,arg_t		*target)-+{p+	xfs_buf_t		*pb;
+p+Epb = pagebuf_a2_HWatt(0);
+	if (pb)p+	s_pagebuf_initiclnit(pb, target, 0,Alen, 0);p+	r dirt pb;
+}
+
+s,atic inlome s,* Ok,pageA*
+mem_to_page(p+Evic s		*addr)-+{p+	if (((unsigted long)addr,< VMALLOC_START) ||p+	    ((unsigted long)addr,>= VMALLOC_END))o{p+	sr dirt virt_to_page(addr);
+	} e_HWo{p+EEr dirt vma2_HW_to_page(addr);
+	}
+}
+
+int
+pagebuf_associatt_memory(
+	xfs_buf_t		*pb,p+Evic s		*mem,-+	snit_t			1en)-+{p+	int	d	rva_;
+	int	d	i =,0;
+ssnit_t			ptr;
+ssnit_t			end, end_cur;
+soff_t		doffset;
+	int	d	page_c*/in;p+p+Epage_c*/in = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT;
+	offset =,(off_t)Amem - ((off_t)mem & PAGE_CACHE_MASK);
+	if (offset && (len > PAGE_CACHE_SIZE))p+EEpage_c*/in++;
+
+	/8 F/ho( nyrprevious set Sf(pageApointers 8/
+	if (pb->pb_pages)p+	s_pagebuf_d/ho_pages(pb);p+
+	pb->pb_pagesi= ct a;p+	pb->pb_addr,= mem;
+
+	rva_ =,_pagebuf_get_pages(pb, page_c*/in, 0);
+	if (rva_)p+	Er dirt rva_;
+
+	pb->pb_offset =,offset;
+	ptr = (snit_t) mem & PAGE_CACHE_MASK;
+	end(= PAGE_CACHE_ALIGN((snit_t) mem + len);
+	end_cur(= end;
+	/8 set upAfirst(pageA*/
+	pb->pb_pages[0],= mem_to_page(mem);p+
+	ptr,+= PAGE_CACHE_SIZE;
+	pb->pb_page_c*/in = ++i;
+	wHile (ptr,< end) {p+EEpb->pb_pages[i],= mem_to_page((tic A*)ptr);p+		pb->pb_page_c*/in = ++i;
+		ptr,+= PAGE_CACHE_SIZE;
+	}
+	pb->pb_12B,ed = 0;
+
+	pb->pb_c*/in_desired = pb->pb_buffer_1engnv = len;
+	pb->pb_+c ls |=+PBF_MAPPED | _PBF_PRIVATE_BH;
+
+	r dirt 0;
+}-+
+xfs_buf_t *
+pagebuf_get_no_daddr(-+	snit_t			1en,p+Exfs_buf,arg_t		*target)-+{p+	snit_t			ma2_HW_len =,len;
+	xfs_buf_t		*bp;p+Evic s		*data;
+	int	d	error;
+
+	bp = pagebuf_a2_HWatt(0);
+	if (unlokely(bp,==+ct a))p+EEgoto(fai_;
+s_pagebuf_initiclnit(bp, target, 0,Alen, PBF_FORCEIO);p+
+ try_again:p+Edata = kmem_a2_HW(ma2_HW_len, KM_SLEEP | KM_MAYFAIL);
+	if (unlokely(data ==+ct a))p+EEgoto(fai__d/ho_buf;
+
+	/8 cheB, wheOH rnaligtmSnt matches.. 8/
+	if ((__psunsigted_t)data !=p+	    ((__psunsigted_t)data & ~,arget->pbr_smask))d{
+E	/8 .. e_HWodoublB OHeAsnit and(Ory again */p+	skmem_d/ho(data, ma2_HW_len);p+		ma2_HW_len <<= 1;p+	sgoto(try_again;
+E}
+
+	error = pagebuf_associatt_memory(bp, data, len);
+	if (error)p+E	goto(fai__d/ho_mem;
+	bp->pb_+c ls |=+_PBF_KMEM_ALLOC;p+p+Epagebuf_un12B,(bp);
+
+	PB_TRACE(bp, "no_daddr", data);p+	r dirt bp;p+(fai__d/ho_mem:p+Ekmem_d/ho(data, ma2_HW_len);p+(fai__d/ho_buf:p+Epagebuf_d/ho(bp);p+(fai_:p+Er dirt ct a;p+}-+
+4-
+68Epagebuf_holdp+ -
+68	IncremSnt(refereice c*/in(oFAbuffer,Ato(hold OHeAbuffer concurreitlyp+ -	winv2anoOH rnchr adAwHicv,may r leaseA(+/ho)oOHeAbuffer asynchronously.
+ -
+68	Mustihold OHeAbuffer  2r ady yoAca2_ OHdonfunctISF.p+ -/-+tic 
+pagebuf_hold(
+	xfs_buf_t		*pb)-+{p+	aSomic_inc(&pb->pb_hold);
+	PB_TRACE(pb, "hold", 0);
+}-+
+4-
+68Epagebuf_r le
+68
+68	pagebuf_r le r leases aihold on OH uspecifiBd buffer.  If(OHe
+68	OHeAhold(c*/in,is 1, pagebuf_r le ca2_onpagebuf_d/ho.p+ -/-+tic 
+pagebuf_r lt(
+	xfs_buf_t		*pb)-+{p+	pb_hash_t		*vash = pb_hash(pb);
+
+	PB_TRACE(pb, "r lt", pb->pb_re_HW);
+p+Eif (aSomic_dec_and_12B,(&pb->pb_hold, &hash->pb_hash_12B,))o{p+	sint	ddo_+/ho(= 1;
+
+		if (pb->pb_re_HW)o{p+EEsaSomic_inc(&pb->pb_hold);
+		sspin_un12B,(&hash->pb_hash_12B,);
+		s(*(pb->pb_re_HW)) (pb);p+			spin_l2B,(&hash->pb_hash_12B,);
+		sdo_+/ho(= 0;
+E	}
+
+		if (pb->pb_+c ls &+PBF_DELWRI)o{p+	sEpb->pb_+c ls |=+PBF_ASYNC;p+EEsaSomic_inc(&pb->pb_hold);
+		spagebuf_delw  _queue(pb, 0);
+		sdo_+/ho(= 0;
+E	} e_HWoif (pb->pb_+c ls &+PBF_FS_MANAGED) {p+	sEdo_+/ho(= 0;
+E	}
+
+		if (do_+/ho) {p+	sElist_del_init(&pb->pb_hash_1ist);p+		sspin_un12B,(&hash->pb_hash_12B,);
+		sxfs_buf_d/ho(pb);
+		} e_HWo{p+EEsspin_un12B,(&hash->pb_hash_12B,);
+		}
+	}
+}
+
+
+4-
+68	Mutual exclusISF SFAbuffers.  LoB,iig model:
+ -
+68	BuffersiassociattdAwinv2inodes for-wHicv,buffer loB,iig
+68	ds+_tyAenablBd are _tyAprotectBd byrsemaphores, and(are
+68	assumed to(be exclusIvely owned byrOH ucaller.  There2is a
+68	spin12B,}in2OHeAbuffer,Aused by(OH ucaller wHenAconcurreit
+68	accessndsfpossible.
+68/-+
+4-
+68	pagebuf_cond_12B,
+68
+68	pagebuf_cond_12B, 12B,s a-buffer object,i(++it,ds+_tyA 2r ady 12B,ed.
+68	Note OHat(OHdonin2no way
+68	12B,s OHeAundISlyiig pages,+so+it,ds+only useful for-synchroniziig
+68	concurreit-ush Sf(pageAbuffer objects,A_tyifor-synchroniziig indIpendeit
+68	accessnto(OHeAundISlyiig pages.
+68/-+int
+pagebuf_cond_12B,(EEE/8 12B, buffer,A(++_tyA12B,ed	-/-+		E	E/8 redirton-EBUSYA(++12B,ed)	-/-+	xfs_buf_t		*pb)-+{p+	int	d	12B,ed;
+
+	12B,ed = down_try12B,(&pb->pb_sema) == 0;
+	if (12B,ed)o{p+	sPB_SET_OWNER(pb);p+E}p+	PB_TRACE(pb, "cond_12B,",A(long)12B,ed);p+	r dirt(12B,ed ? 0 :n-EBUSY);
+}-+
+4-
+68Epagebuf_12B,_valuB
+68
+68	R dirt 12B, valuB for-a pagebuf
+68/-+int
+pagebuf_12B,_valuB(
+	xfs_buf_t		*pb)-+{p+	r dirt(aSomic_r ad(&pb->pb_sema.c*/in));
+}-+
+4-
+68Epagebuf_12B,
+68
+68	pagebuf_12B, 12B,s a-buffer object.  Note OHat(OHdonin2no way
+68	12B,s OHeAundISlyiig pages,+so+it,ds+only useful for-synchroniziig
+68	concurreit-ush Sf(pageAbuffer objects,A_tyifor-synchroniziig indIpendeit
+68	accessnto(OHeAundISlyiig pages.
+68/-+int
+pagebuf_12B,(
+	xfs_buf_t		*pb)-+{p+	PB_TRACE(pb, "12B,", 0);
+	if (aSomic_r ad(&pb->pb_io_r mainiig))p+	Erun_,ask_queue(&tq_disk);
+	down(&pb->pb_sema);
+	PB_SET_OWNER(pb);p+EPB_TRACE(pb, "12B,ed", 0);
+	r dirt 0;
+}-+
+4-
+68	pagebuf_un12B,
+68
+68	pagebuf_un12B, r leases OHeAl2B, on2OHeAbuffer object(cr att }by
+68	pagebuf_12B, or-pagebuf_cond_12B, (_tyA ny
+68	pinniigdo++undISlyiig pages(cr att }by-pagebuf_pin).p+ -/-+tic 
+pagebuf_un12B,(	E	E/8 un12B, buffer		-/-+	xfs_buf_t		*pb)E/8 buffer to(un12B,		-/-+{p+	PB_CLEAR_OWNER(pb);
+	up(&pb->pb_sema);
+	PB_TRACE(pb, "un12B,", 0);
+}-+
+
+4-
+68	PinniigdBuffer Storagenin2Memory
+ -/
+
+4-
+68	pagebuf_pin
+68
+68	pagebuf_pin 12B,s all+o++OHeAmemory repr seitt }by-a-buffer in
+68	memory.  Multiple ca2_onto-pagebuf_pin and(pagebuf_unpin, forp+f*	OHeAsameAor-differeik,buffers affectiig argiveinpage, wi2_
+68	properly c*/in,OHeAmumber2o++outstandiig "pin" requests.  The
+68	buffer may be r leased(aftIS OH  pagebuf_pin and(a-differeik
+68	buffer used wHenAca2_iig pagebuf_unpin, if desired.
+68	pagebuf_pin deGuld benused by(OH u.ile system wHenAiyAwains be
+68	assured tHat(no attempt wi2_ibe(made to(forcB OHeAaffected
+68	memory Oo disk.	 Itndoes+_tyAassure tHatAargiveinlogical-pagep+ -	wi2_i_tyibe moved(Oo a-differeik,physical-page.p+ -/-+tic 
+pagebuf_pin(
+	xfs_buf_t		*pb)-+{p+	aSomic_inc(&pb->pb_pin_c*/in);
+	PB_TRACE(pb, "pin",A(long)pb->pb_pin_c*/in.c*/iner);
+}-+
+4-
+68Epagebuf_unpin
+68
+68	pagebuf_unpin reverses OHeAl2B,iigdo++memory performt }by
+68	pagebuf_pin.  Note OHat(bonv2functISFsAaffected OHeAl2gical
+68	pagesiassociattdAwinv2OHeAbuffer,A_tyiOHeAbuffer itself.p+ -/-+tic 
+pagebuf_unpin(
+	xfs_buf_t		*pb)-+{p+	if (aSomic_dec_and_test(&pb->pb_pin_c*/in))o{p+	swakt_up_a2_(&pb->pb_waiters);
+E}p+	PB_TRACE(pb, "unpin",A(long)pb->pb_pin_c*/in.c*/iner);
+}-+
+int
+pagebuf_ispin(
+	xfs_buf_t		*pb)-+{p+	r dirt aSomic_r ad(&pb->pb_pin_c*/in);
+}-+
+4-
+68Epagebuf_wait_unpin
+68
+68	pagebuf_wait_unpin waits /ini_ a2_ o++OHeAmemory associattdp+ -	winv2OHeAbuffer is+_tyA12nger loB, d dn2memory.  It redirto
+68	dmmt iatelyA(++_tno(o++OHeAaffected pagesiarff12B,ed.
+68/
+s,atic inlome tic 
+_pagebuf_wait_unpin(
+	xfs_buf_t		*pb)-+{p+	DECLARE_WAITQUEUE	(wait, curreit);
+
+	if (aSomic_r ad(&pb->pb_pin_c*/in) == 0)p+E	r dirt;
+
+	add_wait_queue(&pb->pb_waiters, &wait);p+	for-(;;) {p+		set_curreit_s,a e(TASK_UNINTERRUPTIBLE);
+	sif (aSomic_r ad(&pb->pb_pin_c*/in) == 0)p+E		br ak;p+	sif (aSomic_r ad(&pb->pb_io_r mainiig))p+	EErun_,ask_queue(&tq_disk);
+	sschedul ();
+	}p+	r move_wait_queue(&pb->pb_waiters, &wait);p+	set_curreit_s,a e(TASK_RUNNING);p+}-+
+
+4-
+68	Buffer Uni_ity Routiies
+ -/
+
+4-
+68	pagebuf_iostre
+68
+68	pagebuf_iostre marks a-buffer for-wHicv,I/O dondnnprogress
+68	dtre winv2respect(to(OHat(I/O.	TheApb_iostre routiie,+(+
+68	pr seit,(wi2_ibe(ca2_ed as a-side-effect.p+ -/-+tic 
+pagebuf_iostre_sched(p+Evic s		*v)-+{p+	xfs_buf_t		*bp = (xfs_buf_t *)v;
+
+	if (bp->pb_iostre)p+	E(*(bp->pb_iostre))(bp);p+	e_HWoif (bp->pb_+c ls &+PBF_ASYNC)p+	Exfs_buf_re_HW(bp);p+}-+
+tic 
+pagebuf_iostre(
+	xfs_buf_t		*pb,p+Eint	d	dataio,p+Eint	d	schedul )-+{p+	pb->pb_+c ls &= ~(PBF_READ | PBF_WRITE);
+	if (pb->pb_error == 0) {p+EEpb->pb_+c ls &= ~(PBF_PARTIAL | PBF_NONE);
+E}
+
+	PB_TRACE(pb, "iodtre",Apb->pb_iostre);
+
+	if ((pb->pb_iostre) || (pb->pb_+c ls &+PBF_ASYNC))o{p+	sif (schedul )o{p+EEsint	daemSF = CPU_TO_DAEMON(smp_processor_id());
+
+			INIT_TQUEUE(&pb->pb_iostre_sched,p+EEEEpagebuf_iostre_sched, (tic A*)pb);p+			queue_,ask(&pb->pb_iostre_sched, dataio ?p+EEEE&pagebuf_dataiostre_tq[daemSF] :p+EEEE&pagebuf_logiostre_tq[daemSF]);p+			wakt_up(dataio ?p+EEEE&pagebuf_dataiostre_wait[daemSF] :p+EEEE&pagebuf_logiostre_wait[daemSF]);
+		} e_HWo{p+EEspagebuf_iostre_sched(pb);
+		}
+	} e_HWo{p+EEup(&pb->pb_iostresema);p+	}
+}-+
+4-
+68Epagebuf_ioerror
+68
+68	pagebuf_ioerror sets OHeAerror codeAfor-a-buffer.p+ -/-+tic 
+pagebuf_ioerror(EEE/8 mark/clear+buffer error +c l -/-+	xfs_buf_t		*pb,E/8 buffer to(mark		-/-+	int	d	error)E/8 error to(stor  (0A(++_tno)	-/-+{p+	ASSERT(error >= 0 && error <= 0xffff);
+	pb->pb_error = (unsigted deGrt)error;
+	PB_TRACE(pb, "ioerror",A(unsigted long)error);
+}-+
+4-
+68Epagebuf_ios,art
+68
+68	pagebuf_ios,art dniticttsiI/O SF a buffer,Abased on2OHeA+c ls suppliBd.
+ -	If necessary, it wi2_iarrangeAfor-any disk space a2_HWatISF required,
+68	and((t wi2_ibr ak upAOHeAr quest i++OHeAb12B, mappiigs require it.
+ -	TheApb_iostre routiie in2OHeAbuffer suppliBd wi2_ionly be(ca2_edp+ -	wHen a2_ o++OHeAsubsidiary I/O requests, if( ny, igafRbeenAcompleted.
+68	pagebuf_ios,art ca2_ontH  pagebuf_iodnitictt routiie orp+f*	pagebuf_iorequest, i++OHeAformtr routiie is+_tyA /homed, to(start
+68	OHeAI/O SF a giveinlow-level request.
+68/-+int
+pagebuf_ios,art(EEE/8 s,art I/O SF a buffers f*/p+	xfs_buf_t		*pb,E/8 buffer to(s,art	s f*/p+	page_buf_+c ls_t	+c ls)E/8 PBF_LOCK,+PBF_ASYNC,+PBF_READ, -/-+		E	E/8 PBF_WRITE,+PBF_DELWRI,s f*/p+	sE	E/8 PBF_DONT_BLOCK	s f*/p+{p+	int	d	s,a usi= 0;
+
+	PB_TRACE(pb, "ios,art",A(unsigted long)+c ls);
+
+Eif (+c ls &+PBF_DELWRI)o{p+	spb->pb_+c ls &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC);p+	spb->pb_+c ls |= +c ls &+(PBF_DELWRI | PBF_ASYNC);p+	spagebuf_delw  _queue(pb, 1);
+		r dirt s,a us;
+E}
+
+	pb->pb_+c ls &= ~(PBF_READ | PBF_WRITE | PBF_ASYNC | PBF_DELWRI | \
+EEsPBF_READ_AHEAD | _PBF_RUN_QUEUES);
+	pb->pb_+c ls |= +c ls &+(PBF_READ | PBF_WRITE | PBF_ASYNC | \
+EEsPBF_READ_AHEAD | _PBF_RUN_QUEUES);
+
+	BUG_ON(pb->pb_bn == XFS_BUF_DADDR_ct a);p+p+E/8 For-w    s allow an alnernate s,*ategy routiie to-precede
+s68 OHeAactual I/O request (wHicv,may _tyibe issued ayiall+in
+s68 a-shutdownAsitua ISF, for example).
+	68/
+	s,a usi= (+c ls &+PBF_WRITE) ?p+EEpagebuf_ios,*ategy(pb) : pagebuf_iorequest(pb);
+
+	/8 Waitifor-I/O df(wh are _tyAan async request.
+s68 Note: async I/O request completISF wi2_ir leaseAOHeAbuffer,
+s68 and tHat(can alr ady be2dtre byrOHdonpoint.  So usiig OHe
+s68 buffer pointer fromrhere2SF, aftIS async I/O, dondnva_id.
+	 8/
+	if (!s,a usi&& !(+c ls &+PBF_ASYNC))p+	Es,a usi= pagebuf_iowait(pb);
+
+	r dirt s,a us;
+}-+
+
+4-
+68 Helptr routiies for-pagebuf_iorequest (pagebuf I/O completISF)
+ -/
+
+STATIC __inlome__ int
+_pagebuf_io12B,ed(
+	xfs_buf_t		*pb)-+{p+	ASSERT(pb->pb_+c ls &+(PBF_READ|PBF_WRITE));
+	if (pb->pb_,arget->pbr_bsnit < PAGE_CACHE_SIZE)
+		r dirt pb->pb_12B,ed;
+	if (pb->pb_+c ls &+PBF_READ)
+		r dirt pb->pb_12B,ed;
+	r dirt (pb->pb_+c ls &+_PBF_PAGE_CACHE);
+}-+
+STATIC tic 
+_pagebuf_iostre(
+	xfs_buf_t		*pb,p+Eint	d	schedul )-+{p+	int	d	i;
+
+	if (aSomic_dec_and_test(&pb->pb_io_r mainiig) !=+1)p+E	r dirt;
+
+	if (_pagebuf_io12B,ed(pb))p+	Efor-(i =,0; i < pb->pb_page_c*/in; i++)
+E		un12B,_page(pb->pb_pages[i]);
+	pb->pb_12B,ed = 0;
+spagebuf_iostre(pb, (pb->pb_+c ls &+PBF_FS_DATAIOD), schedul );
+}-+
+STATIC tic 
+_end_io_pagebuf(p+Es,* Ok,buffer_h ad	*bh,p+Eint	d	uptodatt,p+Eint	d	dullpage)
+{p+	s,* Ok,page		*page = bh->b_page;
+	xfs_buf_t		*pb = (xfs_buf_t *)bh->b_privatt;
+
+	mark_buffer_uptodatt(bh, uptodatt);
+	put_bh(bh);
+p+Eif (!uptodatt)o{p+	sSetPageError(page);p+	spb->pb_error = EIO;
+E}
+
+	if (+ullpage)o{p+EEun12B,_buffer(bh);
+	s_pagebuf_d/ho_bh(bh);
+		if (!PageError(page))
+E		SetPageUptodatt(page);
+	} e_HWo{p+EEs,atic spin12B,_t page_uptodatt_l2B, = SPIN_LOCK_UNLOCKED;
+	Es,* Ok,buffer_h ad *bp;p+E	unsigted long +c ls;p+p+E	ASSERT(PageL2B,ed(page));
+	Espin_l2B,_irqsgaf(&page_uptodatt_l2B,, +c ls);
+		clear_buffer_async(bh);
+		un12B,_buffer(bh);
+	sfor-(bp = bh->b_OHdo_page; bp != bh; bp = bp->b_OHdo_page)o{p+	sEif (buffer_12B,ed(bp)) {p+	sE	if (buffer_async(bp))p+	sE		br ak;p+	s	} e_HWoif (!buffer_uptodatt(bp))p+	sE	br ak;p+	s}
+	Espin_un12B,_irqr stor (&page_uptodatt_l2B,, +c ls);
+		if (bp == bhi&& !PageError(page))
+E		SetPageUptodatt(page);
+	}p+p+E_pagebuf_iostre(pb, 1);
+}-+
+STATIC tic 
+_pagebuf_end_io_complete_pages(
+	s,* Ok,buffer_h ad	*bh,p+Eint	d	uptodatt)
+{p+	_end_io_pagebuf(bh, uptodatt, 1);
+}-+
+STATIC tic 
+_pagebuf_end_io_partial_pages(
+	s,* Ok,buffer_h ad	*bh,p+Eint	d	uptodatt)
+{p+	_end_io_pagebuf(bh, uptodatt, 0);
+}-+
+4-
+68EHandliigdo++buf,args.
+68/-+
+tic 
+xfs_d/ho_buf,arg(-+	xfs_buf,arg_t		*btp,p+Eint	d	exnernal)-+{p+	xfs_flush_buf,arg(btp, 1);p+	if (exnernal)-+	Exfs_blkdev_put(btp->pbr_bdev);p+	kmem_d/ho(btp, snitof(*btp));
+}-+
+tic 
+xfs_incore_re_HW(-+	xfs_buf,arg_t		*btp,p+Eint	d	delw  _only,p+Eint	d	wait)-+{p+	d stroy_buffers(btp->pbr_kdev);p+	,* nWatt_inode_pages(btp->pbr_mappiig,A0 a);
+}
+
+tic 
+xfs_setsnit_buf,arg(-+	xfs_buf,arg_t		*btp,p+Eunsigted iit		b12B,snit,p+Eunsigted iit		sectorsnit)-+{p+	btp->pbr_bsnit =+b12B,snit;p+	btp->pbr_sshift = ffs(sectorsnit) - 1;p+	btp->pbr_smaski= sectorsnit - 1;p+p+	if (set_b12B,snit(btp->pbr_kdev, sectorsnit)) {p+	sprdl ,(KERN_WARNINGp+			"XFS: CannotAset_b12B,snit to-%u SF device20x%x\n",p+EEEsectorsnit, kdev_t_to_nr(btp->pbr_kdev));p+	}
+}-+
+xfs_buf,arg_t68
+xfs_a2_HW_buf,arg(-+	s,* Ok,b12B,_device	-bdev)-+{p+	xfs_buf,arg_t		*btp;p+p+	btp = kmem_za2_HW(snitof(*btp), KM_SLEEP);p+p+	btp->pbr_devi=  bdev->bd_dev;p+	btp->pbr_kdevi= to_kdev_t(btp->pbr_dev);p+	btp->pbr_bdevi= bdev;p+	btp->pbr_mappiig =+bdev->bd_inode->i_mappiig;p+	xfs_setsnit_buf,arg(btp, PAGE_CACHE_SIZE,p+EEE + (get_har sect_snit(btp->pbr_kdev));
+
+	switch (MAJOR(btp->pbr_dev)) {p+	case MD_MAJOR:p+	case EVMS_MAJOR:p+		btp->pbr_+c ls = PBR_ALIGNED_ONLY;
+		br ak;p+	case LVM_BLK_MAJOR:p+		btp->pbr_+c ls = PBR_SECTOR_ONLY;
+		br ak;p+	}
+
+	r dirt btp;p+}
+
+4-
+68 Initictt I/O SF part Sf(a page wh are inter sted ii
+ -/
+STATIC int
+_pagebuf_page_io(-+	s,* Ok,page		*page,E/8 Page s,* Okurerwe are dea2iig winv2-/-+	xfs_buf,arg_t		*pbr,E/8 device2parameters (bsz, ssz, dev)f*/p+	xfs_buf_t		*pb,E/8 pagebuf holdiig it, can be2ct af*/p+	xfs_daddr_t		bn,E/8 s,artiigdb12B, _umber2-/-+	snit_t			pg_offset,E/8 s,artiigdo+fset in(pageA*/
+	snit_t			pg_1engnv,	/8 c*/in(of data to-process -/-+	int	d	rw,E/8 read/w     operatISF -/-+	int	d	flush)-+{p+	snit_t			sector;p+	snit_t			blk_1engnv = 0;
+ss,* Ok,buffer_h ad	*bh, *h ad, *buffer1ist[MAX_BUF_PER_PAGE];p+Eint	d	sector_shift = pbr->pbr_sshift;p+Eint	d	i = 0, cin = 0;p+Eint	d	public_bh = 0;p+Eint	d	multi_ok;
+
+	if ((pbr->pbr_bsnit < PAGE_CACHE_SIZE) &&p+	 + (!(pb->pb_+c ls &+_PBF_PRIVATE_BH))o{p+	sint	dcache_ok;
+
+	dcache_ok = !((pb->pb_+c ls &+PBF_FORCEIO) || (rw == WRITE));
+		public_bh = multi_ok = 1;p+	ssector-= 1 << sector_shift;p+p+E	ASSERT(PageL2B,ed(page));
+	Eif (!page_has_buffers(page))
+E		cr att_ompty_buffers(page, pbr->pbr_kdev, sector);
+
+		ii= sector >> BBSHIFT;
+		bn -= (pg_offset >> BBSHIFT);
+
+		/8 Find buffer_heads belongiig Oo+justiOHdonpagebuf */p+		bh = h ad,= page_buffers(page);
+		doo{p+	s	if (buffer_uptodatt(bh) && cache_ok)p+	sE	continue;p+	sEif (b1k_lengnv < pg_offset)p+	sE	continue;p+	sEif (b1k_lengnv >= pg_offset + pg_1engnv)p+	sE	br ak;p+p+	sE12B,_buffer(bh);
+	s	get_bh(bh);
+		sbh->b_snit =+sector;p+		sbh->b_b12B,nr-= bn;p+		sbuffer1ist[cin++] = bh;p+p+	s} wHile ((bn += i),p+EEE (b1k_lengnv +=+sector),p+EEE  (bh = bh->b_OHdo_page) !=+h ad);
+
+		goto(r quest;p+	}
+
+	/8 Calculate+OHeAb12B, offsets and(lengnv we(wi2_ibe(usiig 8/
+	if (pg_offset)o{p+EEsnit_t		b12B,_offset;
+p+		b12B,_offset = pg_offset >> sector_shift;p+		b12B,_offset = pg_offset - (b12B,_offset << sector_shift);p+		b1k_1engnv = (pg_1engnv + b12B,_offset + pbr->pbr_smask) >>p+	sE			d	sector_shift;
+	} e_HWo{p+EEb1k_1engnv = (pg_1engnv + pbr->pbr_smask) >> sector_shift;p+	}
+
+	/8 THdonwi2_iattempt to(makt a request biggerrOHan OHeAsector
+s68 snit df(wh are we2_ialigted.
+	68/
+	switch (pb->pb_,arget->pbr_+c ls) {p+	case 0:p+	ssector-= b1k_lengnv << sector_shift;p+EEb1k_1engnv = 1;
+		br ak;p+	case PBR_ALIGNED_ONLY:
+	Eif ((pg_offset == 0) && (pg_1engnv == PAGE_CACHE_SIZE) &&p+	s    (((unsigted iin) bn) & BN_ALIGN_MASK) == 0) {p+EEssector-= b1k_lengnv << sector_shift;p+EEEb1k_1engnv = 1;
+			br ak;p+	s}
+	case PBR_SECTOR_ONLY:
+		/8 Fa2_through,AsameAasA /hault68/
+	 /hault:p+	ssector-= 1 << sector_shift;p+	}
+
+	/8 If(wh are doiig I/O largerrOHan OHeAbh->b_snit field OHen
+s68 we need to(splitiOHdonrequest up.
+	68/
+	wHile (sector > ((1t af<< NBBY *,snitof(bh->b_snit)) - 1)) {p+		sector >>= 1;
+		b1k_1engnv++;
+	}p+
+	multi_ok = (b1k_lengnv !=+1);p+Eii= sector >> BBSHIFT;
+
+	for-(; b1k_lengnv >,0; bn += i, b1k_lengnv--, pg_offset +=+sector) {p+		bh = kmem_cache_a2_HW(bh_cachep, SLAB_NOFS);
+	Eif (!bh)p+	E	bh =,_pagebuf_get_prea2_HW_bh();
+	Ememset(bh, 0, snitof(*bh));
+	Ebh->b_b12B,nr-= bn;p+		bh->b_snit =+sector;p+		bh->b_devi= pbr->pbr_kdev;p+	sset_buffer_12B,ed(bh);
+		set_bh_page(bh,npage, pg_offset);
+	Einit_waitqueue_h ad(&bh->b_wait);
+		aSomic_set(&bh->b_c*/in, 1);
+		buffer1ist[cin++] = bh;p+	}p+
+request:p+Eif (cin)d{
+E	vic s(*ca2_baB,)(s,* Ok,buffer_h ad *, iin);
+
+	dca2_baB, = (multi_ok && public_bh) ?p+EEEE_pagebuf_end_io_partial_pages :p+EEEE_pagebuf_end_io_complete_pages;
+
+		/8 Acc*/in(for-additISFal,buffers dnnprogress */p+		aSomic_add(cin, &pb->pb_io_r mainiig);
+
+#if /h RQ_WRITE_ORDERED
+	Eif (flush)-+			set_bit(BH_Order d_Flush, &buffer1ist[cin-1]->b_statt);
+#end(+
+
+	Efor-(i =,0; i < cin; i++) {p+			bh =,buffer1ist[i];p+	sEinit_buffer(bh, ca2_baB,, pb);
+		sbh->b_rdevi= bh->b_dev;
+		sbh->b_rsector-= bh->b_b12B,nr;-+			set_buffer_mapped(bh);
+		sset_buffer_async(bh);
+		sset_buffer_req(bh);
+		sif (rw == WRITE)p+EEEEset_buffer_uptodatt(bh);
+	s	generic_makt_request(rw, bh);
+	s}
+	Er dirt 0;
+	}
+
+	/8
+s68 We igaf nooI/O to(submit, let OH ucaller know(OHat
+s68 we igaf skipped tveriOHdonpage SntIrely.
+	68/
+	r dirt 1;
+}-+
+STATIC tic 
+_pagebuf_page_apply(
+	xfs_buf_t		*pb,p+Eloff_t		doffset,-+	s,* Ok,page		*page,-+	snit_t			pg_offset,
+	snit_t			pg_1engnv,p+Eint	d	last)-+{p+	xfs_daddr_t		bn = pb->pb_bn;
+	xfs_buf,arg_t		*pbr = pb->pb_,arget;p+Eloff_t		dpb_offset;
+	int	d	s,a us,Al2B,iig;
+
+	ASSERT(page);
+	ASSERT(pb->pb_+c ls &+(PBF_READ|PBF_WRITE));
+
+	if ((pbr->pbr_bsnit == PAGE_CACHE_SIZE) &&p+	    (pb->pb_buffer_1engnv < PAGE_CACHE_SIZE) &&p+	 + ((pb->pb_+c ls &+PBF_READ) && pb->pb_12B,ed) {p+		bn -= (pb->pb_offset >> BBSHIFT);
+		pg_offset(= 0;
+E	pg_1engnv = PAGE_CACHE_SIZE;
+	} e_HWo{p+EEpb_offset =,offset - pb->pb_+ile_offset;
+	Eif (pb_offset) {p+			bn += (pb_offset + BBMASK) >> BBSHIFT;
+		}
+	}
+
+	l2B,iigd=,_pagebuf_io12B,ed(pb);p+	if (pb->pb_+c ls &+PBF_WRITE) {
+	Eif (l2B,iigd&& !pb->pb_12B,ed)p+	sE12B,_page(page);
+		s,a usi= _pagebuf_page_io(page, pbr, pb, bn,p+EEEEpg_offset, pg_1engnv, WRITE,p+EEEElast && (pb->pb_+c ls &+PBF_FLUSH));
+	} e_HWo{p+EEs,atusi= _pagebuf_page_io(page, pbr, pb, bn,p+EEEEpg_offset, pg_1engnv, READ, 0);
+	}p+	if (s,a usi&& l2B,iigd&& !(pb->pb_,arget->pbr_bsnit < PAGE_CACHE_SIZE))p+	sun12B,_page(page);
+}-+
+4-
+68Epagebuf_iorequest -- OH ucor  I/O request routiie.
+68/-+int
+pagebuf_iorequest(EEE/8 s,art rea2 I/O		-/-+	xfs_buf_t		*pb)E/8 buffer to(convey Oo device	-/-+{p+	PB_TRACE(pb, "iorequest", 0);
+p+	if (pb->pb_+c ls &+PBF_DELWRI)o{p+	spagebuf_delw  _queue(pb, 1);
+		r dirt 0;
+	}
+
+	if (pb->pb_+c ls &+PBF_WRITE) {
+	E_pagebuf_wait_unpin(pb);p+E}p+p+Epagebuf_hold(pb);
+
+	/8 Set OH uc*/in,Oo 1 initiclly,iOHdonwi2_istop an I/O
+s68 completISF callout wHicv,happens before we igaf s,arted
+s * a2_ OHeAI/O fromrca2_iig pagebuf_iostre too early.
+	68/
+	aSomic_set(&pb->pb_io_r mainiig, 1);
+	_pagebuf_ioapply(pb);p+E_pagebuf_iostre(pb, 0);
+p+	pagebuf_r le(pb);p+Er dirt 0;
+}-+
+4-
+68	pagebuf_iowait
+68
+68	pagebuf_iowaitiwaits for-I/O to(complete on2OHeAbuffer suppliBd.
+ -	It redirto dmmt iatelyA(++_t,I/O donpendiig.  In-any case, it redirto
+68	OHeAerror code, if( ny, or 0 i++OHere is+_tAerror.
+68/-+int
+pagebuf_iowait(-+	xfs_buf_t		*pb)-+{p+	PB_TRACE(pb, "iowait", 0);
+	if (aSomic_r ad(&pb->pb_io_r mainiig))p+	Erun_,ask_queue(&tq_disk);
+	if ((pb->pb_+c ls &+PBF_FS_DATAIOD))p+EEpagebuf_runa2__queues(pagebuf_dataiostre_tq);
+	down(&pb->pb_iostresema);p+	PB_TRACE(pb, "iowaited", (long)pb->pb_error);
+	r dirt pb->pb_error;
+}-+
+caddr_t
+pagebuf_offset(
+	xfs_buf_t		*pb,p+Esnit_t			offset)p+{-+	s,* Ok,page		*page;
+p+	offset +=+pb->pb_offset;
+p+	page = pb->pb_pages[offset >> PAGE_CACHE_SHIFT];
+	r dirt (caddr_t) page_address(page) + (offset &+(PAGE_CACHE_SIZE - 1));
+}-+
+4-
+68	pagebuf_iomove
+ -
+68	Move data dnto(or-out Sf(a buffer.p+ -/-+tic 
+pagebuf_iomove(
+	xfs_buf_t		*pb,E/8 buffer to(process		-/-+	snit_t			bo+f,E/8 s,artiigdbuffer offset	-/-+	snit_t			bsnit,E/8 lengnv to(copy		-/-+	caddr_t			data,E/8 data address			-/-+	page_buf_rw_t		mode)E/8 read/w     +c l		-/-+{p+	snit_t			bend, cpo+f,(csnit;p+	s,* Ok,page		*page;
+p+	bend(= bo+f + bsnit;p+	wHile (bo+f < bend) {p+EEpage = pb->pb_pages[page_buf_btoct(bo+f + pb->pb_offset)];p+	scpo+f,= page_buf_po+f(bo+f + pb->pb_offset);p+	scsnit =+min_,(snit_t,p+EEE + (  PAGE_CACHE_SIZE-cpo+f,(pb->pb_c*/in_desired-bo+f);
+
+	dASSERT(((csnit + cpo+f) <= PAGE_CACHE_SIZE));
+
+	dswitch (mode) {p+EEcase PBRW_ZERO:p+EEEmemset(page_address(page) + cpo+f,(0,(csnit);
+		sbr ak;p+	scase PBRW_READ:p+EEEmemcpy(data, page_address(page) + cpo+f,(csnit);
+		sbr ak;p+	scase PBRW_WRITE:p+EEEmemcpy(page_address(page) + cpo+f,(data, csnit);
+		}
+
+		bo+f +=(csnit;p+	Edata +=(csnit;p+	}
+}-+
+4-
+68E_pagebuf_ioapply
+ -
+68	AppliBs _pagebuf_page_apply to(eachnpage o++OHeAxfs_buf_t.
+ -/
+STATIC tic 
+_pagebuf_ioapply(EEE/8 apply functISFnto-pages	-/-+	xfs_buf_t		*pb)E/8 buffer to(examiie		-/-+{p+	int	d	indIx;p+Eloff_t		dbuffer_offset = pb->pb_+ile_offset;
+	snit_t			buffer_1en = pb->pb_c*/in_desired;
+	snit_t			page_offset, len;
+	snit_t			cur_offset, cur_len;
+-+	cur_offset = pb->pb_offset;
+	cur_len =,buffer_len;
+-+	if (!pb->pb_12B,ed &&p+	 + ((pb->pb_,arget->pbr_bsnit < PAGE_CACHE_SIZE)) {p+EEfor-(indIx+= 0; indIx+< pb->pb_page_c*/in; indIx++)
+E		12B,_page(pb->pb_pages[indIx]);p+	spb->pb_12B,ed = 1;p+E}p+p+Efor-(indIx+= 0; indIx+< pb->pb_page_c*/in; indIx++) {
+	Eif (cur_len == 0)p+E		br ak;p+	sif (cur_offset >= PAGE_CACHE_SIZE) {p+			cur_offset -= PAGE_CACHE_SIZE;
+	E	continue;p+	s}
+
+		page_offset+= cur_offset;p+	scur_offset = 0;
+
+		len =,PAGE_CACHE_SIZE - page_offset;p+	sif (len > cur_len)
+E		1en =,cur_len;
+		cur_len -=,len;
+
+	E_pagebuf_page_apply(pb, buffer_offset,p+EEEEpb->pb_pages[indIx], page_offset, len,p+EEEEindIx++ 1 == pb->pb_page_c*/in);
+		buffer_offset +=+len;
+		buffer_1en -=,len;
+	}
+
+	/8
+s68 Run2OHeAb12B, device2,ask queue H re, wHile we igaf
+s * aihold on OH upagebuf (importain,Oo igaf tHat(hold).
+	 8/
+	if (pb->pb_+c ls &+_PBF_RUN_QUEUES)o{p+	spb->pb_+c ls &= ~_PBF_RUN_QUEUES;p+	sif (aSomic_r ad(&pb->pb_io_r mainiig) > 1)p+	EErun_,ask_queue(&tq_disk);
+	}
+}
+
+
+4-
+68 DelayBd w     buffer list2handliig
+ -/
+
+STATIC LIST_HEAD(pbd_delw  te_queue);
+STATIC spin12B,_t pbd_delw  te_l2B, = SPIN_LOCK_UNLOCKED;
+
+STATIC tic 
+pagebuf_delw  _queue(
+	xfs_buf_t		*pb,p+Eint	d	un12B,)-+{p+	PB_TRACE(pb, "delw  _q", (long)un12B,);
+	ASSERT(pb->pb_+c ls &+PBF_DELWRI);
+
+	spin_l2B,(&pbd_delw  te_l2B,);
+	/8 If(alr ady in2OHeAqueue, dequeue and(place an,Oail 8/
+	if (!list_ompty(&pb->pb_1ist)) {
+	Eif (un12B,)-+			aSomic_dec(&pb->pb_hold);
+		list_del(&pb->pb_1ist);
+	}
+
+	list_add_Oail(&pb->pb_1ist, &pbd_delw  te_queue);
+spb->pb_queueSIme = jiffies;
+sspin_un12B,(&pbd_delw  te_l2B,);
+
+Eif (un12B,)-+		pagebuf_un12B,(pb);p+}-+
+tic 
+pagebuf_delw  _dequeue(
+	xfs_buf_t		*pb)-+{p+	int	d	dequeued = 0;
+
+	spin_l2B,(&pbd_delw  te_l2B,);
+	if ((pb->pb_+c ls &+PBF_DELWRI)o&& !list_ompty(&pb->pb_1ist)) {
+	Elist_del_init(&pb->pb_1ist);p+		dequeued = 1;p+E}p+Epb->pb_+c ls &= ~PBF_DELWRI;
+sspin_un12B,(&pbd_delw  te_l2B,);
+
+Eif (dequeued)p+EEpagebuf_r le(pb);p+p+	PB_TRACE(pb, "delw  _dq", (long)dequeued);
+}
+
+
+4-
+68 TH upagebuf iostre daemSFs
+ -/
+
+STATIC int
+pagebuf_iostre_daemSF(p+Evic s		*__bind_cpu,p+Econst char		-namt,p+Eint	d	pagebuf_daemSFs[],-+	s,* Ok,list_h ad	pagebuf_iostre_tq[],-+	wait_queue_h ad_t	pagebuf_iostre_wait[])-+{p+	int	d	bind_cpu, cpu;
+sDECLARE_WAITQUEUE	(wait, curreit);
+
+	bind_cpu = (iin) (long)__bind_cpu;
+	cpu = CPU_TO_DAEMON(cpu_l2gical_map(bind_cpu));
+
+	/8  Set upAOHeAchr adA68/
+	 aemSFnit();
+
+	/8 Atic AsigtalsA*/
+	sngmask_l2B,();
+	sngfi2_set(&curreit->b12B,ed);p+	__r calc_sngpendiig(curreit);
+	sngmask_un12B,();
+
+	/8 Migrate+Oo+OHeAright CPUA*/
+	migrate_to_cpu(cpu);
+#if /h __HAVE_NEW_SCHEDULER
+Eif (smp_processor_id() !=+cpu)p+EEBUG();
+#e_sep+	wHile (smp_processor_id() !=+cpu)p+EEschedul ();
+#end(+
+
+	sprdl f(curreit->comm, "%s/%d", namt, bind_cpu);
+	INIT_LIST_HEAD(&pagebuf_iostre_tq[cpu]);p+	init_waitqueue_h ad(&pagebuf_iostre_wait[cpu]);p+	__set_curreit_s,a e(TASK_INTERRUPTIBLE);
+	mb();
+
+	pagebuf_daemSFs[cpu](= 1;
+
+	for-(;;) {p+		add_wait_queue(&pagebuf_iostre_wait[cpu], &wait);p+
+	Eif (TQ_ACTIVE(pagebuf_iostre_tq[cpu]))-+			__set_,ask_s,a e(curreit, TASK_RUNNING);p+	sschedul ();
+		r move_wait_queue(&pagebuf_iostre_wait[cpu], &wait);p+EErun_,ask_queue(&pagebuf_iostre_tq[cpu]);p+		if (pagebuf_daemSFs[cpu](== 0)p+E		br ak;p+	s__set_curreit_s,a e(TASK_INTERRUPTIBLE);
+	}
+
+	pagebuf_daemSFs[cpu](= -1;p+Ewakt_up_interruptible(&pagebuf_iostre_wait[cpu]);p+	r dirt 0;
+}-+
+STATIC tic 
+pagebuf_runa2__queues(-+	s,* Ok,list_h ad	pagebuf_iostre_tq[])-+{p+	int	pcpu, cpu;
+
+	for-(cpu = 0; cpu <+min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
+	Epcpu = CPU_TO_DAEMON(cpu_l2gical_map(cpu));
+
+	Erun_,ask_queue(&pagebuf_iostre_tq[pcpu]);p+	}
+}-+
+STATIC int
+pagebuf_12giostre_daemSF(p+Evic s		*__bind_cpu)-+{p+	r dirt pagebuf_iostre_daemSF(__bind_cpu, "xfs12gd",Apb_12gio_daemSFs,p+EEEpagebuf_12giostre_tq, pagebuf_logiostre_wait);
+}-+
+STATIC int
+pagebuf_dataiostre_daemSF(p+Evic s		*__bind_cpu)-+{p+	r dirt pagebuf_iostre_daemSF(__bind_cpu, "xfsdatad",Apb_dataio_daemSFs,p+EEEpagebuf_dataiostre_tq, pagebuf_dataiostre_wait);
+}
+
+
+4- Defiies for-pagebuf daemSF -/
+STATIC DECLARE_COMPLETION(pagebuf_daemSF_stre);
+STATIC s,* Ok,,ask_s,* Ok,*pagebuf_daemSF_,ask;
+STATIC int pagebuf_daemSF_active;
+STATIC int forcB_flush;
+
+
+STATIC int
+pagebuf_daemSF_waktup(-+	int	d	prio  ty,p+Eunsigted iit		mask)-+{p+	+orcB_flush = 1;p+Ebarrier();
+	wakt_up_process(pagebuf_daemSF_,ask);p+	r dirt 0;
+}-+
+STATIC int
+pagebuf_daemSF(p+Evic s		*data)p+{-+	s,* Ok,list_h ad	tmp;p+Eunsigted long		age;
+	xfs_buf_t		*pb, *n;-+	int	d	c*/in;p+p+E/8  Set upAOHeAchr adA68/
+	 aemSFnit();
+
+	/8 Mark it activef*/p+	pagebuf_daemSF_,ask =,curreit;p+	pagebuf_daemSF_activef= 1;p+Ebarrier();
+
+	/8 Atic AsigtalsA*/
+	sngmask_l2B,();
+	sngfi2_set(&curreit->b12B,ed);p+	__r calc_sngpendiig(curreit);
+	sngmask_un12B,();
+
+	s,*cpy(curreit->comm, "xfsbufd");
+	curreit->+c ls |=+PF_MEMALLOC;p+p+EINIT_LIST_HEAD(&tmp);
+	do {p+		set_curreit_s,a e(TASK_INTERRUPTIBLE);
+	sschedul _SImeout((xfs_buf_tImer_cSntIsecs68 HZ) / 100);
+p+		c*/in = 0;
+E	age = (xfs_buf_age_cSntIsecs68 HZ) / 100;
+	sspin_l2B,(&pbd_delw  te_l2B,);
+	Elist_+or_each_Sntry_safe(pb, n, &pbd_delw  te_queue,Apb_1ist)o{p+EEsPB_TRACE(pb, "walkq1", (long)pagebuf_ispin(pb));
+		sASSERT(pb->pb_+c ls &+PBF_DELWRI);
+
+		Eif (!pagebuf_ispin(pb)d&& !pagebuf_cond_12B,(pb))d{
+E		Eif (!+orcB_flush &&p+	sEE + (tIme_before(jiffies,p+EEEE	spb->pb_queueSIme + age))d{
+E		EEpagebuf_un12B,(pb);p+E	E		br ak;p+	s	s}
+
+		sEpb->pb_+c ls &= ~PBF_DELWRI;
+s	sEpb->pb_+c ls |=+PBF_WRITE;
+s	sElist_move(&pb->pb_1ist, &tmp);
+		d	c*/in++;
+		s}
+	E}
+	Espin_un12B,(&pbd_delw  te_l2B,);
+
+E	wHile (!list_ompty(&tmp))o{p+	sEpb =,list_ontry(tmp.next, xfs_buf_t,Apb_1ist);
+		slist_del_init(&pb->pb_1ist);p+		Epagebuf_ios,*ategy(pb);p+	s}
+
+		if (as_1ist_len > 0)p+E		purge_addresses();p+		if (c*/in)
+	EErun_,ask_queue(&tq_disk);
+
+EEforcB_flush = 0;
+	} wHile (pagebuf_daemSF_active);
+
+Ecomplete_and_exit(&pagebuf_daemSF_stre, 0);
+}-+
+4-
+68 Go+OHroughiall+incor  buffers, and(r leaseAbuffers d++OHey belong+Oo
+68 OHeAgiveindevice. THdondonused inu.ilesystem error handliig+Oo
+68 pr serve OH uc*nsistency of its metadata.
+68/-+int
+xfs_flush_buf,arg(
+	xfs_buf,arg_t		*target,-+	int	d	wait)-+{p+	s,* Ok,list_h ad	tmp;p+Exfs_buf_t		*pb, *n;-+	int	d	pincouin = 0;p+Eint	d	flush_cin = 0;p+p+	pagebuf_runa2__queues(pagebuf_dataiostre_tq);
+	pagebuf_runa2__queues(pagebuf_12giostre_tq);p+p+EINIT_LIST_HEAD(&tmp);
+	spin_l2B,(&pbd_delw  te_l2B,);
+	list_+or_each_Sntry_safe(pb, n, &pbd_delw  te_queue,Apb_1ist)o{p+p+		if (pb->pb_,arget !=+target)-+	E	continue;p+
+	sASSERT(pb->pb_+c ls &+PBF_DELWRI);
+EsPB_TRACE(pb, "walkq2", (long)pagebuf_ispin(pb));
+		if (pagebuf_ispin(pb))o{p+	sEpincouin++;
+		scontinue;p+	s}
+
+		pb->pb_+c ls &= ~PBF_DELWRI;
+s	pb->pb_+c ls |=+PBF_WRITE;
+s	list_move(&pb->pb_1ist, &tmp);
+	}
+sspin_un12B,(&pbd_delw  te_l2B,);
+
+E/8
+s68 Dropped OH udelayBd w     list2l2B,, now(walkAOHeAcemporary list
+	 8/
+	list_+or_each_Sntry_safe(pb, n, &tmp,Apb_1ist)o{p+p+		if (wait)-+	sEpb->pb_+c ls &= ~PBF_ASYNC;p+EEe_sep+		slist_del_init(&pb->pb_1ist);p+
+EEpagebuf_12B,(pb);p+E	pagebuf_ios,*ategy(pb);p+p+		if (++flush_cin > 32)o{p+	sErun_,ask_queue(&tq_disk);
+	s	flush_cin = 0;p+		}
+	}
+
+	run_,ask_queue(&tq_disk);
+
+E/8
+s68 R mainiig list2   ms mustib  +cusht }before r dirtiig
+	68/
+	wHile (!list_ompty(&tmp))o{p+	spb =,list_ontry(tmp.next, xfs_buf_t,Apb_1ist);
+
+s	list_del_init(&pb->pb_1ist);p+		p+		xfs_iowait(pb);
+	Exfs_buf_re_HW(pb);p+E}p+p+Er dirt pincouin;
+}-+
+STATIC int
+pagebuf_daemSF_s,art(tic )-+{p+	int	dcpu, pcpu;
+
+	kernel_chr ad(pagebuf_daemSF,2ct a, CLONE_FS|CLONE_FILES|CLONE_VM);
+
+	for-(cpu = 0; cpu <+min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
+	Epcpu = CPU_TO_DAEMON(cpu_l2gical_map(cpu));
+
+	Eif (kernel_chr ad(pagebuf_12giostre_daemSF,p+EEEE(tic A*)(long) cpu,p+EEEECLONE_FS|CLONE_FILES|CLONE_VM) <+0) {p+EEsprdl ,("pagebuf_12giostre daemSF fai_ed to(s,art\n");p+	s} e_HWo{p+EEswHile (!pb_12gio_daemSFs[pcpu])p+EEEEyield();p+		}
+	}
+	for-(cpu = 0; cpu <+min(smp_num_cpus, MAX_IO_DAEMONS); cpu++) {
+	Epcpu = CPU_TO_DAEMON(cpu_l2gical_map(cpu));
+
+	Eif (kernel_chr ad(pagebuf_dataiostre_daemSF,p+EEEE(tic A*)(long) cpu,p+EEEECLONE_FS|CLONE_FILES|CLONE_VM) <+0) {p+EEsprdl ,("pagebuf_dataiostre daemSF fai_ed to(s,art\n");p+	s} e_HWo{p+EEswHile (!pb_dataio_daemSFs[pcpu])p+EEEEyield();p+		}
+	}
+	r dirt 0;
+}-+
+4-
+68 pagebuf_daemSF_stop
+ -
+68 Note: do+_tyAmarkAasA__exit,+it,ds+ca2_ed fromrpagebuf_terminate.
+ -/
+STATIC tic 
+pagebuf_daemSF_stop(tic )-+{p+	int	dcpu, pcpu;
+
+	pagebuf_daemSF_activef= 0;p+Ebarrier();
+	wait_+or_completISF(&pagebuf_daemSF_stre);
+
+	for-(pcpu = 0; pcpu <+min(smp_num_cpus, MAX_IO_DAEMONS); pcpu++) {
+	Ecpu = CPU_TO_DAEMON(cpu_l2gical_map(pcpu));
+
+	Epb_12gio_daemSFs[cpu](= 0;p+		wakt_up(&pagebuf_logiostre_wait[cpu]);p+		wait_eveit_interruptible(pagebuf_logiostre_wait[cpu],p+EEEEpb_12gio_daemSFs[cpu](== -1);
+
+	Epb_dataio_daemSFs[cpu](= 0;p+		wakt_up(&pagebuf_dataiostre_wait[cpu]);p+		wait_eveit_interruptible(pagebuf_dataiostre_wait[cpu],p+EEEEpb_dataio_daemSFs[cpu](== -1);
+	}
+}-+
+4-
+68EIniticlniatISF and(TerminatISF
+ -/
+
+int __init
+pagebuf_init(tic )-+{p+	int	d	i;
+
+	pagebuf_cache = kmem_cache_cr att("xfs_buf_t", snitof(xfs_buf_t),(0,p+EEESLAB_HWCACHE_ALIGN,2ct a, ct a);p+	if (pagebuf_cache ==+ct a) {p+	sprdl ,("XFS: cGuldn't dnit xfs_buf_t cache\n");p+	sr dirt -ENOMEM;p+E}p+p+Eif (_pagebuf_prea2_HW_bh(NR_RESERVED_BH) <+NR_RESERVED_BH) {p+	sprdl ,("XFS: cGuldn't a2_HWatt %d(r served buffers\n",p+EEENR_RESERVED_BH);p+	skmem_ztre_d stroy(pagebuf_cache);p+	sr dirt -ENOMEM;p+E}p+	init_waitqueue_h ad(&pb_resv_bh_wait);p+
+#if /h PAGEBUF_TRACE
+	pagebuf_,*ace_buf = k,*ace_a2_HW(PAGEBUF_TRACE_SIZE, KM_SLEEP);p+#end(+
+
+	pagebuf_daemSF_s,art();
+
+	pagebuf_shakt = kmem_shakt_register(pagebuf_daemSF_waktup);p+	if (pagebuf_shakt ==+ct a) {p+	spagebuf_terminate();p+	sr dirt -ENOMEM;p+E}p+p+Efor-(i =,0; i < NHASH; i++) {p+		spin_l2B,_init(&pbhash[i].pb_hash_12B,);
+		INIT_LIST_HEAD(&pbhash[i].pb_hash);p+E}p+p+Er dirt 0;
+}-+
+4-
+68	pagebuf_terminate.
+ -
+68	Note: do+_tyAmarkAasA__exit,+tHdondonalso+ca2_ed fromrOHeA__init code.p+ -/-+tic 
+pagebuf_terminate(tic )-+{p+	pagebuf_daemSF_stop();p+
+#if /h PAGEBUF_TRACE
+	k,*ace_d/ho(pagebuf_,*ace_buf);p+#end(+
+
+	kmem_ztre_d stroy(pagebuf_cache);p+	kmem_shakt_der gister(pagebuf_shakt);
+}-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_buf.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_buf.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_buf.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_buf.h	2004-07-30 16:30:42.000000000 +0000
@@ -0,0 +1,633 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+4-
+68 W   ten}by(Steve Lord, Jim Mostek, Russe2_iCattelan at SGI
+ -/
+
+#ifn /h __XFS_BUF_H__
+# /home __XFS_BUF_H__
+
+#include <linux/versISF.h>
+#include <linux/config.h>
+#include <linux/1ist.h>
+#include <linux/types.h>
+#include <linux/spin12B,.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/uio.h>
+
+4- nptl-patch changes wher  OH usngmask_l2B,ndond/homed -/
+#if /h CLONE_SIGNAL /8 s,2B,n-/
+# /home sngmask_l2B,()	Espin_l2B,_irq(&curreit->sngmask_l2B,);p+# /home sngmask_un12B,()Espin_un12B,_irq(&curreit->sngmask_l2B,);p+# /home __r calc_sngpendiig(x)	r calc_sngpendiig(x)
+#e_se 4- nptl--/
+# /home sngmask_l2B,()	Espin_l2B,_irq(&curreit->snghand->sngl2B,);p+# /home sngmask_un12B,()Espin_un12B,_irq(&curreit->snghand->sngl2B,);p+# /home __r calc_sngpendiig(x)	r calc_sngpendiig()p+#end(+
+4-
+68	BaseAOypes
+ -/
+
+# /home XFS_BUF_DADDR_ct a ((xfs_daddr_t) (-1 a))
+
+# /home page_buf_ctob(pp)	((pp)68 PAGE_CACHE_SIZE)
+# /home page_buf_btoc(dd)	(((dd) +,PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+# /home page_buf_btoct(dd)	((dd) >> PAGE_CACHE_SHIFT)
+# /home page_buf_po+f(aa)	((aa) & ~PAGE_CACHE_MASK)
+
+Oype /h enum page_buf_rw_Wo{p+EPBRW_READf= 1,EEE/8 ,*ansfer inOo+Oarget memory 8/
+	PBRW_WRITEf= 2,EEE/8 ,*ansfer fromrOarget memory 8/
+	PBRW_ZEROf= 3EEE/8 Zero+Oarget memory 8/
+} page_buf_rw_n;p+p+
+Oype /h enum page_buf_+c ls_Wo{EE/8 pb_+c ls valuBs 8/
+	PBF_READf= (1 << 0),E/8 buffer intended for-r adiig fromrdevice28/
+	PBF_WRITEf= (1 << 1),E/8 buffer intended for-w   iig Oo+device2 28/
+	PBF_MAPPEDf= (1 << 2),  /8 buffer mapped (pb_addr va_id)           8/
+	PBF_PARTIAL = (1 << 3), /8 buffer partially r adA6666666666666666668/
+	PBF_ASYNC = (1 << 4),   /8 dnitictor-wi2_i_tyiwaitifor-completISF 68/
+	PBF_NONE = (1 << 5),    /8 buffer _tyir adAayiall+666666666666666668/
+	PBF_DELWRI = (1 << 6),  /8 buffer hasA irty pagesi666666666666666668/
+	PBF_STALE = (1 << 7),E/8 buffer hasAbeenAstaled, do+_tyAfind((t 68/
+	PBF_FS_MANAGEDf= (1 << 8),  /8 .ilesystem controlon+/hoiig memory 68/
+	PBF_FS_DATAIODf= (1 << 9),  /8 schedul  IO completISF on fs(datad 68/
+	PBF_FORCEIOf= (1 << 10),    /8 ignore any cache s,a eEE + 8/
+	PBF_FLUSHf= (1 << 11),E    /8 flush disk w     cacheEE + 8/
+	PBF_READ_AHEAD = (1 << 12), /8 asynchronousir ad-ah ad	E + 8/
+	PBF_DIRECTIOf= (1 << 13),   /8 used for-a- irect(IOfmappiigE + 8/
+
+E/8 +c ls used only as argumSntonto-accessnroutiies 8/
+	PBF_LOCKf= (1 << 14),       /8 12B, r quested		E + 8/
+	PBF_TRYLOCKf= (1 << 15),    /8 12B, r quested, but do+_tyAwaitE + 8/
+	PBF_DONT_BLOCKf= (1 << 16), /8 do+_tyAb12B, in curreitAchr adE + 8/
+
+E/8 +c ls used only internally 8/
+	_PBF_PAGE_CACHEf= (1 << 17),/8 baB,ed by-pagecacheEE + 8/
+	_PBF_KMEM_ALLOCf= (1 << 18),/8 baB,ed by-kmem_a2_HW()EE + 8/
+	_PBF_RUN_QUEUESf= (1 << 19),/8 runAb12B, device2,ask queueE + 8/
+	_PBF_PRIVATE_BHf= (1 << 20),/8 do+_tyAuseApublic buffer headsE + 8/
+} page_buf_+c ls_n;p+p+# /home PBF_UPDATE+(PBF_READ | PBF_WRITE)p+# /home PBF_NOT_DONE(pb)d(((pb)->pb_+c ls &+(PBF_PARTIAL|PBF_NONE)) !=+0)p+# /home PBF_DONE(pb)d(((pb)->pb_+c ls &+(PBF_PARTIAL|PBF_NONE)) == 0)p+p+# /home PBR_SECTOR_ONLY	1E/8 only useAsector-snit buffer heads--/
+# /home PBR_ALIGNED_ONLY 2E/8 only useAaligted,I/O 8/
+
+Oype /h s,* Ok,xfs_buf,arg {p+	int	d	pbr_+c ls;
+	dev_t	d	pbr_dev;
+	kdev_t	d	pbr_kdev;p+	s,* Ok,b12B,_device	-pbr_bdev;p+	s,* Ok,address_space	-pbr_mappiig;p+	unsigted iit		pbr_bsnit;p+	unsigted iit		pbr_sshift;p+Esnit_t			pbr_smask;
+} xfs_buf,arg_t;-+
+4-
+68	xfs_buf_t:  Buffer s,* Okurerfor-page cache-based buffersp+ -
+68 THdonbuffer s,* Okurerdonused by(OH upage cache buffer managemSntnroutiies
+68 Oo(r fer to(an assembly o++pagesiformiig anlogical-buffer.  TH uactual I/O
+68 donperformt }winv2buffer_h ad s,* Okures, as required by(drivers.p+ - 
+68 TH ubuffer s,* Okurerdonused on Oemporary basis only, and(discardt }wHen
+ *(r leased.  TH urea2 data storage donrecordt }in(OH upage cache.  Metadataiis
+68 hashed to(OHeAb12B, device2SF wHicv,OHeAfile system resides.
+68/-+
+s,* Ok,xfs_buf;-+
+4-+ca2_-baB, functISFnon I/O completISF68/-+Oype /h tic A(*page_buf_iostre_t)(s,* Ok,xfs_buf *);p+4-+ca2_-baB, functISFnon I/O completISF68/-+Oype /h tic A(*page_buf_re_HW_t)(s,* Ok,xfs_buf *);p+4-+pre-w     +unctISFn8/-+Oype /h int (*page_buf_bds,*at_t)(s,* Ok,xfs_buf *);p+
+# /home PB_PAGES	4
+
+Oype /h s,* Ok,xfs_buf {p+	s,* Ok,semaphoreEpb_sema;E/8 semaphorerfor-12B,ablesi68/
+	unsigted long		pb_queueSIme;E/8 SIme buffer was queued  68/
+	aSomic_t		pb_pin_c*/in;E/8 pin c*/inEE + (8/
+	wait_queue_h ad_t	pb_waiters;E/8 unpin waitersE + (8/
+	s,* Ok,list_h ad	pb_1ist;
+	page_buf_+c ls_t	pb_+c ls;E/8 s,a usi+c ls 8/
+	s,* Ok,list_h ad	pb_hash_1ist;
+	xfs_buf,arg_t		*pb_,arget;E/8 logical-object68/
+	aSomic_t		pb_hold;E/8 referenc uc*/in,*/p+	xfs_daddr_t		pb_bn;EE/8 b12B, _umber2for-I/O 8/
+	loff_t		dpb_+ile_offset;E/8 o+fset in(file */
+	snit_t			pb_buffer_1engnv; /8 snit o++buffer in bytes */
+	snit_t			pb_c*/in_desired; /8 desired ,*ansfer snit */
+	vic s		*pb_addr;E/8 virtual address o++buffer 8/
+	s,* Ok,tq_s,* Ok	pb_iostre_sched;
+	aSomic_t		pb_io_r mainiig;/8 #outs,andiig I/O requestsf*/p+	page_buf_iostre_t	pb_iostre;E/8 I/O completISF6+unctISFn8/-+	page_buf_re_HW_t	pb_re_HW;E/8 releasiig functISFn8/-+	page_buf_bds,*at_tEpb_s,*at;E/8 pre-w     +unctISFn8/-+	s,* Ok,semaphoreEpb_iostresema;	/8 Semaphorerfor-I/O waiters */
+	vic s		*pb_fsprdv;p+	vic s		*pb_fsprdv2;p+	vic s		*pb_fsprdv3;p+	unsigted deGrt		pb_error;E/8 error codeAon I/O 8/
+	unsigted deGrt		pb_page_c*/in;	/8 snit o++page array 8/
+	unsigted deGrt		pb_offset;E/8 page o+fset in(first(pageA*/
+	unsigted char		pb_12B,ed;E/8 page array don12B,ed */
+	unsigted char		pb_hash_indIx;E/8 hash2,able indIx	8/-+	s,* Ok,page		**pb_pages;E/8 array o++page pointers 8/
+	s,* Ok,page		*pb_page_array[PB_PAGES]; /8 dnlome pages -/
+#if /h PAGEBUF_LOCK_TRACKINGp+	int	d	pb_last_holder;p+#end(+
+} xfs_buf_t;
+
+
+4- Findiig and(R adiig Buffers 8/-+
+exnern xfs_buf_t *pagebuf_find(E/8 +ind bufferrfor-b12B, if	*/p+	sE	E/8 OHeAb12B, dondn memory	*/p+	sxfs_buf,arg_t68,E/8 inoderfor-b12B,		-/-+		loff_t,EEE/8 s,artiigdo+fset o++range	-/-+		snit_t,EEE/8 lengnv o++range		-/-+		page_buf_+c ls_t);E/8 PBF_LOCK			-/-+
+exnern xfs_buf_t *pagebuf_get(EE/8 a2_HWatt a buffers	*/p+	sxfs_buf,arg_t68,E/8 inoderfor-buffers	*/p+	sloff_t,EEE/8 s,artiigdo+fset o++range666668/
+		snit_t,EEE/8 lengnv o++range666666666666668/
+		page_buf_+c ls_t);E/8 PBF_LOCK,+PBF_READ,		*/p+	sE	E/8 PBF_ASYNC			-/-+
+exnern xfs_buf_t *pagebuf_lookup(-+	sxfs_buf,arg_t68,-+		loff_t,EEE/8 s,artiigdo+fset o++range	-/-+		snit_t,EEE/8 lengnv o++range		-/-+		page_buf_+c ls_t);E/8 PBF_READ, PBF_WRITE,		*/p+	sE	E/8 PBF_FORCEIO, 		-/-+
+exnern xfs_buf_t *pagebuf_get_ompty(E/8 a2_HWatt pagebuf s,* Ok,winv	*/p+	sE	E/8 +_tAmemory or-disk address	-/-+		snit_t len,p+EExfs_buf,arg_t68);E/8 m*/in,point "fake" inode	-/-+
+exnern xfs_buf_t *pagebuf_get_no_daddr(/8 a2_HWatt pagebuf s,* Ok	*/p+	sE	E/8 winvout disk address		-/-+		snit_t len,p+EExfs_buf,arg_t68);E/8 m*/in,point "fake" inode	-/-+
+exnern int pagebuf_associate_memory(-+	sxfs_buf_t68,-+		tic A*,-+		snit_t);p+
+exnern tic Apagebuf_hold(	E/8 incremSntnreferenc uc*/in	*/p+	sxfs_buf_t68);EE/8 buffer to(hold		-/-+
+exnern tic Apagebuf_r adah ad(	E/8 r adAah ad inOo+cacheE*/p+	sxfs_buf,arg_t668,E/8 Oarget for-buffer (or-ct a)	*/p+	sloff_t,EEE/8 s,artiigdo+fset o++range666668/
+		snit_t,EEE/8 lengnv o++range666666666666668/
+		page_buf_+c ls_t);E/8 additISFal,r adA+c ls	-/
+
+4-(R leasiig Buffers 8/-+
+exnern tic Apagebuf_d/ho(	E/8 dea2_HWatt a buffers	*/p+	sxfs_buf_t68);EE/8 buffer to(dea2_HWatt		-/-+
+exnern tic Apagebuf_r le(	E/8 r leaseAhold on a buffers*/p+	sxfs_buf_t68);EE/8 buffer to(r lease		-/
+
+4-(L2B,iigdand(Unl2B,iigdBuffers 8/-+
+exnern int pagebuf_cond_12B,(EE/8 l2B, buffer,A(++_tyn12B,ed	*/p+	sE	E/8 (redirto -EBUSYA(++12B,ed)s*/p+	sxfs_buf_t68);EE/8 buffer to(12B,		-/-+
+exnern int pagebuf_12B,_valuB(	E/8 r dirt c*/in(on 12B,		-/-+		xfs_buf_t68);6666666666/8 buffer to(cheB, 66666666666668/
+
+exnern int pagebuf_12B,(EE/8 l2B, bufferi666666666666666668/
+		xfs_buf_t68);6666666666/8 buffer to(l2B,  66666666666668/
+
+exnern tic Apagebuf_un12B,(	E/8 unl2B, buffers	*/p+	sxfs_buf_t68);EE/8 buffer to(unl2B,		-/
+
+4-(Buffer R adAand(W     Routiies 8/
+
+exnern tic Apagebuf_iostre(EE/8 markAbuffer I/O complete	*/p+	sxfs_buf_t68,EE/8 buffer to(marks	*/p+	sint,EEE/8 useAdata/log helptr chr ad.	*/p+	sint);EE	/8 runAcompletISF6_HWally,ior ii
+	sE	E * aihelptr chr ad.		-/-+
+exnern tic Apagebuf_ioerror(EE/8 markAbuffer dn error	(or-_ty)68/
+		xfs_buf_t68,EE/8 buffer to(marks	*/p+	sint);EE	/8 error to(s,orer(0A(++_tne)	-/-+
+exnern int pagebuf_ios,art(EE/8 s,art I/O SF a buffers*/p+	sxfs_buf_t68,EE/8 buffer to(s,art		-/-+		page_buf_+c ls_t);E/8 PBF_LOCK, PBF_ASYNC,		*/p+	sE	E/8 PBF_READ, PBF_WRITE,		*/p+	sE	E/8 PBF_DELWRI			-/-+
+exnern int pagebuf_iorequest(EE/8 s,art rea2 I/O		-/-+	sxfs_buf_t68);EE/8 buffer to(convey Oo device	-/-+
+exnern int pagebuf_iowait(	E/8 waitifor-buffer I/O stre	-/-+	sxfs_buf_t68);EE/8 buffer to(waition		-/-+
+exnern tic Apagebuf_iomove(EE/8 move data dn/out Sf(pagebuf	*/p+	sxfs_buf_t68,EE/8 buffer to(manipulate		-/-+		snit_t,EEE/8 s,artiigdbuffer offset	-/-+		snit_t,EEE/8 lengnv in buffers	*/p+	scaddr_t,EE/8 data pointer			-/-+		page_buf_rw_n);EE/8  irection			8/-+
+s,atic dnlome int pagebuf_ios,*ategy(xfs_buf_t *pb)-+{p+	r dirt pb->pb_s,*at ? pb->pb_s,*at(pb)d: pagebuf_iorequest(pb);p+}-+
+s,atic dnlome int pagebuf_geterror(xfs_buf_t *pb)-+{p+	r dirt pb ? pb->pb_error : ENOMEM;p+}
+
+4-(Buffer Utility Routiies 8/
+
+exnern caddr_t pagebuf_offset(EE/8 pointerAayio+fset in(buffers*/p+	sxfs_buf_t68,EE/8 buffer to(o+fset into	-/-+		snit_t);EE/8 offset			-/
+
+4-(PinniigdBuffer Storage dn Memory 8/
+
+exnern tic Apagebuf_pin(	E/8 pin buffer dn memory		-/-+	sxfs_buf_t68);EE/8 buffer to(pin		-/-+
+exnern tic Apagebuf_unpin(	E/8 unpin buffered datas	*/p+	sxfs_buf_t68);EE/8 buffer to(unpin		-/-+
+exnern int pagebuf_ispin(	E/8 cheB, i++buffer is(pinned	*/p+	sxfs_buf_t68);EE/8 buffer to(cheB,		-/
+
+4-(DelayBd W     Buffer Routiies 8/
+
+exnern tic Apagebuf_delw  _dequeue(xfs_buf_t68);
+
+4-(Buffer DaemSF S dip Routiies 8/
+
+exnern int pagebuf_init(tic );
+exnern tic Apagebuf_terminate(tic );
+
+
+#if /h PAGEBUF_TRACE
+exnern k,*ace_t *pagebuf_,*ace_buf;
+exnern tic Apagebuf_t*ace(-+	sxfs_buf_t68,EE/8 buffer boiig t*aceds	*/p+	schar68,EEE/8 descriptISFnof operatISF	*/p+	stic A*,EEE/8 arbitrary diagnos,ic valuB	*/p+	stic A*);EE/8 r dirt address		-/-+#e_sep+#  /home pagebuf_t*ace(pb, id, ptr,Ara)	do { } wHile (0)p+#end(+
+
+# /home pagebuf_target_namt(target)	bdevnamt((target)->pbr_kdev)
+
+4-
+68 Kernel versISF compatIbility macros
+ -/
+
+# /home page_buffers(page)	((page)->buffers)
+# /home page_has_buffers(page)	((page)->buffers)
+# /home PageUptodatt(x)		Page_Uptodatt(x)
+4-
+68 macro t*icks to(expand(OHeAset_buffer_foo()Aand(clear_buffer_foo()
+68 +unctISFs.
+68/-+# /home BUFFER_FNS(bit,+namt)	sE	E	\
+s,atic dnlome tic Aset_buffer_##namt(s,* Ok,buffer_h ad *bh)E	\
+{									\
+	set_bit(BH_##bit,+&(bh)->b_statt);				\
+}									\
+s,atic dnlome tic Aclear_buffer_##namt(s,* Ok,buffer_h ad *bh)E	\
+{									\
+	clear_bit(BH_##bit,+&(bh)->b_statt);				\
+}									\
+
+4-
+68 Emit2OHeAbuffer bitops +unctISFs.666Note tHat(OHere are also++unctISFsp+f* o++OHeAform "mark_buffer_foo()".  TH se are higHer-level +unctISFs wHicvp+f* do somethiig in additISF to(settiig anb_statt bit.
+68/-+BUFFER_FNS(Uptodatt, uptodatt)-+BUFFER_FNS(Dirty,A irty)-+BUFFER_FNS(L2B,, 12B,ed)p+BUFFER_FNS(Req, req)p+BUFFER_FNS(Mapped, mapped)p+BUFFER_FNS(New, new)p+BUFFER_FNS(Async, async)p+BUFFER_FNS(Wait_IO, wait_io)-+BUFFER_FNS(LaundIS, 1aundIS)-+BUFFER_FNS(Sync, sync)p+BUFFER_FNS(Delay,udelay)p+p+# /home get_seconds()EECURRENT_TIMEp+# /home i_snit_r ad(inode)	((inode)->i_snit)p+# /home i_snit_w    (inode, sz)	((inode)->i_snitf= (sz))
+
+4- TH se are justifor-xfs_syncsub...((t sets an internal variable
+68 OHet passes((t to(VOP_FLUSH_PAGES or-adds+OHeAfc ls to(a newly go ten}buf_t
+68/-+# /home XFS_B_ASYNC		PBF_ASYNC-+# /home XFS_B_DELWRI		PBF_DELWRI-+# /home XFS_B_READ		PBF_READ-+# /home XFS_B_WRITE		PBF_WRITE-+# /home XFS_B_STALE		PBF_STALE
+
+# /home XFS_BUF_TRYLOCK		PBF_TRYLOCK
+# /home XFS_INCORE_TRYLOCK	PBF_TRYLOCK
+# /home XFS_BUF_LOCK		PBF_LOCK
+# /home XFS_BUF_MAPPED		PBF_MAPPED
+
+# /home BUF_BUSY		PBF_DONT_BLOCK
+
+# /home XFS_BUF_BFLAGS(x)	((x)->pb_+c ls)
+# /home XFS_BUF_ZEROFLAGS(x)	\
+	((x)->pb_+c ls &= ~(PBF_READ|PBF_WRITE|PBF_ASYNC|PBF_DELWRI))
+
+# /home XFS_BUF_STALE(x)	((x)->pb_+c ls |=+XFS_B_STALE)
+# /home XFS_BUF_UNSTALE(x)	((x)->pb_+c ls &= ~XFS_B_STALE)
+# /home XFS_BUF_ISSTALE(x)	((x)->pb_+c ls &+XFS_B_STALE)
+# /home XFS_BUF_SUPER_STALE(x)	do {				\
+					XFS_BUF_STALE(x);	\
+					pagebuf_delw  _dequeue(x);	\
+					XFS_BUF_DONE(x);	\
+				} wHile (0)p+
+# /home XFS_BUF_MANAGE		PBF_FS_MANAGED
+# /home XFS_BUF_UNMANAGE(x)	((x)->pb_+c ls &= ~PBF_FS_MANAGED)p+
+# /home XFS_BUF_DELAYWRITE(x)	 ((x)->pb_+c ls |=+PBF_DELWRI)
+# /home XFS_BUF_UNDELAYWRITE(x)	 pagebuf_delw  _dequeue(x)
+# /home XFS_BUF_ISDELAYWRITE(x)	 ((x)->pb_+c ls &+PBF_DELWRI)
+
+# /home XFS_BUF_ERROR(x,no)	 pagebuf_ioerror(x,no)
+# /home XFS_BUF_GETERROR(x)	 pagebuf_geterror(x)
+# /home XFS_BUF_ISERROR(x)	 (pagebuf_geterror(x)?1:0)p+
+# /home XFS_BUF_DONE(x)		 ((x)->pb_+c ls &= ~(PBF_PARTIAL|PBF_NONE))
+# /home XFS_BUF_UNDONE(x)	 ((x)->pb_+c ls |=+PBF_PARTIAL|PBF_NONE)
+# /home XFS_BUF_ISDONE(x)	 (!(PBF_NOT_DONE(x)))
+
+# /home XFS_BUF_BUSY(x)		 ((x)->pb_+c ls |=+PBF_FORCEIO)
+# /home XFS_BUF_UNBUSY(x)	 ((x)->pb_+c ls &= ~PBF_FORCEIO)
+# /home XFS_BUF_ISBUSY(x)	 (1)
+
+# /home XFS_BUF_ASYNC(x)	 ((x)->pb_+c ls |=+PBF_ASYNC)
+# /home XFS_BUF_UNASYNC(x)	 ((x)->pb_+c ls &= ~PBF_ASYNC)
+# /home XFS_BUF_ISASYNC(x)	 ((x)->pb_+c ls &+PBF_ASYNC)
+
+# /home XFS_BUF_FLUSH(x)	 ((x)->pb_+c ls |=+PBF_FLUSH)
+# /home XFS_BUF_UNFLUSH(x)	 ((x)->pb_+c ls &= ~PBF_FLUSH)
+# /home XFS_BUF_ISFLUSH(x)	 ((x)->pb_+c ls &+PBF_FLUSH)
+
+# /home XFS_BUF_SHUT(x)		 prdl ,("XFS_BUF_SHUT+_tynimplemSntBd yet\n")
+# /home XFS_BUF_UNSHUT(x)	 prdl ,("XFS_BUF_UNSHUT+_tynimplemSntBd yet\n")
+# /home XFS_BUF_ISSHUT(x)	 (0)p+
+# /home XFS_BUF_HOLD(x)		pagebuf_hold(x)
+# /home XFS_BUF_READ(x)		((x)->pb_+c ls |=+PBF_READ)
+# /home XFS_BUF_UNREAD(x)	((x)->pb_+c ls &= ~PBF_READ)
+# /home XFS_BUF_ISREAD(x)	((x)->pb_+c ls &+PBF_READ)
+
+# /home XFS_BUF_WRITE(x)	((x)->pb_+c ls |=+PBF_WRITE)p+# /home XFS_BUF_UNWRITE(x)	((x)->pb_+c ls &= ~PBF_WRITE)p+# /home XFS_BUF_ISWRITE(x)	((x)->pb_+c ls &+PBF_WRITE)p+p+# /home XFS_BUF_ISUNINITIAL(x)	 (0)p+# /home XFS_BUF_UNUNINITIAL(x)	 (0)p+
+# /home XFS_BUF_BP_ISMAPPED(bp)	 1
+
+# /home XFS_BUF_DATAIO(x)	((x)->pb_+c ls |=+PBF_FS_DATAIOD)
+# /home XFS_BUF_UNDATAIO(x)	((x)->pb_+c ls &= ~PBF_FS_DATAIOD)
+p+# /home XFS_BUF_IODONE_FUNC(buf)	(buf)->pb_iostre
+# /home XFS_BUF_SET_IODONE_FUNC(buf, +unc)	\
+			(buf)->pb_iostref= (+unc)
+# /home XFS_BUF_CLR_IODONE_FUNC(buf)		\
+			(buf)->pb_iostref= ct a
+# /home XFS_BUF_SET_BDSTRAT_FUNC(buf, +unc)	\
+			(buf)->pb_s,*at = (+unc)
+# /home XFS_BUF_CLR_BDSTRAT_FUNC(buf)		\
+			(buf)->pb_s,*at = ct a
+
+# /home XFS_BUF_FSPRIVATE(buf, Oype)		\
+			((Oype)(buf)->pb_fsprdv)
+# /home XFS_BUF_SET_FSPRIVATE(buf, valuB)	\
+			(buf)->pb_fsprdv = (tic A*)(valuB)
+# /home XFS_BUF_FSPRIVATE2(buf, Oype)		\
+			((Oype)(buf)->pb_fsprdv2)
+# /home XFS_BUF_SET_FSPRIVATE2(buf, valuB)	\
+			(buf)->pb_fsprdv2 = (tic A*)(valuB)
+# /home XFS_BUF_FSPRIVATE3(buf, Oype)		\
+			((Oype)(buf)->pb_fsprdv3)
+# /home XFS_BUF_SET_FSPRIVATE3(buf, valuB)	\
+			(buf)->pb_fsprdv3  = (tic A*)(valuB)
+# /home XFS_BUF_SET_START(buf)
+
+# /home XFS_BUF_SET_BRELSE_FUNC(buf, valuB) \
+			(buf)->pb_re_HW = (taluB)
+
+# /home XFS_BUF_PTR(bp)		(xfs_caddr_t)((bp)->pb_addr)
+
+exnern inlome xfs_caddr_t xfs_buf_offset(xfs_buf_t68bp, snit_yio+fset)-+{p+	if (bp->pb_+c ls &+PBF_MAPPED)p+	Er dirt XFS_BUF_PTR(bp) + offset;p+	r dirt (xfs_caddr_t) pagebuf_offset(bp, offset);p+}
+
+# /home XFS_BUF_SET_PTR(bp, val, c*/in)		\
+				pagebuf_associate_memory(bp, val, c*/in)
+# /home XFS_BUF_ADDR(bp)	((bp)->pb_bn)
+# /home XFS_BUF_SET_ADDR(bp, blk)		\
+			((bp)->pb_bn = (xfs_daddr_t)(blk))
+# /home XFS_BUF_OFFSET(bp)	((bp)->pb_+ile_offset)
+# /home XFS_BUF_SET_OFFSET(bp, off)		\
+			((bp)->pb_+ile_offset = (off))
+# /home XFS_BUF_COUNT(bp)	((bp)->pb_c*/in_desired)
+# /home XFS_BUF_SET_COUNT(bp, cin)		\
+			((bp)->pb_c*/in_desired = (cin))
+# /home XFS_BUF_SIZE(bp)	((bp)->pb_buffer_1engnv)
+# /home XFS_BUF_SET_SIZE(bp, cin)		\
+			((bp)->pb_buffer_1engnv = (cin))
+# /home XFS_BUF_SET_VTYPE_REF(bp, Oype, ref)
+# /home XFS_BUF_SET_VTYPE(bp, Oype)
+# /home XFS_BUF_SET_REF(bp, ref)
+p+# /home XFS_BUF_ISPINNED(bp)	pagebuf_ispin(bp)
+p+# /home XFS_BUF_VALUSEMA(bp)	pagebuf_12B,_valuB(bp)
+# /home XFS_BUF_CPSEMA(bp)	(pagebuf_cond_12B,(bp) ==+0)p+# /home XFS_BUF_VSEMA(bp)	pagebuf_un12B,(bp)
+# /home XFS_BUF_PSEMA(bp,x)	pagebuf_12B,(bp)
+# /home XFS_BUF_V_IODONESEMA(bp) up(&bp->pb_iostresema);p+
+4- s dip OHeAbuffer Oarget fromra buf,arg s,* Okurer8/-+# /home XFS_BUF_SET_TARGET(bp, target)	\
+		(bp)->pb_Oarget = (target)-+# /home XFS_BUF_TARGET(bp)	((bp)->pb_target)-+# /home XFS_BUFTARG_NAME(target)	\
+		pagebuf_target_namt(target)
+
+# /home XFS_BUF_SET_VTYPE_REF(bp, Oype, ref)
+# /home XFS_BUF_SET_VTYPE(bp, Oype)
+# /home XFS_BUF_SET_REF(bp, ref)
+p+# /home xfs_buf_read(target, blkno, len,Afc ls) \
+		pagebuf_get((target), (blkno), (len), \
+			PBF_LOCKf|+PBF_READf|+PBF_MAPPED)p+# /home xfs_buf_get(target, blkno, len,Afc ls) \
+		pagebuf_get((target), (blkno), (len), \
+			PBF_LOCKf|+PBF_MAPPED)p+p+# /home xfs_buf_read_+c ls(target, blkno, len,Afc ls) \
+		pagebuf_get((target), (blkno), (len), PBF_READf|+(fc ls))p+# /home xfs_buf_get_+c ls(target, blkno, len,Afc ls) \
+		pagebuf_get((target), (blkno), (len), (fc ls))p+
+s,atic dnlome intsxfs_baw    (tic A*mp,Axfs_buf_t68bp)-+{p+	bp->pb_+sprdv3 = mp;p+Ebp->pb_s,*at = xfs_bds,*at_cb;
+	pagebuf_delw  _dequeue(bp);p+	r dirt pagebuf_ios,art(bp, PBF_WRITEf|+PBF_ASYNCf|+_PBF_RUN_QUEUES);p+}-+
+s,atic dnlome vic sxfs_buf_re_HW(xfs_buf_t68bp)-+{p+	if (!bp->pb_re_HW)
+		pagebuf_un12B,(bp);
+	pagebuf_r le(bp);
+}p+p+# /home xfs_bpin(bp)		pagebuf_pin(bp)
+# /home xfs_bunpin(bp)		pagebuf_unpin(bp)p+p+# /home xfs_buft*ace(id, bp)	\
+	6666pagebuf_t*ace(bp, id, ct a, (tic A*)__builtin_r dirt_address(0))p+p+# /home xfs_biostre(pb)E	6666\
+	6666pagebuf_iostre(pb, (pb->pb_+c ls &+PBF_FS_DATAIOD), 0)p+p+# /home xfs_incor (buf,arg,blkno,len,l2B,it)6\
+	6666pagebuf_find(buf,arg, blkno ,len, l2B,it)
+
+
+# /home xfs_biomove(pb, o+f,(len, data, rw)6\
+	6666pagebuf_iomove((pb), (off), (len), (data), \
+		((rw)6==+XFS_B_WRITE) ? PBRW_WRITE : PBRW_READ)p+p+# /home xfs_biozero(pb, o+f,(len)6\
+	6666pagebuf_iomove((pb), (off), (len), ct a, PBRW_ZERO)
+
+
+s,atic dnlome intsXFS_bw    (xfs_buf_t *pb)-+{p+	intsiowait = (pb->pb_+c ls &+PBF_ASYNC) ==+0;p+	intserror = 0;p+p+	if (!iowait)
+		pb->pb_+c ls |=+_PBF_RUN_QUEUES;p+
+	pagebuf_delw  _dequeue(pb);p+Epagebuf_ios,*ategy(pb);p+Eif (iowait) {p+		error = pagebuf_iowait(pb);
+	Exfs_buf_re_HW(pb);p+E}p+	r dirt error;p+}
+
+# /home XFS_bdw    (pb)E	66666\
+	6666pagebuf_ios,art(pb, PBF_DELWRI |+PBF_ASYNC)
+
+s,atic dnlome int xfs_bdw    (tic A*mp,Axfs_buf_t68bp)-+{p+	bp->pb_s,*at = xfs_bds,*at_cb;
+	bp->pb_+sprdv3 = mp;p+p+	r dirt pagebuf_ios,art(bp, PBF_DELWRI |+PBF_ASYNC);p+}
+
+# /home XFS_bds,*at(bp) pagebuf_iorequest(bp)p+p+# /home xfs_iowait(pb)	pagebuf_iowait(pb)p+p+# /home xfs_baread(target, rablkno, ralen)66\
+	pagebuf_r adah ad((target), (rablkno), (ralen), PBF_DONT_BLOCK)p+p+# /home xfs_buf_get_ompty(len, target)	pagebuf_get_ompty((len), (target))p+# /home xfs_buf_get_noaddr(len, target)	pagebuf_get_no_daddr((len), (target))p+# /home xfs_buf_d/ho(bp)		pagebuf_d/ho(bp)p+p+ 4-
+6 *	Handliig+o++buftargs.
+6r8/-+ 
+exnern xfs_buf,arg_t68xfs_a2_HW_buf,arg(s,* Ok,b12B,_device68);
+exnern tic Axfs_f/ho_buf,arg(xfs_buf,arg_t68, iit);
+exnern tic Axfs_setsnit_buf,arg(xfs_buf,arg_t68, unsigted iit, unsigted iit);
+exnern tic Axfs_incor _re_HW(xfs_buf,arg_t68, iit, iit);
+exnern int xfs_flush_buf,arg(xfs_buf,arg_t68, iit);
+p+# /home xfs_getsnit_buf,arg(buf,arg)6\
+	b12B,_snit((buf,arg)->pbr_kdev)
+# /home xfs_r adonly_buf,arg(buf,arg)6\
+	is_r ad_only((buf,arg)->pbr_kdev)
+# /home xfs_binval(buf,arg)6\
+	xfs_flush_buf,arg(buf,arg, 1)
+# /home XFS_bflush(buf,arg)6\
+	xfs_flush_buf,arg(buf,arg, 1)
+p+#end(+E/8 __XFS_BUF_H__r8/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_cred.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_cred.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_cred.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_cred.h	2004-07-30 16:31:01.000000000 +0000
@@ -0,0 +1,50 @@
+4-
+68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifn /h __XFS_CRED_H__
+# /home __XFS_CRED_H__
+
+4-
+68 CredSntIals
+ -/
+Oype /h s,* Ok,cred {p+	/8 EMPTY(8/
+} cred_t;
+
+exnern s,* Ok,cred *sys_cred;p+
+4- tHdondona igck.. (assums sys_credndonOH uonly cred_t in2OHeAsystem)68/
+s,atic __inlome int capable_cred(cred_t *cr, int cc )-+{p+	r dirt (cr ==+sys_cred) ? 1 : capable(cc );
+}
+p+#end(+66/8 __XFS_CRED_H__r8/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_.ile.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_.ile.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_.ile.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_.ile.c	2004-07-30 16:26:41.000000000 +0000
@@ -0,0 +1,445 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_sb.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_,*ans.h"
+#include "xfs_dmapi.h"
+#include "xfs_m*/in.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_a2_HW_btree.h"
+#include "xfs_ia2_HW_btree.h"
+#include "xfs_a2_HW.h"
+#include "xfs_btree.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_error.h"
+#include "xfs_rw.h"
+#include <linux/iobuf.h>
+
+#include <linux/dcache.h>
+#include <linux/smp_12B,.h>
+#include <linux/mmaF.h> /8 for PROT_WRITE 8/-+
+s,atic s,* Ok,vm_operatISFs_s,* Ok,linvfs_.ile_vm_ops;p+
+STATIC inlome ssnit_y
+__linvfs_read(
+	s,* Ok,.ile	*.ile,-+	char		*buf,p+	ints	io+c ls,p+	snit_t		snit,p+	loff_t		*o+fset)-+{p+	s,* Ok,inode	-inoder=,.ile->f_dentry->d_inode;p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Essnit_t		rval;p+p+	if (unlokely(.ile->f_+c ls &+O_DIRECT))o{p+	sio+c ls |=+IO_ISDIRECT;
+	Edown_read(&inode->i_a2_HW_sem);
+	EVOP_READ(vp,,.ile, buf, snit, offset,+(o+c ls, ct a, rval);
+	Eup_read(&inode->i_a2_HW_sem);
+	} e_HWo{p+EEVOP_READ(vp,,.ile, buf, snit, offset,+(o+c ls, ct a, rval);
+	}p+p+Er dirt rval;p+}-+
+STATIC ssnit_y
+linvfs_read(
+	s,* Ok,.ile	*.ile,-+	char		*buf,p+	snit_t		snit,p+	loff_t		*o+fset)-+{p+	r dirt __linvfs_read(.ile, buf, 0, snit, offset);p+}-+
+STATIC ssnit_y
+linvfs_read_invis(
+	s,* Ok,.ile	*.ile,-+	char		*buf,p+	snit_t		snit,p+	loff_t		*o+fset)-+{p+	r dirt __linvfs_read(.ile, buf, IO_INVIS, snit, offset);p+}-+
+
+STATIC inlome ssnit_y
+__linvfs_w    (
+	s,* Ok,.ile	*.ile,-+	cSFst char	*buf,p+	ints	io+c ls,p+	snit_t		c*/in,p+	loff_t		*ppos)-+{p+	s,* Ok,inode	-inoder=,.ile->f_dentry->d_inode;p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Eloff_t		pos;p+Essnit_t		rval;	/8 UHWonegativeferrors in2OHdon+'n 8/
+
+Eif ((ssnit_t) c*/in(< 0)p+	sr dirt -EINVAL;p+p+	if (!access_ok(VERIFY_READ, buf, c*/in))p+	sr dirt -EFAULT;p+
+	posr=,*ppos;p+	if (posr< 0)p+	sr dirt -EINVAL;p+p+	rvalr=,.ile->f_error;p+	if (rval)o{p+EE.ile->f_error(= 0;p+		r dirt rval;p+	}p+p+E/8 We a2_Hw multiple  irect(w    rs in,(OHere don_t
+s68 potSntIal+ca2_ to(vm,* nWatt in2OHat path.
+	68/
+	if (unlokely(.ile->f_+c ls &+O_DIRECT))o{p+	sio+c ls |=+IO_ISDIRECT;
+	Edown_read(&inode->i_a2_HW_sem);
+	EVOP_WRITE(vp,,.ile, buf, c*/in, &pos,+(o+c ls, ct a, rval);
+	E*ppos = pos;p+	Eup_read(&inode->i_a2_HW_sem);
+	} e_HWo{p+EEdown(&inode->i_sem);
+	EVOP_WRITE(vp,,.ile, buf, c*/in, &pos,+(o+c ls, ct a, rval);
+	E*ppos = pos;p+	Eup(&inode->i_sem);
+	}p+p+Er dirt rval;p+}-+
+STATIC inlome ssnit_y
+linvfs_w    (
+	s,* Ok,.ile	*.ile,-+	cSFst char	*buf,p+	snit_t		c*/in,p+	loff_t		*ppos)-+{p+	r dirt __linvfs_w    (.ile, buf, 0, c*/in, ppos);p+}-+
+STATIC inlome ssnit_y
+linvfs_w    _invis(
+	s,* Ok,.ile	*.ile,-+	cSFst char	*buf,p+	snit_t		c*/in,p+	loff_t		*ppos)-+{p+	r dirt __linvfs_w    (.ile, buf, IO_INVIS, c*/in, ppos);p+}-+
+STATIC iny
+linvfs_open(
+	s,* Ok,inode	-inode,
+	s,* Ok,.ile	*.ilp)-+{p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Eints	error;p+p+	if (!(.ilp->f_+c ls &+O_LARGEFILE) && i_snit_r ad(inode) > MAX_NON_LFS)p+	sr dirt -EFBIG;p+p+	ASSERT(vp);p+EVOP_OPEN(vp,,ct a, error);p+	r dirt -error;p+}
+
+
+STATIC iny
+linvfs_r lease(
+	s,* Ok,inode	-inode,
+	s,* Ok,.ile	*.ilp)-+{p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Eints	error = 0;p+p+	if (vp)p+EEVOP_RELEASE(vp,,error);p+	r dirt -error;p+}
+
+
+STATIC iny
+linvfs_fsync(
+	s,* Ok,.ile	*.ilp,
+	s,* Ok,dentry	*dentry,p+	ints	datasync)p+{p+	s,* Ok,inode	-inoder=,dentry->d_inode;p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Eints	error;p+Eints	+c ls = FSYNC_WAIT;p+
+	error = fsync_inode_data_buffers(inode);p+Eif (error)p+	sr dirt error;p+p+	if (datasync)p+s	+c ls |= FSYNC_DATA;p+p+	ASSERT(vp);p+EVOP_FSYNC(vp,,.c ls, ct a, (xfs_off_t)0, (xfs_off_t)-1,,error);p+	r dirt -error;p+}
+
+4-
+68 linvfs_read ir maps to(VOP_READDIR().p+ - WWoneed to(build a(uio, cred, ...
+68/-+
+# /home nextdp(dp)      ((s,* Ok,xfs_ irein,*)((char68)(dp) + (dp)->d_reclen))
+
+STATIC iny
+linvfs_r ad ir(
+	s,* Ok,.ile	*.ilp,
+	vic s	* irein,
+	.illdir_t	.illdir)-+{p+	ints	error = 0;p+	vnode_t		*vp;p+	uio_t		uio;p+Eiovec_t		iov;p+Eints	eof = 0;p+	caddr_t		read_buf;
+Eints	namtlen, snitf= 0;p+	snit_t		rlenf= PAGE_CACHE_SIZE;
+	xfs_off_t	s,art_offset,+curr_offset;p+	xfs_ irein_t	*dbp = ct a;p+p+	vpr=,LINVFS_GET_VP(.ilp->f_dentry->d_inode);p+	ASSERT(vp);p+p+E/8 Try fairly hard to(get memory 8/
+	do {p+	sif ((read_buf = (caddr_t)kma2_HW(rlen, GFP_KERNEL)))p+	s	break;p+		rlenf>>= 1;
+	} wHile (rlenf>= 1024);p+p+	if (read_buf ==+ct a)p+	sr dirt -ENOMEM;p+p+	uio.uio_iov = &iov;p+Euio.uio_segflg = UIO_SYSSPACE;
+	curr_offsetr=,.ilp->f_pos;p+	if (.ilp->f_pos !=+0x7fffffff)p+	suio.uio_offsetr=,.ilp->f_pos;p+	e_sep+	suio.uio_offsetr=,0xffffffff;-+
+	wHile (!eof)o{p+	suio.uio_residr=,iov.iov_lenf= rlen;p+	siov.iov_basef= read_buf;
+E	uio.uio_iovcntr=,1;-+
+		s,art_offsetr=,uio.uio_offset;-+
+		VOP_READDIR(vp,,&uio, ct a, &eof,,error);p+	sif ((uio.uio_offsetr== s,art_offset) ||,error)o{p+	s	snitf= 0;p+	s	break;p+		}-+
+		snitf= rlenf- uio.uio_resid;
+	Edbp = (xfs_ irein_t68)read_buf;
+E	wHile (snitf> 0)o{p+	s	namtlen = s,rlen(dbp->d_namt);p+p+			if (.illdir( irein, dbp->d_namt,+namtlen,p+EE			(loff_t)+curr_offset &+0x7fffffff,p+EE			(ino_t)+dbp->d_ino,p+EE			DT_UNKNOWN))o{p+	s		goOo dtre;p+	s	}p+	s	snitf-=+dbp->d_reclen;p+	s	curr_offsetr=,(loff_t)dbp->d_off /8 &+0x7fffffff 8/;p+	s	dbp = nextdp(dbp);
+		}p+	}p+dtre:p+	if (!error)o{p+	sif (snitf== 0)p+	s	.ilp->f_pos =,uio.uio_offset &+0x7fffffff;
+		e_HWoif (dbp)p+	s	.ilp->f_pos =,curr_offset;p+	}-+
+	kd/ho(read_buf);p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_file_mmap(
+	s,* Ok,.ile	*.ilp,
+	s,* Ok,vm_area_s,* Ok,*vma)p+{p+	s,* Ok,inode	-ipr=,.ilp->f_dentry->d_inode;p+	vnode_t		*vpr=,LINVFS_GET_VP(ip);
+	vattr_t		var=,{ .va_mask =+XFS_AT_UPDATIME };p+Eints	error;p+p+	if ((vp->v_Oypef== VREG) && (vp->v_vfsp->vfs_flag &+VFS_DMI))o{p+	sxfs_m*/in_t	*mp =+XFS_VFSTOM(vp->v_vfsp);p+p+		error = -XFS_SEND_MMAP(mp,Avma, 0);p+	sif (error)p+	ssr dirt error;p+	}-+
+	vma->vm_ops = &linvfs_.ile_vm_ops;p+
+	VOP_SETATTR(vp,,&va, XFS_AT_UPDATIME,,ct a, error);p+	r dirt 0;p+}
+
+
+STATIC iny
+linvfs_ioctl(
+	s,* Ok,inode	-inode,
+	s,* Ok,.ile	*.ilp,
+	unsigted iit	cmd,
+	unsigted long	arg)-+{p+	ints	error;p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+
+	un12B,_kernel();p+EVOP_IOCTL(vp,,inode, .ilp, 0, cmd, arg, error);p+	VMODIFY(vp);p+E12B,_kernel();p+p+E/8 NOTE:  some o++OHeAioctl's r dirt positivef#'s as a
+	68	  byte c*/in(indicatiig success, suchAas
+	68	  readlink_by_handle.  So we dtr't "sigt,.cip"
+	68	  loke most oOH rnroutiies.  THis means true
+	68	  errors need to(be r dirted as(a negativefvaluB.
+	68/
+	r dirt error;p+}
+
+STATIC iny
+linvfs_ioctl_invis(
+	s,* Ok,inode	-inode,
+	s,* Ok,.ile	*.ilp,
+	unsigted iit	cmd,
+	unsigted long	arg)-+{p+	ints	error;p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+
+	un12B,_kernel();p+EVOP_IOCTL(vp,,inode, .ilp, IO_INVIS, cmd, arg, error);p+	VMODIFY(vp);p+E12B,_kernel();p+p+E/8 NOTE:  some o++OHeAioctl's r dirt positivef#'s as a
+	68	  byte c*/in(indicatiig success, suchAas
+	68	  readlink_by_handle.  So we dtr't "sigt,.cip"
+	68	  loke most oOH rnroutiies.  THis means true
+	68	  errors need to(be r dirted as(a negativefvaluB.
+	68/
+	r dirt error;p+}
+
+#if /h HAVE_VMOP_MPROTECT
+STATIC iny
+linvfs_mprotect(
+	s,* Ok,vm_area_s,* Ok,*vma,
+	unsigted iit	new+c ls)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(vma->vm_.ile->f_dentry->d_inode);p+Eints	error = 0;p+p+	if ((vp->v_Oypef== VREG) && (vp->v_vfsp->vfs_flag &+VFS_DMI))o{p+	sif ((vma->vm_.c ls &+VM_MAYSHARE) &&p+	s    (new+c ls &+PROT_WRITE) && !(vma->vm_.c ls &+PROT_WRITE))o{p+	s	xfs_m*/in_t	*mp =+XFS_VFSTOM(vp->v_vfsp);p+p+			error = XFS_SEND_MMAP(mp,Avma, VM_WRITE);p+	s    }p+	}p+	r dirt error;p+}
+#end(+6/8 HAVE_VMOP_MPROTECT68/-+
+
+s,* Ok,+ile_operatISFs,linvfs_.ile_operatISFs,=o{p+	.l_HWek		=(generic_.ile_l_HWek,
+	.r adE	=(linvfs_r ad,
+	.w    E	=(linvfs_w    ,
+	.ioctlE	=(linvfs_ioctl,
+	.mmapE	=(linvfs_file_mmap,
+	.openE	=(linvfs_open,
+	.r lease	=(linvfs_r lease,
+	.fsyncE	=(linvfs_fsync,p+};
+
+s,* Ok,+ile_operatISFs,linvfs_invis_.ile_operatISFs,=o{p+	.l_HWek		=(generic_.ile_l_HWek,
+	.r adE	=(linvfs_r ad_invis,
+	.w    E	=(linvfs_w    _invis,
+	.ioctlE	=(linvfs_ioctl_invis,
+	.mmapE	=(linvfs_file_mmap,
+	.openE	=(linvfs_open,
+	.r lease	=(linvfs_r lease,
+	.fsyncE	=(linvfs_fsync,p+};
+
+
+s,* Ok,+ile_operatISFs,linvfs_dir_operatISFs,=o{p+	.r adE	=(generic_r ad_dir,
+	.r addir	=(linvfs_r addir,
+	.ioctlE	=(linvfs_ioctl,
+	.fsyncE	=(linvfs_fsync,p+};
+
+s,atic s,* Ok,vm_operatISFs_s,* Ok,linvfs_.ile_vm_ops,=o{p+	.nopage		=,.ilemap_nopage,
+#if /h HAVE_VMOP_MPROTECT
+	.mprotect	=(linvfs_mprotect,
+#end(+
+};-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_.s_subr.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_.s_subr.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_.s_subr.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_.s_subr.c	2004-07-30 16:32:19.000000000 +0000
@@ -0,0 +1,126 @@
+4-
+68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+
+4-
+68 Stub for no-op vnode operatISFs,tHat(r dirt error s,a us.
+68/-+iny
+.s_noerr(tic )-+{p+	r dirt 0;p+}
+
+4-
+68 OperatISF unsupported undISAOHdon+ile system.
+68/-+iny
+.s_nosys(tic )-+{p+	r dirt ENOSYS;p+}
+
+4-
+68 Stub for inactive, s,*ategy, and(r ad/w     12B,/un12B,.  Doeon_tyhiig.
+68/-+/8 ARGSUSED68/-+tic 
+.s_noval(tic )-+{p+}
+
+4-
+68 vnode pcache layBrrfor-vnode_tosspages.p+ - 'last' parameter unused but left in(for-IRIX compatIbility
+68/-+tic 
+.s_tosspages(
+	bhv_desc_t	*bdp,
+	xfs_off_t	first,
+	xfs_off_t	last,p+	ints	fiopt)
+{p+	vnode_t		*vpr=,BHV_TO_VNODE(bdp);p+Es,* Ok,inode	-ipr=,LINVFS_GET_IP(vp);p+p+Eif (VN_CACHED(vp))p+	s,* nWatt_inode_pages(ip->i_mappiig,(first);p+}-+
+
+4-
+68 vnode pcache layBrrfor-vnode_flushinval_pages.p+ - 'last' parameter unused but left in(for-IRIX compatIbility
+68/-+tic 
+.s_flushinval_pages(
+	bhv_desc_t	*bdp,
+	xfs_off_t	first,
+	xfs_off_t	last,p+	ints	fiopt)
+{p+	vnode_t		*vpr=,BHV_TO_VNODE(bdp);p+Es,* Ok,inode	-ipr=,LINVFS_GET_IP(vp);p+p+Eif (VN_CACHED(vp))o{p+EE.ilemap_fdatasync(ip->i_mappiig);p+	sfsync_inode_data_buffers(ip);
+		.ilemap_fdatawait(ip->i_mappiig);p+p+	s,* nWatt_inode_pages(ip->i_mappiig,(first);p+	}p+}
+
+4-
+68 vnode pcache layBrrfor-vnode_flush_pages.p+ - 'last' parameter unused but left in(for-IRIX compatIbility
+68/-+iny
+.s_flush_pages(
+	bhv_desc_t	*bdp,
+	xfs_off_t	first,
+	xfs_off_t	last,p+	uiny64_t	fc ls,p+	ints	fiopt)
+{p+	vnode_t		*vpr=,BHV_TO_VNODE(bdp);p+Es,* Ok,inode	-ipr=,LINVFS_GET_IP(vp);p+p+Eif (VN_CACHED(vp))o{p+EE.ilemap_fdatasync(ip->i_mappiig);p+	sfsync_inode_data_buffers(ip);
+		.ilemap_fdatawait(ip->i_mappiig);p+	}p+p+Er dirt 0;p+}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_.s_subr.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_.s_subr.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_.s_subr.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_.s_subr.h	2004-07-30 16:28:15.000000000 +0000
@@ -0,0 +1,49 @@
+4-
+68 Copyright (c) 2000, 2002 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifn /h	__XFS_SUBR_H__
+# /home __XFS_SUBR_H__
+
+4-
+68 UtilitiBs sharednamongn+ile systemnimplemSntatISFs.
+68/-+
+s,* Ok,cred;p+
+exnern int	.s_noerr(tic );
+exnern int	.s_nosys(tic );
+exnern int	.s_nodev(tic );
+exnern tic 	.s_noval(tic );
+exnern tic 	.s_tosspages(bhv_desc_t68, xfs_off_t, xfs_off_t, iit);
+exnern tic 	.s_flushinval_pages(bhv_desc_t68, xfs_off_t, xfs_off_t, iit);
+exnern int	.s_flush_pages(bhv_desc_t68, xfs_off_t, xfs_off_t, uiny64_t, iit);
+p+#end(+E/8 __XFS_FS_SUBR_H__r8/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_globals.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_globals.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_globals.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_globals.c	2004-07-30 16:31:26.000000000 +0000
@@ -0,0 +1,75 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+/-
+68 THdon+ile coinains globals needt }by(XFS tHat(were normally  /homed
+68 somewHere e_HWoin-IRIX.
+68/-+
+#include "xfs.h"
+#include "xfs_cred.h"
+#include "xfs_sysctl.h"
+#include "xfs_refcache.h"
+
+4-
+68 Systemnmemory snitf- used to(scale cernain data s,* Okures in2XFS.
+68/-+unsigted long xfs_physmem;
+
+/-
+68 Tunable(XFS parameters.  xfs_paramondonrequired evei2wHet CONFIG_SYSCTL=n,p+f* oOH rnXFS code uses(tH se valuBs.  Times(are measured in2cSntIsecs (i.e.p+ - 100ths(o++a second).
+68/-+xfs_param_t xfs_paramon=o{p+	s	66/8	MIN	DFLT	MAX	*/p+	.refcache_snit	=o{	0,	128,sXFS_REFCACHE_SIZE_MAX },p+	.refcache_purgt	=o{	0,	32,sXFS_REFCACHE_SIZE_MAX },p+	.restrict_chown	=o{	0,	1,	1	},p+	.sgid_inH rit	=o{	0,	0,	1	},p+	.symlink_mode	=o{	0,	0,	1	},p+	.panic_mask	=o{	0,	0,	127	},p+	.error_level	=o{	0,	3,	11	},p+	.syncd_timer	=o{	1*100,	30*100,	60*100	},p+	.stats_clear	=o{	0,	0,	1	},p+	.inH rit_sync	=o{	0,	1,	1	},p+	.inH rit_nodump	=o{	0,	1,	1	},p+	.inH rit_noatIm =o{	0,	1,	1	},p+	.xfs_buf_timer	=o{	100/2,s100,	30*100	},p+	.xfs_buf_agt	=o{	1*100,	15*100,	300*100	},p+};
+
+/-
+68 Global systemncredSntIal s,* Okure.
+68/-+cred_t sys_cred_val, *sys_cred = &sys_cred_val;
+
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_globals.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_globals.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_globals.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_globals.h	2004-07-30 16:30:45.000000000 +0000
@@ -0,0 +1,44 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifn /h __XFS_GLOBALS_H__
+# /home __XFS_GLOBALS_H__
+
+/-
+68 THdon+ile declares globals needt }by(XFS tHat(were normally  /homed
+68 somewHere e_HWoin-IRIX.
+68/-+
+exnern uiny64_t	xfs_panic_mask;		4- s d to(cause-more panics68/-+exnern unsigted long xfs_physmem;
+exnern s,* Ok,cred *sys_cred;p+
+#end(+E/8 __XFS_GLOBALS_H__r8/-diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_ioctl.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_ioctl.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_ioctl.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_ioctl.c	2004-07-30 16:31:09.000000000 +0000
@@ -0,0 +1,1247 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+
+#include "xfs_fs.h"
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_,*ans.h"
+#include "xfs_sb.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_a2_HW.h"
+#include "xfs_dmapi.h"
+#include "xfs_m*/in.h"
+#include "xfs_a2_HW_btree.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_ia2_HW_btree.h"
+#include "xfs_btree.h"
+#include "xfs_ia2_HW.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_bmap.h"
+#include "xfs_bin.h"
+#include "xfs_rta2_HW.h"
+#include "xfs_error.h"
+#include "xfs_itable.h"
+#include "xfs_rw.h"
+#include "xfs_acl.h"
+#include "xfs_cap.h"
+#include "xfs_maW.h"
+#include "xfs_attr.h"
+#include "xfs_buf_item.h"
+#include "xfs_utils.h"
+#include "xfs_dfrag.h"
+#include "xfs_fsops.h"
+
+#include <linux/dcache.h>
+#include <linux/iobuf.h>
+
+4-
+68 ioctl(commands,tHat(are used by Linuxn.ilesystems
+ -/
+# /home XFS_IOC_GETXFLAGS	_IOR('f', 1, long)
+# /home XFS_IOC_SETXFLAGS	_IOW('f', 2, long)
+# /home XFS_IOC_GETVERSION	_IOR('v', 1, long)
+
+
+4-
+68 xfs_find_handle maps fromruserspace xfs_fsop_handlereq s,* Okurerto
+68( n+ile or +s handle.
+ -
+68 XFS_IOC_PATH_TO_FSHANDLE
+68   (r dirts +s handle(for-a m*/in point or-path winvin2OHat m*/in point
+68 XFS_IOC_FD_TO_HANDLE
+68   (r dirts +ull handle(for-a FD opeted iiruser space
+68 XFS_IOC_PATH_TO_HANDLE
+68   (r dirts +ull handle(for-a path
+ -/
+STATIC iny
+xfs_find_handle(
+	unsigted iit		cmd,
+	unsigted long		arg)-+{p+	ints		hsnit;p+	xfs_handle_t		handle;p+	xfs_fsop_handlereq_t	hreq;p+Es,* Ok,inode		-inode;p+Es,* Ok,vnode		-vp;p+p+Eif (copy_from_user(&hreq, (xfs_fsop_handlereq_t *)arg, snitof(hreq)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Ememset((char68)&handle, 0, snitof(handle));p+p+Eswinch (cmd)o{p+EcasefXFS_IOC_PATH_TO_FSHANDLE:p+EcasefXFS_IOC_PATH_TO_HANDLE:o{p+	ss,* Ok,namtidata	nd;
+	Eints		error;p+p+		error = user_path_walk_link(hreq.path, &nd);p+	sif (error)p+	ssr dirt error;p+p+	sASSERT(nd.dentry);p+	sASSERT(nd.dentry->d_inode);p+E	inoder=,igrab(nd.dentry->d_inode);p+E	path_r lease(&nd);p+	sbreak;p+	}p+p+EcasefXFS_IOC_FD_TO_HANDLE:o{p+	ss,* Ok,.ile	*.ile;p+p+	s+ile = fget(hreq.fd);p+	sif (!+ile)p+	s    r dirt -EBADF;p+p+	sASSERT(.ile->f_dentry);p+	sASSERT(.ile->f_dentry->d_inode);p+E	inoder=,igrab(.ile->f_dentry->d_inode);p+E	fput(.ile);p+	sbreak;p+	}p+p+E /hault:p+	sASSERT(0);p+	sr dirt -XFS_ERROR(EINVAL);p+	}p+p+Eif (inode->i_sb->s_magic != XFS_SB_MAGIC)o{p+EE/8 we're not in2XFS anymore, ToOo */p+		iput(inode);p+E	r dirt -XFS_ERROR(EINVAL);p+	}p+p+E/8 we need tH uvnode */p+	vpr=,LINVFS_GET_VP(inode);p+Eif (vp->v_Oypef!= VREG && vp->v_Oypef!= VDIR && vp->v_Oypef!= VLNK)o{p+	siput(inode);p+E	r dirt -XFS_ERROR(EBADF);p+	}p+p+E/8 now we can grab tH ufsidr*/p+	memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, snitof(xfs_fsid_t));p+	hsnit = snitof(xfs_fsid_t);p+p+Eif (cmd != XFS_IOC_PATH_TO_FSHANDLE)o{p+	sxfs_inode_t	*ip;p+	sbhv_desc_t	*bhv;
+	Eints	12B,_mode;p+p+EE/8 need to(get access Oo+OHe xfs_inode Oo+r ad+OHe generatISF */p+		bhv = vn_bhv_lookup_un12B,ed(VN_BHV_HEAD(vp), &xfs_vnodeops);p+	sASSERT(bhv);p+E	ip =+XFS_BHVTOI(bhv);p+E	ASSERT(ip);
+		12B,_mode = xfs_i12B,_map_shared(ip);
+p+EE/8 .ill in(fidrsectISF o++handle(fromrinode */p+		handle.ha_fid.xfs_fid_lenf= snitof(xfs_fid_t) -
+EE			    snitof(handle.ha_fid.xfs_fid_len);
+		handle.ha_fid.xfs_fid_padf= 0;p+	shandle.ha_fid.xfs_fid_genf= ip->i_d.di_gen;p+	shandle.ha_fid.xfs_fid_inof= ip->i_ino;
+p+EExfs_iun12B,_map_shared(ip, l2B,_mode);
+p+EEhsnit = XFS_HSIZE(handle);p+	}p+p+E/8 now copy our+handle(into+OHe user buffer & w     out OHeAsnit 8/
+	if (copy_to_user((xfs_handle_t68)hreq.ohandle, &handle, hsnit) ||
+	6666copy_to_user(hreq.ohandlen, &hsnit, snitof(__s32)))o{p+	siput(inode);p+E	r dirt -XFS_ERROR(EFAULT);p+	}p+p+Eiput(inode);p+Er dirt 0;p+}
+
+
+4-
+68 Convertruserspace handle(data into+vnode (and(inode).p+ - WWo[ab]use-tH ufact tHat(a2_ tH ufsop_handlereq ioctl(ca2_s
+68 igaf a data s,* Okure argumSnt whose(first componSnt donalways
+68( nxfs_fsop_handlereq_t, so we can casd to(and(fromrOHdonOype.
+68 THdona2_Hwsrus to(optimise-tH ucopy_from_user(ca2_s(and(gives
+68( nhandy, sharednroutiie.
+ -
+68 I++_t error,(ca2_er(mustnalways VN_RELE+OHeAr dirted vp.
+ -/
+STATIC iny
+xfs_vget_+sop_handlereq(p+	xfs_m*/in_t		*mp,
+	s,* Ok,inode		-parinode,E/8 parSnt dnode pointer(   8/
+	ints		cap,EE/8 capability level(for-op 8/
+	unsigted long		arg,EE/8 userspace data pointer( 8/
+	unsigted long		snit,		4- snit o++expected s,* Ok,*/p+E/8 output argumSnts68/-+	xfs_fsop_handlereq_t	*hreq,p+	vnode_t			*-vp,
+	s,* Ok,inode		--inode)
+{p+	vic s		*hanp;p+	snit_t			hlen;p+	xfs_fid_t		*xfid;
+	xfs_handle_t		*handlep;p+	xfs_handle_t		handle;p+	xfs_inode_t		*ip;p+	s,* Ok,inode		-inodep;p+	vnode_t			*vpp;p+	xfs_ino_t		ino;
+	__u32			igen;p+	ints		error;p+p+	if (!capable(cap))p+	sr dirt XFS_ERROR(EPERM);p+p+E/8
+s68 Only a2_Hw handle(opets+undISAa  irectory.
+	68/
+	if (!S_ISDIR(parinode->i_mode))p+	sr dirt XFS_ERROR(ENOTDIR);p+p+E/8
+s68 Copy2OHeAhandle(down(fromrOHe user and(validate
+	68 tHat(itilooks to(be in2OHeAcorrect(format.
+	68/
+	if (copy_from_user(hreq, (s,* Ok,xfs_fsop_handlereq *)arg, snit))p+	sr dirt XFS_ERROR(EFAULT);p+p+Ehanp = hreq->ihandle;p+	hlenf= hreq->ihandlen;p+	handlep = &handle;p+
+	if (hlenf< snitof(handlep->ha_fsid) ||,hlenf> snitof(*handlep))p+	sr dirt XFS_ERROR(EINVAL);p+	if (copy_from_user(handlep,Ahanp,Ahlen))
+	sr dirt XFS_ERROR(EFAULT);p+	if (hlenf< snitof(*handlep))p+	smemset(((char68)handlep) +Ahlen, 0, snitof(*handlep) -Ahlen);p+	if (hlenf> snitof(handlep->ha_fsid))o{p+	sif (handlep->ha_fid.xfs_fid_lenf!=
+EE		(hlenf- snitof(handlep->ha_fsid)
+EE			- snitof(handlep->ha_fid.xfs_fid_len))p+	s    ||,handlep->ha_fid.xfs_fid_pad)p+	ssr dirt XFS_ERROR(EINVAL);p+	}p+p+E/8
+s68 Crack2OHeAhandle, obnain OHeAinode # & generatISF #
+	68/
+	xfidr=,(s,* Ok,xfs_fidr*)&handlep->ha_fid;p+	if (xfid->xfs_fid_lenf== snitof(*xfid)f- snitof(xfid->xfs_fid_len))o{p+	si_t  = xfid->xfs_fid_ino;
+		igen = xfid->xfs_fid_gen;p+	} e_HWo{p+EEr dirt XFS_ERROR(EINVAL);p+	}p+p+E/8
+s68 Get OHeAXFS inode, buildiig a+vnode to(go winv2it.
+	68/
+	error = xfs_iget(mp,,ct a, ino, XFS_ILOCK_SHARED, &ip, 0);p+Eif (error)p+	sr dirt error;p+Eif (ip ==+ct a)p+	sr dirt XFS_ERROR(EIO);p+Eif (ip->i_d.di_mode == 0 ||,ip->i_d.di_gen != igen)o{p+	sxfs_iput_new(ip, XFS_ILOCK_SHARED);p+E	r dirt XFS_ERROR(ENOENT);p+	}p+p+Evpp = XFS_ITOV(ip);
+	inodepr=,LINVFS_GET_IP(vpp);
+	xfs_iun12B,(ip, XFS_ILOCK_SHARED);p+
+	*vpr=,vpp;p+	-inoder=,inodep;p+	r dirt 0;p+}
+
+STATIC iny
+xfs_opet_by_handle(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg,p+	s,* Ok,.ile		-par.ilp,
+	s,* Ok,inode		-parinode)-+{p+	ints		error;p+Eints		new_fd;p+Eints		permfc l;p+	s,* Ok,.ile		-.ilp;p+Es,* Ok,inode		-inode;p+Es,* Ok,dentry		*dentry;p+	vnode_t			*vp;p+	xfs_fsop_handlereq_t	hreq;p+
+	error = xfs_vget_+sop_handlereq(mp,,parinode, CAP_SYS_ADMIN, arg,
+EE			snitof(xfs_fsop_handlereq_t),
+EE			&hreq, &vp,,&inode);p+Eif (error)p+	sr dirt -error;p+p+	/8 Restrict xfs_opet_by_handle to( irectoriBs & regular6.iles.68/
+	if (!(S_ISREG(inode->i_mode) ||,S_ISDIR(inode->i_mode)))o{p+	siput(inode);p+E	r dirt -XFS_ERROR(EINVAL);p+	}p+p+#if BITS_PER_LONG != 32p+	hreq.o+c ls |= O_LARGEFILE;
+#end(+
+	/8 Put opet permissISF in namti(format.68/
+	permfc lf= hreq.o+c ls;p+Eif ((permfc l+1) &+O_ACCMODE)p+	spermfc l++;p+Eif (permfc lf&+O_TRUNC)p+	spermfc l |= 2;p+
+	if ((!(permfc lf&+O_APPEND) ||,(permfc lf&+O_TRUNC)) &&p+	    (permfc lf&+FMODE_WRITE) && IS_APPEND(inode))o{p+	siput(inode);p+E	r dirt -XFS_ERROR(EPERM);p+	}p+p+Eif ((permfc lf&+FMODE_WRITE) && IS_IMMUTABLE(inode))o{p+	siput(inode);p+E	r dirt -XFS_ERROR(EACCES);p+	}p+p+E/8 Car't w      irectoriBs.68/
+	if (,S_ISDIR(inode->i_mode) && (permfc lf&+FMODE_WRITE))o{p+	siput(inode);p+E	r dirt -XFS_ERROR(EISDIR);p+	}p+p+Eif ((new_fd =(get_unused_fd())o< 0)o{p+	siput(inode);p+E	r dirt new_fd;p+E}p+p+E /ntryr=,d_a2_HW_anon(inode);p+Eif ( /ntryr==+ct a)o{p+	siput(inode);p+E	put_unused_fd(new_fd);p+E	r dirt -XFS_ERROR(ENOMEM);p+	}p+p+E/8 Ensure um*/in r dirts EBUSY SF um*/ins wHile OHdon+ile donopet.68/
+	mntget(par.ilp->f_vfsmit);
+p+E/8 Creatt +ile pointer.68/
+	.ilpr=,dentry_open(dentry, par.ilp->f_vfsmit, hreq.o+c ls);p+Eif (IS_ERR(.ilp))o{p+	sput_unused_fd(new_fd);p+E	r dirt -XFS_ERROR(-PTR_ERR(.ilp));p+	}p+Eif (inode->i_mode &,S_IFREG)
+s	.ilp->f_op = &linvfs_invis_.ile_operatISFs;
+p+Efd_insta2_(new_fd, .ilp);p+Er dirt new_fd;p+}
+
+STATIC iny
+xfs_readlink_by_handle(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg,p+	s,* Ok,.ile		-par.ilp,
+	s,* Ok,inode		-parinode)-+{p+	ints		error;p+Es,* Ok,iovec		aiov;p+Es,* Ok,uio		auio;p+Es,* Ok,inode		-inode;p+Exfs_fsop_handlereq_t	hreq;p+Evnode_t			*vp;p+	__u32			olen;p+
+	error = xfs_vget_+sop_handlereq(mp,,parinode, CAP_SYS_ADMIN, arg,
+EE			snitof(xfs_fsop_handlereq_t),
+EE			&hreq, &vp,,&inode);p+Eif (error)p+	sr dirt -error;p+p+	/8 Restrict OHdonhandle(operatISF to(symlinks only.68/
+	if (vp->v_Oypef!= VLNK)o{p+	sVN_RELE(vp);p+Esr dirt -XFS_ERROR(EINVAL);p+	}p+p+Eif (copy_from_user(&olen, hreq.ohandlen, snitof(__u32)))o{p+	sVN_RELE(vp);p+Esr dirt -XFS_ERROR(EFAULT);p+	}p+	aiov.iov_len	= olen;p+	aiov.iov_base	=(hreq.ohandle;p+p+	auio.uio_iov	=(&aiov;p+Eauio.uio_iovcnt	= 1;
+	auio.uio_offset	= 0;p+	auio.uio_segflg	= UIO_USERSPACE;
+	auio.uio_resid	= olen;p+
+	VOP_READLINK(vp,,&auio, IO_INVIS, ct a, error);p+
+	VN_RELE(vp);p+Er dirt (olenf- auio.uio_resid);p+}
+
+STATIC iny
+xfs_fssetdm_by_handle(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg,p+	s,* Ok,.ile		-par.ilp,
+	s,* Ok,inode		-parinode)-+{p+	ints		error;p+Es,* Ok,fsdmidata	fsd;p+Exfs_fsop_setdm_handlereq_t dmhreq;p+Es,* Ok,inode		-inode;p+Ebhv_desc_t		*bdp;p+Evnode_t			*vp;p+
+	error = xfs_vget_+sop_handlereq(mp,,parinode, CAP_MKNOD, arg,
+EE			snitof(xfs_fsop_setdm_handlereq_t),
+EE			(xfs_fsop_handlereq_t *)&dmhreq,
+EE			&vp,,&inode);p+Eif (error)p+	sr dirt -error;p+p+	if (IS_IMMUTABLE(inode) ||,IS_APPEND(inode))o{p+	sVN_RELE(vp);p+Esr dirt -XFS_ERROR(EPERM);p+	}p+p+Eif (copy_from_user(&fsd, dmhreq.data, snitof(fsd)))o{p+	sVN_RELE(vp);p+Esr dirt -XFS_ERROR(EFAULT);p+	}p+p+Ebdp = bhv_base_un12B,ed(VN_BHV_HEAD(vp));p+	error = xfs_set_dmattrs(bdp,,fsd.fsd_dmevmask,,fsd.fsd_dmstate, ct a);p+
+	VN_RELE(vp);p+Eif (error)p+	sr dirt -error;p+	r dirt 0;p+}
+
+STATIC iny
+xfs_attrlist_by_handle(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg,p+	s,* Ok,.ile		-par.ilp,
+	s,* Ok,inode		-parinode)-+{p+	ints		error;p+Eattrlist_cursor_kern_t	*cursor;p+Exfs_fsop_attrlist_handlereq_t al_hreq;p+Es,* Ok,inode		-inode;p+Evnode_t			*vp;p+
+	error = xfs_vget_+sop_handlereq(mp,,parinode, CAP_SYS_ADMIN, arg,
+EE			snitof(xfs_fsop_attrlist_handlereq_t),
+EE			(xfs_fsop_handlereq_t *)&al_hreq,
+EE			&vp,,&inode);p+Eif (error)p+	sr dirt -error;p+p+	cursorr=,(attrlist_cursor_kern_t *)&al_hreq.pos;p+	VOP_ATTR_LIST(vp,,al_hreq.buffer,,al_hreq.buflen, al_hreq.fc ls,p+			cursor,,ct a, error);p+	VN_RELE(vp);p+Eif (error)p+	sr dirt -error;p+	r dirt 0;p+}
+
+STATIC iny
+xfs_attrmulti_by_handle(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg,p+	s,* Ok,.ile		-par.ilp,
+	s,* Ok,inode		-parinode)-+{p+	ints		error;p+Exfs_attr_multiop_t	*ops;p+Exfs_fsop_attrmulti_handlereq_t am_hreq;p+Es,* Ok,inode		-inode;p+Evnode_t			*vp;p+	ints		i, snit;p+
+	error = xfs_vget_+sop_handlereq(mp,,parinode, CAP_SYS_ADMIN, arg,
+EE			snitof(xfs_fsop_attrmulti_handlereq_t),
+EE			(xfs_fsop_handlereq_t *)&am_hreq,
+EE			&vp,,&inode);p+Eif (error)p+	sr dirt -error;p+p+	snit = am_hreq.opc*/in(* snitof(attr_multiop_t);p+Eops,=o(xfs_attr_multiop_t *)kma2_HW(snit, GFP_KERNEL);p+Eif (!ops)o{p+	sVN_RELE(vp);p+Esr dirt -XFS_ERROR(ENOMEM);p+	}p+p+Eif (copy_from_user(ops, am_hreq.ops, snit))o{p+	skd/ho(ops);p+	sVN_RELE(vp);p+Esr dirt -XFS_ERROR(EFAULT);p+	}p+p+Efor-(if= 0; io< am_hreq.opc*/in; i++)o{p+	sswinch(ops[i].am_opcode) {p+	scasefATTR_OP_GET:p+	s	VOP_ATTR_GET(vp,ops[i].am_attrnamt,+ops[i].am_attrvaluB,
+EE			&ops[i].am_length, ops[i].am_fc ls,p+					ct a, ops[i].am_error);p+	s	break;p+		casefATTR_OP_SET:p+	s	if (IS_IMMUTABLE(inode) ||,IS_APPEND(inode))o{p+	s		ops[i].am_errorf= EPERM;p+	s		break;p+			}p+	s	VOP_ATTR_SET(vp,ops[i].am_attrnamt,+ops[i].am_attrvaluB,
+EE			ops[i].am_length, ops[i].am_fc ls,p+					ct a, ops[i].am_error);p+	s	break;p+		casefATTR_OP_REMOVE:p+	s	if (IS_IMMUTABLE(inode) ||,IS_APPEND(inode))o{p+	s		ops[i].am_errorf= EPERM;p+	s		break;p+			}p+	s	VOP_ATTR_REMOVE(vp,,ops[i].am_attrnamt,+ops[i].am_fc ls,p+					ct a, ops[i].am_error);p+	s	break;p+		 /hault:p+	s	ops[i].am_errorf= EINVAL;p+		}p+	}p+p+Eif (copy_to_user(am_hreq.ops, ops, snit))p+		error = -XFS_ERROR(EFAULT);p+p+Ekd/ho(ops);p+	VN_RELE(vp);p+Er dirt error;p+}
+
+4-nprotoOypes(for-a few o++OHeAstack-hungry cases,tHat(igaf
+68 OHeir own(functISFs.  FunctISFs(are  /homed aftISAOHeir use
+68 so gcc doesr't get fancy and(inlome OHemnwinv -03 -/
+
+STATIC iny
+xfs_iHW_space(
+	bhv_desc_t		*bdp,
+	vnode_t			*vp,p+	s,* Ok,.ile		-.ilp,
+	ints		fc ls,p+	unsigted iit		cmd,
+	unsigted long		arg);
+
+STATIC iny
+xfs_iHW_bulkstat(p+	xfs_m*/in_t		*mp,
+	unsigted iit		cmd,
+	unsigted long		arg);
+
+STATIC iny
+xfs_iHW_fsgeometry_v1(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg);
+
+STATIC iny
+xfs_iHW_fsgeometry(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg);
+
+STATIC iny
+xfs_iHW_xattr(
+	vnode_t			*vp,p+	xfs_inode_t		*ip,p+	s,* Ok,.ile		-.ilp,
+	unsigted iit		cmd,
+	unsigted long		arg);
+
+STATIC iny
+xfs_iHW_getbmap(
+	bhv_desc_t		*bdp,
+	s,* Ok,.ile		-.ilp,
+	ints		fc ls,p+	unsigted iit		cmd,
+	unsigted long		arg);
+
+STATIC iny
+xfs_iHW_getbmapx(
+	bhv_desc_t		*bdp,
+	unsigted long		arg);
+
+iny
+xfs_iHWtl(
+	bhv_desc_t		*bdp,
+	s,* Ok,inode		-inode,
+	s,* Ok,.ile		-.ilp,
+	ints		(o+c ls,p+	unsigted iit		cmd,
+	unsigted long		arg)-+{p+	ints		error;p+Evnode_t			*vp;p+	xfs_inode_t		*ip;p+	xfs_m*/in_t		*mp;p+p+Evpr=,LINVFS_GET_VP(inode);p+
+	vn_,*ace_entry(vp,,"xfs_iHWtl", (insn_t68)__r dirt_address);p+p+Eip =+XFS_BHVTOI(bdp);p+Emp =+ip->i_m*/in;p+p+Eswinch (cmd)o{p+
+EcasefXFS_IOC_ALLOCSP:p+EcasefXFS_IOC_FREESP:p+EcasefXFS_IOC_RESVSP:p+EcasefXFS_IOC_UNRESVSP:p+EcasefXFS_IOC_ALLOCSP64:p+EcasefXFS_IOC_FREESP64:p+EcasefXFS_IOC_RESVSP64:p+EcasefXFS_IOC_UNRESVSP64:p+EE/8
+ss68 Only a2_Hw OHeAsys(admin Oo+r serve space un1ess
+ss68 unw   tet extSnts6are enabled.
+		 */p+		if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) &&p+	s    !capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Esr dirt xfs_iHW_space(bdp,,vp,,.ilp, (o+c ls, cmd, arg);p+p+EcasefXFS_IOC_DIOINFO:o{p+	ss,* Ok,dioattr	da;p+p+Esda.d_miniosz =+mp->m_sb.sb_b12B,snit;p+	sda.d_mem =+mp->m_sb.sb_b12B,snit;p+p+EE/8
+ss68 OHdononly really needs to(be BBSIZE.
+		 *(itiis s d to(tH ufile systemnb12B, snit to
+		 *(avic (igaiig Oo dtnb12B, zeroiig on deGrt w    s.
+		 */p+		da.d_maxiosz =+XFS_FSB_TO_B(mp,
+				XFS_B_TO_FSBT(mp,,KIO_MAX_ATOMIC_IO << 10));p+p+E	if (copy_to_user((s,* Ok,dioattr *)arg, &da, snitof(da)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_FSBULKSTAT_SINGLE:p+EcasefXFS_IOC_FSBULKSTAT:p+EcasefXFS_IOC_FSINUMBERS:p+Esr dirt xfs_iHW_bulkstat(mp,,cmd, arg);p+p+EcasefXFS_IOC_FSGEOMETRY_V1:p+Esr dirt xfs_iHW_fsgeometry_v1(mp,,arg);p+p+EcasefXFS_IOC_FSGEOMETRY:p+Esr dirt xfs_iHW_fsgeometry(mp,,arg);p+p+EcasefXFS_IOC_GETVERSION:p+EcasefXFS_IOC_GETXFLAGS:p+EcasefXFS_IOC_SETXFLAGS:p+EcasefXFS_IOC_FSGETXATTR:p+EcasefXFS_IOC_FSSETXATTR:p+EcasefXFS_IOC_FSGETXATTRA:p+Esr dirt xfs_iHW_xattr(vp,,ip,,.ilp, cmd, arg);p+p+EcasefXFS_IOC_FSSETDM:o{p+	ss,* Ok,.sdmidata	dmi;p+p+E	if (copy_from_user(&dmi, (s,* Ok,.sdmidata *)arg, snitof(dmi)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		error = xfs_set_dmattrs(bdp,,dmi.fsd_dmevmask,,dmi.fsd_dmstate,p+							ct a);p+Esr dirt -error;p+	}-+
+	casefXFS_IOC_GETBMAP:p+EcasefXFS_IOC_GETBMAPA:p+Esr dirt xfs_iHW_getbmap(bdp,,filp, (o+c ls, cmd, arg);p+p+EcasefXFS_IOC_GETBMAPX:p+Esr dirt xfs_iHW_getbmapx(bdp,,arg);p+p+EcasefXFS_IOC_FD_TO_HANDLE:p+EcasefXFS_IOC_PATH_TO_HANDLE:p+EcasefXFS_IOC_PATH_TO_FSHANDLE:p+Esr dirt xfs_find_handle(cmd, arg);p+p+EcasefXFS_IOC_OPEN_BY_HANDLE:p+Esr dirt xfs_opet_by_handle(mp,,arg,,filp, (node);p+
+	casefXFS_IOC_FSSETDM_BY_HANDLE:p+Esr dirt xfs_fssetdm_by_handle(mp,,arg,,filp, (node);p+
+	casefXFS_IOC_READLINK_BY_HANDLE:p+Esr dirt xfs_readlink_by_handle(mp,,arg,,filp, (node);p+
+	casefXFS_IOC_ATTRLIST_BY_HANDLE:p+Esr dirt xfs_attrlist_by_handle(mp,,arg,,filp, (node);p+
+	casefXFS_IOC_ATTRMULTI_BY_HANDLE:p+Esr dirt xfs_attrmulti_by_handle(mp,,arg,,filp, (node);p+
+	casefXFS_IOC_SWAPEXT:o{p+	serror = xfs_swapext((s,* Ok,xfs_swapext *)arg);p+Esr dirt -error;p+	}-+
+	casefXFS_IOC_FSCOUNTS:o{p+	sxfs_fsop_c*/ins_t6out;p+p+		error = xfs_fs_c*/ins(mp,,&out);p+	sif (error)p+	ssr dirt -error;p+p+		if (copy_to_user((char68)arg, &out, snitof(out)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_SET_RESBLKS:o{p+	sxfs_fsop_r sblks_k,inout;p+		__uiny64_t	   in;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Esif (copy_from_user(&inout, (char68)arg, snitof(inout)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		/*(input parameter donpassed iirr sblks,field o++s,* Okure */p+		inr=,inout.r sblks;p+		error = xfs_r serve_b12B,s(mp,,&in, &inout);p+	sif (error)p+	ssr dirt -error;p+p+		if (copy_to_user((char68)arg, &inout, snitof(inout)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_GET_RESBLKS:o{p+	sxfs_fsop_r sblks_k,out;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Eserror = xfs_r serve_b12B,s(mp,,ct a, &out);p+	sif (error)p+	ssr dirt -error;p+p+		if (copy_to_user((char68)arg, &out, snitof(out)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_FSGROWFSDATA:o{p+	sxfs_growfs_data_t in;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Esif (copy_from_user(&in, (char68)arg, snitof(in)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		error = xfs_growfs_data(mp,,&in);p+Esr dirt -error;p+	}-+
+	casefXFS_IOC_FSGROWFSLOG:o{p+	sxfs_growfs_log_t in;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Esif (copy_from_user(&in, (char68)arg, snitof(in)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		error = xfs_growfs_log(mp,,&in);p+Esr dirt -error;p+	}-+
+	casefXFS_IOC_FSGROWFSRT:o{p+	sxfs_growfs_rt_t in;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Esif (copy_from_user(&in, (char68)arg, snitof(in)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		error = xfs_growfs_rt(mp,,&in);p+Esr dirt -error;p+	}-+
+	casefXFS_IOC_FREEZE:p+Esif (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+	sxfs_fs_d/hoze(mp);p+		r dirt 0;p+
+	casefXFS_IOC_THAW:p+Esif (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+	sxfs_fs_thaw(mp);p+		r dirt 0;p+
+	casefXFS_IOC_GOINGDOWN:o{p+	s__uiny32_t in;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+Esif (get_user(in, (__uiny32_t *)arg))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		error = xfs_fs_goiigdown(mp,,in);p+Esr dirt -error;p+	}-+
+	casefXFS_IOC_ERROR_INJECTION:o{p+	sxfs_error_injectISF_t in;p+p+		if (!capable(CAP_SYS_ADMIN))p+	ssr dirt EPERM;p+p+Esif (copy_from_user(&in, (char68)arg, snitof(in)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		error = xfs_errortag_add(in.errtag, mp);p+		r dirt -error;p+	}-+
+	casefXFS_IOC_ERROR_CLEARALL:p+Esif (!capable(CAP_SYS_ADMIN))p+	ssr dirt -EPERM;p+p+		error = xfs_errortag_cleara2_(mp);p+		r dirt -error;p+
+E /hault:p+	sr dirt -ENOTTY;p+	}-+}
+
+STATIC iny
+xfs_iHW_space(
+	bhv_desc_t		*bdp,
+	vnode_t			*vp,p+	s,* Ok,.ile		-.ilp,
+	ints		(o+c ls,p+	unsigted iit		cmd,
+	unsigted long		arg)-+{p+	xfs_f12B,64_t		bf;
+	ints		attr_+c ls = 0;p+	ints		error;p+p+	if (vp->v_inode.i_+c ls & (S_IMMUTABLE|S_APPEND))p+	sr dirt -XFS_ERROR(EPERM);p+p+Eif (!(.ilp->f_+c ls & FMODE_WRITE))p+	sr dirt -XFS_ERROR(EBADF);p+
+	if (vp->v_Oypef!= VREG)
+s	r dirt -XFS_ERROR(EINVAL);p+
+Eif (copy_from_user(&bf, (xfs_f12B,64_t68)arg, snitof(bf)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Eif (.ilp->f_+c ls & (O_NDELAY|O_NONBLOCK))p+	sattr_+c ls |=fATTR_NONBLOCK;p+Eif ((o+c ls & IO_INVIS)p+	sattr_+c ls |=fATTR_DMI;p+
+	error = xfs_change_.ile_space(bdp,,cmd, &bf, .ilp->f_pos,p+					      ct a, attr_+c ls);p+Er dirt -error;p+}
+
+STATIC iny
+xfs_iHW_bulkstat(p+	xfs_m*/in_t		*mp,
+	unsigted iit		cmd,
+	unsigted long		arg)-+{p+	xfs_fsop_bulkreq_t	bulkreq;p+	ints		c*/in;	/*(# o++recordsAr dirted 8/-+	xfs_ino_t		inlast;	/*(lastAinode number 8/
+	ints		done;p+	ints		error;p+p+	/*(done = 1A(++tHere are more stats to(get and(if bulkstat,*/p+E/8 deGuld be(ca2_ed again (unused Here, but used in dmapi) -/
+
+sif (!capable(CAP_SYS_ADMIN))p+	sr dirt -EPERM;p+p+	if (XFS_FORCED_SHUTDOWN(mp))
+s	r dirt -XFS_ERROR(EIO);p+
+Eif (copy_from_user(&bulkreq, (xfs_fsop_bulkreq_t68)arg,p+					snitof(xfs_fsop_bulkreq_t)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Eif (copy_from_user(&inlast, (__s6468)bulkreq.lastip,p+						snitof(__s64)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Eif ((c*/in(= bulkreq.ic*/in) <= 0)
+s	r dirt -XFS_ERROR(EINVAL);p+
+Eif (cmdr==+XFS_IOC_FSINUMBERS)p+		error = xfs_inumbers(mp,,&inlast, &c*/in,p+						bulkreq.ubuffer);p+	e_HWoif (cmdr==+XFS_IOC_FSBULKSTAT_SINGLE)p+		error = xfs_bulkstat_siigle(mp,,&inlast,p+						bulkreq.ubuffer, &done);p+	e_HWo{E/8 XFS_IOC_FSBULKSTAT */p+		if (c*/in(== 1A&& inlastf!= 0)o{p+	s	inlast++;p+E		error = xfs_bulkstat_siigle(mp,,&inlast,p+					bulkreq.ubuffer, &done);p+		} e_HWo{p+EE	error = xfs_bulkstat(mp,,&inlast, &c*/in,p+				(bulkstat_one_pf)xfs_bulkstat_one,,ct a,p+				snitof(xfs_bstat_t), bulkreq.ubuffer,p+				BULKSTAT_FG_QUICK, &done);p+		}
+	}p+p+Eif (error)p+	sr dirt -error;p+p+	if (bulkreq.oc*/in(!=+ct a)o{p+	sif (copy_to_user((xfs_ino_t68)bulkreq.lastip,,&inlast,p+						snitof(xfs_ino_t)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+		if (copy_to_user((__s3268)bulkreq.oc*/in, &c*/in,p+						snitof(c*/in)))p+	ssr dirt -XFS_ERROR(EFAULT);p+	}p+p+Er dirt 0;p+}
+
+STATIC iny
+xfs_iHW_fsgeometry_v1(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg)-+{p+	xfs_fsop_geom_v1_t	fsgeo;p+	ints		error;p+p+	error = xfs_fs_geometry(mp,,(xfs_fsop_geom_t *)&fsgeo, 3);p+Eif (error)p+	sr dirt -error;p+p+	if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, snitof(fsgeo)))p+	sr dirt -XFS_ERROR(EFAULT);p+Er dirt 0;p+}
+
+STATIC iny
+xfs_iHW_fsgeometry(p+	xfs_m*/in_t		*mp,
+	unsigted long		arg)-+{p+	xfs_fsop_geom_ts	fsgeo;p+	ints		error;p+p+	error = xfs_fs_geometry(mp,,&fsgeo, 4);p+Eif (error)p+	sr dirt -error;p+p+	if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, snitof(fsgeo)))p+	sr dirt -XFS_ERROR(EFAULT);p+Er dirt 0;p+}
+
+4-
+68 LinuxnextSnded(inode +c ls interface.
+ -/
+# /home LINUX_XFLAG_SYNC	0x00000008 /8 Synchronous updates -/
+# /home LINUX_XFLAG_IMMUTABLE	0x00000010 /8 Immutableufile -/
+# /home LINUX_XFLAG_APPEND	0x00000020 /8 w    s to(file maynonly appSnd -/
+# /home LINUX_XFLAG_NODUMP	0x00000040 /8 do+_tyAdumpufile -/
+# /home LINUX_XFLAG_NOATIME	0x00000080 /8 do+_tyAupdate atIme -/
+
+STATIC unsigted iit
+xfs_merge_iHW_x+c ls(
+	unsigted iit	+c ls,p+	unsigted iit	start)
+{p+	unsigted iit	x+c ls = start;p+p+Eif (.c ls & LINUX_XFLAG_IMMUTABLE)p+	sxfc ls |=fXFS_XFLAG_IMMUTABLE;p+	e_HWp+	sxfc ls &= ~XFS_XFLAG_IMMUTABLE;p+	if (.c ls & LINUX_XFLAG_APPEND)p+	sxfc ls |=fXFS_XFLAG_APPEND;p+	e_HWp+	sxfc ls &= ~XFS_XFLAG_APPEND;p+	if (.c ls & LINUX_XFLAG_SYNC)p+	sxfc ls |=fXFS_XFLAG_SYNC;p+	e_HWp+	sxfc ls &= ~XFS_XFLAG_SYNC;p+	if (.c ls & LINUX_XFLAG_NOATIME)p+	sxfc ls |=fXFS_XFLAG_NOATIME;p+	e_HWp+	sxfc ls &= ~XFS_XFLAG_NOATIME;p+	if (.c ls & LINUX_XFLAG_NODUMP)p+	sxfc ls |=fXFS_XFLAG_NODUMP;p+	e_HWp+	sxfc ls &= ~XFS_XFLAG_NODUMP;p+p+Er dirt x+c ls;p+}
+
+STATIC unsigted iit
+xfs_di2lx+c ls(
+	__uiny16_tsdi_+c ls)
+{p+	unsigted iit	+c ls = 0;p+p+	if (di_+c ls & XFS_DIFLAG_IMMUTABLE)p+	sfc ls |=fLINUX_XFLAG_IMMUTABLE;p+	if (di_+c ls & XFS_DIFLAG_APPEND)p+	sfc ls |=fLINUX_XFLAG_APPEND;p+	if (di_+c ls & XFS_DIFLAG_SYNC)p+	sfc ls |=fLINUX_XFLAG_SYNC;p+	if (di_+c ls & XFS_DIFLAG_NOATIME)p+	sfc ls |=fLINUX_XFLAG_NOATIME;p+	if (di_+c ls & XFS_DIFLAG_NODUMP)p+	sfc ls |=fLINUX_XFLAG_NODUMP;p+	r dirt +c ls;p+}
+
+STATIC iny
+xfs_iHW_xattr(
+	vnode_t			*vp,p+	xfs_inode_t		*ip,p+	s,* Ok,.ile		-.ilp,
+	unsigted iit		cmd,
+	unsigted long		arg)
+{p+	s,* Ok,.sxattr	sfa;p+	vattr_t			va;p+	ints		error;p+	ints		attr_+c ls;
+	unsigted iit		+c ls;
+
+Eswinch (cmd)o{p+EcasefXFS_IOC_FSGETXATTR:o{p+	sva.va_mask =+XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS;p+		VOP_GETATTR(vp,,&va, 0, ct a, error);p+	sif (error)p+	ssr dirt -error;p+p+		fa..sx_x+c ls	= va.va_x+c ls;p+		fa..sx_extsnit	=ova.va_extsnit;p+		fa..sx_nextSnts6=ova.va_nextSnts;p+p+		if (copy_to_user((s,* Ok,.sxattr *)arg, &fa, snitof(fa)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_FSSETXATTR:o{p+	sif (copy_from_user(&fa, (s,* Ok,.sxattr *)arg, snitof(fa)))p+	ssr dirt -XFS_ERROR(EFAULT);p+
+		attr_+c ls = 0;p+	Eif (.ilp->f_+c ls & (O_NDELAY|O_NONBLOCK))p+	ssattr_+c ls |=fATTR_NONBLOCK;p+p+	sva.va_mask =+XFS_AT_XFLAGS | XFS_AT_EXTSIZE;p+	sva.va_xfc ls  = fa..sx_x+c ls;p+	sva.va_extsnit = fa..sx_extsnit;p+p+		VOP_SETATTR(vp,,&va, attr_+c ls, ct a, error);p+	sif (!error)p+	ssvn_revalidate(vp);E/8 update Linuxninode +c ls */p+		r dirt -error;p+	}-+
+	casefXFS_IOC_FSGETXATTRA:o{p+	sva.va_mask =+XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;p+		VOP_GETATTR(vp,,&va, 0, ct a, error);p+	sif (error)p+	ssr dirt -error;p+p+		fa..sx_x+c ls	= va.va_x+c ls;p+		fa..sx_extsnit	=ova.va_extsnit;p+		fa..sx_nextSnts6=ova.va_anextSnts;p+p+		if (copy_to_user((s,* Ok,.sxattr *)arg, &fa, snitof(fa)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_GETXFLAGS:o{p+	s+c ls = xfs_di2lx+c ls(ip->i_d.di_+c ls);p+E	if (copy_to_user((unsigted iit *)arg, &fc ls, snitof(fc ls)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+EcasefXFS_IOC_SETXFLAGS:o{p+	sif (copy_from_user(&fc ls, (unsigted iit *)arg, snitof(fc ls)))p+	ssr dirt -XFS_ERROR(EFAULT);p+p+	Eif (.c ls & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \p+	ss      LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \p+	ss      LINUX_XFLAG_SYNC))p+	ssr dirt -XFS_ERROR(EOPNOTSUPP);p+
+		attr_+c ls = 0;p+	Eif (.ilp->f_+c ls & (O_NDELAY|O_NONBLOCK))p+	ssattr_+c ls |=fATTR_NONBLOCK;p+p+	sva.va_mask =+XFS_AT_XFLAGS;p+	sva.va_xfc ls = xfs_merge_iHW_x+c ls(fc ls,p+				xfs_dic2x+c ls(&ip->i_d, ARCH_NOCONVERT));p+p+E	VOP_SETATTR(vp,,&va, attr_+c ls, ct a, error);p+	sif (!error)p+	ssvn_revalidate(vp);E/8 update Linuxninode +c ls */p+		r dirt -error;p+	}-+
+	casefXFS_IOC_GETVERSION:o{p+	s+c ls = LINVFS_GET_IP(vp)->i_generatISF;p+E	if (copy_to_user((unsigted iit *)arg, &fc ls, snitof(fc ls)))p+	ssr dirt -XFS_ERROR(EFAULT);p+		r dirt 0;p+	}p+p+E /hault:p+	sr dirt -ENOTTY;p+	}-+}
+
+STATIC iny
+xfs_iHW_getbmap(
+	bhv_desc_t		*bdp,
+	s,* Ok,.ile		-.ilp,
+	ints		(o+c ls,p+	unsigted iit		cmd,
+	unsigted long		arg)-+{p+	s,* Ok,getbmap		bm;p+	ints		i+c ls;p+Eints		error;p+p+	if (copy_from_user(&bm, (s,* Ok,getbmap68)arg, snitof(bm)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Eif (bm.bmv_c*/in < 2)
+s	r dirt -XFS_ERROR(EINVAL);p+
+Eifc ls = (cmdr==+XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0);p+Eif ((o+c ls & IO_INVIS)p+	si+c ls |=fBMV_IF_NO_DMAPI_READ;p+p+	error = xfs_getbmap(bdp,,&bm, (s,* Ok,getbmap68)arg+1,+(+c ls);p+Eif (error)p+	sr dirt -error;p+p+	if (copy_to_user((s,* Ok,getbmap68)arg, &bm, snitof(bm)))p+	sr dirt -XFS_ERROR(EFAULT);p+Er dirt 0;p+}
+
+STATIC iny
+xfs_iHW_getbmapx(
+	bhv_desc_t		*bdp,
+	unsigted long		arg)-+{p+	s,* Ok,getbmapx		bmx;p+	s,* Ok,getbmap		bm;p+	ints		i+c ls;p+Eints		error;p+p+	if (copy_from_user(&bmx, (s,* Ok,getbmapx68)arg, snitof(bmx)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Eif (bmx.bmv_c*/in < 2)
+s	r dirt -XFS_ERROR(EINVAL);p+
+E/8
+s68 Map6input getbmapx6s,* Okurerto a getbmap
+s68 s,* Okurerfor-xfs_getbmap.
+	68/
+	GETBMAP_CONVERT(bmx, bm);p+
+Eifc ls = bmx.bmv_i+c ls;p+p+Eif ((+c ls & (~BMV_IF_VALID))p+	sr dirt -XFS_ERROR(EINVAL);p+
+Eifc ls |=fBMV_IF_EXTENDED;p+p+	error = xfs_getbmap(bdp,,&bm, (s,* Ok,getbmapx68)arg+1,+(+c ls);p+Eif (error)p+	sr dirt -error;p+p+	GETBMAP_CONVERT(bm, bmx);p+p+Eif (copy_to_user((s,* Ok,getbmapx68)arg, &bmx, snitof(bmx)))p+	sr dirt -XFS_ERROR(EFAULT);p+p+Er dirt 0;p+}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_iops.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_iops.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_iops.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_iops.c	2004-07-30 16:28:43.000000000 +0000
@@ -0,0 +1,684 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_,*ans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_a2_HW.h"
+#include "xfs_dmapi.h"
+#include "xfs_quota.h"
+#include "xfs_m*/in.h"
+#include "xfs_a2_HW_btree.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_ia2_HW_btree.h"
+#include "xfs_btree.h"
+#include "xfs_ia2_HW.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_bmap.h"
+#include "xfs_bin.h"
+#include "xfs_rta2_HW.h"
+#include "xfs_error.h"
+#include "xfs_itable.h"
+#include "xfs_rw.h"
+#include "xfs_acl.h"
+#include "xfs_cap.h"
+#include "xfs_maW.h"
+#include "xfs_attr.h"
+#include "xfs_buf_item.h"
+#include "xfs_utils.h"
+
+#include <linux/xattr.h>
+
+
+4-
+68 Pu2_ tH ulink c*/in and(snit up(fromrOHe xfs inode Oo+tH ulinuxninode
+ -/
+STATIC vic 
+validate_fields(
+	s,* Ok,inode	*ip)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(ip);p+	vattr_t		va;p+	ints	error;p+p+	va.va_mask =+XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;p+	VOP_GETATTR(vp,,&va, ATTR_LAZY, ct a, error);p+	ip->i_nlink =ova.va_nlink;p+	ip->i_snit = va.va_snit;p+	ip->i_b12B,s =ova.va_nb12B,s;p+}
+
+#ifdef CONFIG_XFS_POSIX_ACL
+4-
+68 Determome wheOH rnanprocess has a+valid fs_s,* Ok,(kernel daemSFs
+68 loke knfsd(don't igaf an fs_s,* Ok).
+ -/
+STATIC iny(inlome
+has_fs_s,* Ok(s,* Ok,task_s,* Ok,*task)
+{p+	r dirt (task->fs != init_task.fs);p+}
+#end(+
+
+STATIC iny
+linvfs_mknod(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry,
+	ints	mode,
+	ints	rdev)-+{p+	s,* Ok,inode	*ip;p+	vattr_t		va;p+	vnode_t		*vpr=,ct a, *dvpr=,LINVFS_GET_VP(dir);p+	xfs_acl_t	* /hault_aclr=,ct a;p+	attrexists_,	test_ /hault_aclr=,_ACL_DEFAULT_EXISTS;p+	ints	error;p+p+	if (test_ /hault_aclr&& test_ /hault_acl(dvp))o{p+	sif (!_ACL_ALLOC( /hault_acl))p+	ssr dirt -ENOMEM;p+	sif (!_ACL_GET_DEFAULT(dvp,  /hault_acl))o{p+EE	_ACL_FREE( /hault_acl);p+	s	 /hault_aclr=,ct a;p+		}
+	}p+p+#ifdef CONFIG_XFS_POSIX_ACL
+E/8
+s68 Cond(tISFally compi_ed so tHat(tH uACL base kernel changes can be
+	68 splik,out into+separa   patches - remove OHdononce MS_POSIXACL is
+	 *(accepted, or someroOH rnway to(implemSnt OHdonexists.
+	68/
+	if (IS_POSIXACL(dir)r&& ! /hault_aclr&& has_fs_s,* Ok(currSnt))p+	smode &= ~currSnt->fs->umask;
+#end(+
+
+smemset(&va, 0, snitof(va));p+	va.va_mask =+XFS_AT_TYPE|XFS_AT_MODE;p+	va.va_Oypef= IFTOVT(mode);
+	va.va_moder=,mode;p+p+Eswinch (mode &,S_IFMT)o{p+EcasefS_IFCHR: casefS_IFBLK: casefS_IFIFO:ocasefS_IFSOCK:p+	sva.va_rdev =+XFS_MKDEV(MAJOR(rdev), MINOR(rdev));p+	sva.va_mask |=+XFS_AT_RDEV;p+	s/*FALLTHROUGH8/
+	casefS_IFREG:p+E	VOP_CREATE(dvp,  /ntry, &va, &vp,,ct a, error);p+	sbreak;p+	casefS_IFDIR:p+E	VOP_MKDIR(dvp,  /ntry, &va, &vp,,ct a, error);p+	sbreak;p+	 /hault:p+	serrorf= EINVAL;p+		break;p+	}p+p+Eif ( /hault_acl)o{p+	sif (!error)o{p+EE	error = _ACL_INHERIT(vp,,&va,  /hault_acl);p+	s	if (!error)o{p+EE		VMODIFY(vp);p+Es	} e_HWo{p+EE		s,* Ok,dentry	teardown(= {};p+Es		ints	err2;p+
+				/*(Oh,2OHeAhorror.
+				68 I++we can't add(tH uACL we mustnback2out.
+				68 ENOSPC can hiO Here, amSFgroOH rnnvings.
+				68/
+				teardown.d_inode =+ip = LINVFS_GET_IP(vp);
+				teardown.d_namtr=,dentry->d_namt;
+				remove_inode_hash(ip);
+			smake_bad_inode(ip);
+			sif (S_ISDIR(mode))p+	s	E	VOP_RMDIR(dvp, &teardown,,ct a, err2);
+			se_HWp+	s	E	VOP_REMOVE(dvp, &teardown,,ct a, err2);
+			sVN_RELE(vp);p+Es	}p+	s}p+	s_ACL_FREE( /hault_acl);p+	}p+p+Eif (!error)o{p+EEASSERT(vp);p+Esip = LINVFS_GET_IP(vp);
+p+	sif (S_ISCHR(mode) ||,S_ISBLK(mode))p+	s	ip->i_rdev =+to_kdev_t(rdev);p+Ese_HWoif (S_ISDIR(mode))p+	s	validate_fields(ip);
+		d_instantiate( /ntry, ip);
+		validate_fields(dir);p+	}
+Er dirt -error;p+}
+
+STATIC iny
+linvfs_creatt(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry,
+	ints	mode)
+{p+	r dirt linvfs_mknod(dir,  /ntry, mode, 0);p+}
+
+STATIC iny
+linvfs_mkdir(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry,
+	ints	mode)
+{p+	r dirt linvfs_mknod(dir,  /ntry, mode|S_IFDIR, 0);p+}
+
+STATIC s,* Ok,dentry -
+linvfs_lookup(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry)-+{p+	s,* Ok,inode	*ipr=,ct a;p+	vnode_t		*vp, *cvpr=,ct a;p+	ints	error;p+p+	if (dentry->d_namt.lenf>= MAXNAMELEN)p+	sr dirt ERR_PTR(-ENAMETOOLONG);
+p+	vpr=,LINVFS_GET_VP(dir);p+	VOP_LOOKUP(vp,  /ntry, &cvp, 0, ct a, ct a, error);p+	if (!error)o{p+EEASSERT(cvp);p+Esip = LINVFS_GET_IP(cvp);p+Esif (!ip)o{p+EE	VN_RELE(cvp);p+Essr dirt ERR_PTR(-EACCES);p+		}
+	}p+Eif (error && (error != ENOENT))p+	sr dirt ERR_PTR(-error);p+	d_add( /ntry, ip);	/*(Negative entry goes inoif ip donct a68/
+	r dirt ct a;p+}
+
+STATIC iny
+linvfs_link(
+	s,* Ok,dentry	*old_dentry,
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry)-+{p+	s,* Ok,inode	*ip;	/*(inode of guy beiig linked to(*/p+	vnode_t		*tdvp;	/*(target  irectoryrfor-new namt/link */p+	vnode_t		*vp;	/*(vprof namtrbeiig linked 8/
+	ints	error;p+p+	ip = old_dentry->d_inode;	/*(inode beiig linked to(*/p+	if (S_ISDIR(ip->i_m*de))p+	sr dirt -EPERM;p+p+	tdvpr=,LINVFS_GET_VP(dir);p+	vpr=,LINVFS_GET_VP(ip);p+p+	VOP_LINK(tdvp, vp,  /ntry, ct a, error);p+	if (!error)o{p+EEVMODIFY(tdvp);p+		VN_HOLD(vp);p+Esvalidate_fields(ip);
+		d_instantiate( /ntry, ip);
+	}
+Er dirt -error;p+}
+
+STATIC iny
+linvfs_unlink(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry)-+{p+	s,* Ok,inode	*inode;p+Evnode_t		*dvp;	/*( irectoryrcoinainiig namtrOo+r move 8/
+	ints	error;p+p+	inode =+dentry->d_inode;p+	dvpr=,LINVFS_GET_VP(dir);p+
+	VOP_REMOVE(dvp,  /ntry, ct a, error);p+	if (!error)o{p+EEvalidate_fields(dir);	/*(For snit only 8/
+		validate_fields(inode);p+E}p+p+Er dirt -error;p+}
+
+STATIC iny
+linvfs_symlink(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry,
+	coist char	*symnamt)-+{p+	s,* Ok,inode	*ip;p+	vattr_t		va;p+	vnode_t		*dvp;	/*( irectoryrcoinainiig namtrOo+r move 8/
+	vnode_t		*cvp;	/*(used Oo+lookup(symlink Oo+put in,dentry -/
+	ints	error;p+p+	dvpr=,LINVFS_GET_VP(dir);p+	cvpr=,ct a;p+
+smemset(&va, 0, snitof(va));p+	va.va_Oypef= VLNK;
+	va.va_moder=,irix_symlink_moder? 0777 & ~currSnt->fs->umask :,S_IRWXUGO;p+	va.va_mask =+XFS_AT_TYPE|XFS_AT_MODE;p+
+	error = 0;p+	VOP_SYMLINK(dvp,  /ntry, &va, (char68)symnamt, &cvp, ct a, error);p+	if (!error && cvp)o{p+EEASSERT(cvp->v_Oypef== VLNK);p+Esip = LINVFS_GET_IP(cvp);p+Esd_instantiate( /ntry, ip);
+		validate_fields(dir);p+	svalidate_fields(ip); 4- snit needs update -/
+	}
+Er dirt -error;p+}
+
+STATIC iny
+linvfs_rmdir(
+	s,* Ok,inode	*dir,
+	s,* Ok,dentry	*dentry)-+{p+	s,* Ok,inode	*inode =+dentry->d_inode;p+	vnode_t		*dvpr=,LINVFS_GET_VP(dir);p+	ints	error;p+p+	VOP_RMDIR(dvp,  /ntry, ct a, error);p+	if (!error)o{p+EEvalidate_fields(inode);p+E	validate_fields(dir);p+	}
+Er dirt -error;p+}
+
+STATIC iny
+linvfs_rSnamt(
+	s,* Ok,inode	*odir,
+	s,* Ok,dentry	*odentry,
+	s,* Ok,inode	*ndir,
+	s,* Ok,dentry	*ndentry)-+{p+	s,* Ok,inode	*new_inode =+ndentry->d_inode;p+	vnode_t		*fvp;	/*(fromr irectoryr*/p+	vnode_t		*tvp;	/*(target  irectoryr-/
+	ints	error;p+p+	fvpr=,LINVFS_GET_VP(odir);p+	tvpr=,LINVFS_GET_VP(ndir);p+
+	VOP_RENAME(fvp,,o /ntry, tvp,,n /ntry, ct a, error);p+	if (error)p+	sr dirt -error;p+p+	if (new_inode)p+E	validate_fields(new_inode);
+p+	validate_fields(odir);p+	if (ndir != odir)p+E	validate_fields(ndir);p+	r dirt 0;p+}
+
+STATIC iny
+linvfs_rSadlink(
+	s,* Ok,dentry	*dentry,
+	char		*buf,
+	ints	snit)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(dentry->d_inode);p+	uio_t		uio;p+Eiovec_t		iov;p+Eints	error;p+p+	iov.iov_base(= buf;p+	iov.iov_lenf= snit;p+p+	uio.uio_iov = &iov;p+Euio.uio_offset = 0;p+	uio.uio_segflg = UIO_USERSPACE;
+	uio.uio_residf= snit;p+	uio.uio_iovcnt = 1;
+
+	VOP_READLINK(vp,,&uio, 0, ct a, error);p+	if (error)p+	sr dirt -error;p+p+	r dirt (snit - uio.uio_resid);p+}
+
+4-
+68 careful Here - OHdon+unctISF can get ca2_ed recursively, so
+68 wt need to(be very careful about how muchAstack wt use.
+68+uio donkma2_HWed foSAOHisAr ason...
+ -/
+STATIC iny
+linvfs_fo2_Hw_link(
+	s,* Ok,dentry		*dentry,
+	s,* Ok,namtidata	*nd)
+{p+	vnode_t			*vp;p+	uio_t			*uio;p+Eiovec_t			iov;p+Eints		error;p+	char			*link;p+p+	ASSERT(dentry);p+	ASSERT(nd);
+p+	link =o(char68)kma2_HW(MAXNAMELEN+1,+GFP_KERNEL);p+Eif (!link)p+	sr dirt -ENOMEM;p+p+	uio =o(uio_t *)kma2_HW(snitof(uio_t),+GFP_KERNEL);p+Eif (!uio)o{p+	skd/ho(link);p+	sr dirt -ENOMEM;p+	}p+p+Evpr=,LINVFS_GET_VP(dentry->d_inode);p+p+	iov.iov_base(= link;p+	iov.iov_lenf= MAXNAMELEN;p+p+	uio->uio_iov = &iov;p+Euio->uio_offset = 0;p+	uio->uio_segflg = UIO_SYSSPACE;
+	uio->uio_residf= MAXNAMELEN;p+	uio->uio_iovcnt = 1;
+
+	VOP_READLINK(vp,,uio, 0, ct a, error);p+	if (error)o{p+	skd/ho(uio);p+	skd/ho(link);p+	sr dirt -error;p+	}-+
+	link[MAXNAMELEN - uio->uio_resid] = '\0';p+	kd/ho(uio);p+
+E/8 vfs_fo2_Hw_link r dirts (-) errors68/
+	error = vfs_fo2_Hw_link(nd, link);p+	kd/ho(link);p+	r dirt error;p+}
+
+STATIC iny
+linvfs_permissISF(
+	s,* Ok,inode	*inode,
+	ints	mode)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Eints	error;p+p+	moder<<= 6;		/*(coivert(fromrlinuxnto(vnode(access bits68/
+	VOP_ACCESS(vp,,mode, ct a, error);p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_rSvalidate(
+	s,* Ok,dentry	*dentry)-+{p+	vnode_t		*vpr=,LINVFS_GET_VP(dentry->d_inode);p+p+	if (unlikely(vp->v_fc lf&+VMODIFIED))p+	sr dirt vn_revalidate(vp);p+	r dirt 0;p+}
+
+STATIC iny
+linvfs_setattr(
+	s,* Ok,dentry	*dentry,
+	s,* Ok,iattr	*attr)-+{p+	s,* Ok,inode	*inode =+dentry->d_inode;p+	unsigted iit	ia_valid = attr->ia_valid;p+	vnode_t		*vpr=,LINVFS_GET_VP(inode);p+Evattr_t		vattr;p+Eints	+c ls = 0;p+	ints	error;p+p+	memset(&vattr, 0, snitof(vattr_t));p+Eif ((a_valid & ATTR_UID)o{p+EEvattr.va_mask |=+XFS_AT_UID;p+EEvattr.va_uid = attr->ia_uid;p+E}p+Eif ((a_valid & ATTR_GID)o{p+EEvattr.va_mask |=+XFS_AT_GID;p+EEvattr.va_gid = attr->ia_gid;p+E}p+Eif ((a_valid & ATTR_SIZE)o{p+EEvattr.va_mask |=+XFS_AT_SIZE;p+	svattr.va_snit = attr->ia_snit;p+	}p+Eif ((a_valid & ATTR_ATIME)o{p+EEvattr.va_mask |=+XFS_AT_ATIME;p+	Evattr.va_atIme.tv_sec = attr->ia_atIme;p+	Evattr.va_atIme.tv_nsec = 0;p+	}p+Eif ((a_valid & ATTR_MTIME)o{p+EEvattr.va_mask |=+XFS_AT_MTIME;p+	Evattr.va_mtIme.tv_sec = attr->ia_mtIme;p+	Evattr.va_mtIme.tv_nsec = 0;p+	}p+Eif ((a_valid & ATTR_CTIME)o{p+EEvattr.va_mask |=+XFS_AT_CTIME;p+	Evattr.va_ctIme.tv_sec = attr->ia_ctIme;p+	Evattr.va_ctIme.tv_nsec = 0;p+	}p+Eif ((a_valid & ATTR_MODE)o{p+EEvattr.va_mask |=+XFS_AT_MODE;p+	Evattr.va_mode =+attr->ia_mode;p+	sif (!in_group_p(inode->i_gid)r&& !capable(CAP_FSETID))p+	s	inode->i_mode &= ~S_ISGID;p+E}p+p+Eif ((a_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET))p+	sfc ls |=fATTR_UTIME;p+
+	VOP_SETATTR(vp,,&vattr, +c ls, ct a, error);p+	if (error)p+	sr dirt -error;p+svn_revalidate(vp);p+	r dirt error;p+}
+
+STATIC vic 
+linvfs_,* ncatt(
+	s,* Ok,inode	*inode)-+{p+	b12B,_,* ncatt_page(inode->i_mapping, (node->i_snit, linvfs_get_b12B,);p+}
+
+STATIC iny
+linvfs_setxattr(
+	s,* Ok,dentry	*dentry,
+	coist char	*namt,p+svic 		*data,
+	snit_ts	snit,
+	ints	+c ls)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(dentry->d_inode);p+	char		*attr =o(char68)namt;
+	attrnamts_,	*namtsp;p+	ints	x+c ls = 0;p+	ints	error;p+p+	namtsp =+attr_lookup_namtspace(attr, attr_namtspaces, ATTR_NAMECOUNT);p+Eif (!namtsp)p+	sr dirt -EOPNOTSUPP;
+	attr += namtsp->attr_namtlen;p+	error = namtsp->attr_capable(vp, ct a);p+	if (error)p+	sr dirt error;p+p+	/*(Coivert(Linuxnsysca2_nto(XFS internal ATTR +c ls */p+	if (.c ls & XATTR_CREATE)p+	sxfc ls |=fATTR_CREATE;p+	if (.c ls & XATTR_REPLACE)p+	sxfc ls |=fATTR_REPLACE;p+	xfc ls |=fnamtsp->attr_fc l;p+	r dirt namtsp->attr_set(vp,,attr, (vic (*)data, snit, x+c ls);p+}
+
+STATIC ssnit_t
+linvfs_getxattr(
+	s,* Ok,dentry	*dentry,
+	coist char	*namt,p+svic 		*data,
+	snit_ts	snit)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(dentry->d_inode);p+	char		*attr =o(char68)namt;
+	attrnamts_,	*namtsp;p+	ints	x+c ls = 0;p+	ssnit_ts	error;p+p+	namtsp =+attr_lookup_namtspace(attr, attr_namtspaces, ATTR_NAMECOUNT);p+Eif (!namtsp)p+	sr dirt -EOPNOTSUPP;
+	attr += namtsp->attr_namtlen;p+	error = namtsp->attr_capable(vp, ct a);p+	if (error)p+	sr dirt error;p+p+	/*(Coivert(Linuxnsysca2_nto(XFS internal ATTR +c ls */p+	if (!snit)o{p+	sxfc ls |=fATTR_KERNOVAL;p+		data =,ct a;p+	}p+	xfc ls |=fnamtsp->attr_fc l;p+	r dirt namtsp->attr_get(vp,,attr, (vic (*)data, snit, x+c ls);p+}
+
+STATIC ssnit_t
+linvfs_listxattr(
+	s,* Ok,dentry		*dentry,
+	char			*data,
+	snit_ts		snit)
+{p+	vnode_t			*vpr=,LINVFS_GET_VP(dentry->d_inode);p+	ints		error, x+c ls =fATTR_KERNAMELS;p+	ssnit_ts		r sult;p+p+Eif (!snit)
+	sxfc ls |=fATTR_KERNOVAL;p+	xfc ls |=fcapable(CAP_SYS_ADMIN) ?fATTR_KERNFt aS :fATTR_KERNORMALS;p+p+	error = attr_generic_list(vp,  ata, snit, x+c ls,,&r sult);p+	if (error < 0)
+s	r dirt error;p+sr dirt r sult;p+}
+
+STATIC iny
+linvfs_rSmovexattr(
+	s,* Ok,dentry	*dentry,
+	coist char	*namt)
+{p+	vnode_t		*vpr=,LINVFS_GET_VP(dentry->d_inode);p+	char		*attr =o(char68)namt;
+	attrnamts_,	*namtsp;p+	ints	x+c ls = 0;p+	ints	error;p+p+	namtsp =+attr_lookup_namtspace(attr, attr_namtspaces, ATTR_NAMECOUNT);p+Eif (!namtsp)p+	sr dirt -EOPNOTSUPP;
+	attr += namtsp->attr_namtlen;p+	error = namtsp->attr_capable(vp, ct a);p+	if (error)p+	sr dirt error;p+	xfc ls |=fnamtsp->attr_fc l;p+	r dirt namtsp->attr_rSmove(vp,,attr, x+c ls);p+}
+
+
+s,* Ok,inode_operatISFs(linvfs_file_inode_operatISFs(=o{p+	.permissISF		= linvfs_permissISF,
+	.,* ncatt		= linvfs_,* ncatt,
+	.revalidate		= linvfs_revalidate,
+	.setattr		= linvfs_setattr,
+	.setxattr		= linvfs_setxattr,
+	.getxattr		= linvfs_getxattr,
+	.listxattr		= linvfs_listxattr,
+	.removexattr		= linvfs_removexattr,
+};
+
+s,* Ok,inode_operatISFs(linvfs_dir_inode_operatISFs(=o{p+	.creatt			= linvfs_creatt,
+	.lookup			= linvfs_lookup,
+	.link			= linvfs_link,
+	.unlink			= linvfs_unlink,
+	.symlink		= linvfs_symlink,
+	.mkdir			= linvfs_mkdir,
+	.rmdir			= linvfs_rmdir,
+	.mknod			= linvfs_mknod,
+	.renamt			= linvfs_renamt,p+s.permissISF		= linvfs_permissISF,
+	.revalidate		= linvfs_revalidate,
+	.setattr		= linvfs_setattr,
+	.setxattr		= linvfs_setxattr,
+	.getxattr		= linvfs_getxattr,
+	.listxattr		= linvfs_listxattr,
+	.removexattr		= linvfs_removexattr,
+};
+
+s,* Ok,inode_operatISFs(linvfs_symlink_inode_operatISFs(=o{p+	.rSadlink		= linvfs_readlink,
+	.fo2_Hw_link		= linvfs_fo2_Hw_link,p+s.permissISF		= linvfs_permissISF,
+	.revalidate		= linvfs_revalidate,
+	.setattr		= linvfs_setattr,
+	.setxattr		= linvfs_setxattr,
+	.getxattr		= linvfs_getxattr,
+	.listxattr		= linvfs_listxattr,
+	.removexattr		= linvfs_removexattr,
+};
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_iops.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_iops.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_iops.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_iops.h	2004-07-30 16:24:28.000000000 +0000
@@ -0,0 +1,51 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifndef __XFS_IOPS_H__
+# /home __XFS_IOPS_H__
+
+extSrt s,* Ok,inode_operatISFs(linvfs_file_inode_operatISFs;
+extSrt s,* Ok,inode_operatISFs(linvfs_dir_inode_operatISFs;
+extSrt s,* Ok,inode_operatISFs(linvfs_symlink_inode_operatISFs;
+
+extSrt s,* Ok,file_operatISFs(linvfs_file_operatISFs;
+extSrt s,* Ok,file_operatISFs(linvfs_invis_file_operatISFs;
+extSrt s,* Ok,file_operatISFs(linvfs_dir_operatISFs;
+
+extSrt s,* Ok,address_space_operatISFs(linvfs_aops;
+
+extSrt int linvfs_get_b12B,(s,* Ok,inode *, long, s,* Ok,buffer_H ad *, int);
+extSrt vic (linvfs_unw   tet_done(s,* Ok,buffer_H ad *, int);
+
+extSrt int xfs_iHWtl(s,* Ok,bhv_desc *, s,* Ok,inode *, s,* Ok,file *,
+                        iin, unsigted iit, unsigted long);
+
+#end(+ 4- __XFS_IOPS_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_linux.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_linux.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_linux.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_linux.h	2004-07-30 16:29:56.000000000 +0000
@@ -0,0 +1,382 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifndef __XFS_LINUX__
+# /home __XFS_LINUX__
+
+#include <linux/Oypes.h>
+#include <linux/config.h>
+
+4-
+68 SomerOypes are cond(tISFal depSndiig oi2OHeAtarget system.
+68 XFS_BIG_BLKNOS needs b12B, layer disk,address s to(ben64 bits.
+68 XFS_BIG_INUMS needs OHeAVFS inode number to(ben64 bits, as well
+68( sAr quirdlg XFS_BIG_BLKNOS to(benset.
+ -/
+# /home XFS_BIG_BLKNOS	0
+# /home XFS_BIG_INUMS	0
+
+#include <xfs_,ypes.h>
+#include <xfs_arch.h>
+
+#include <kmem.h>
+#include <mr12B,.h>
+#include <spin.h>
+#include <sv.h>
+#include <mutex.h>
+#include <sema.h>
+#include <tIme.h>
+
+#include <support/qsort.h>
+#include <support/ktrace.h>
+#include <support/debug.h>
+#include <support/move.h>
+#include <support/uuid.h>
+
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/blkdev.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/.ile.h>
+#include <linux/swap.h>
+#include <linux/errno.h>
+#include <linux/12B,s.h>
+#include <linux/scht .h>
+#include <linux/bitops.h>
+#include <linux/major.h>
+#include <linux/pagemap.h>
+#include <linux/seq_.ile.h>
+#include <linux/init.h>
+#include <linux/prHW_fs.h>
+
+#include <asm/page.h>
+#include <asm/div64.h>
+#include <asm/param.h>
+#include <asm/uaccess.h>
+#include <asm/byteordIS.h>
+#include <asm/uFaligted.h>
+
+#include <xfs_beigaior.h>
+#include <xfs_vfs.h>
+#include <xfs_crt .h>
+#include <xfs_vnode.h>
+#include <xfs_stats.h>
+#include <xfs_sysWtl.h>
+#include <xfs_iops.h>
+#include <xfs_supIS.h>
+#include <xfs_globals.h>
+#include <xfs_fs_subS.h>
+#include <xfs_lrw.h>
+#include <xfs_buf.h>
+
+4-
+68 F aturermacros (disable/enable)
+ -/
+# /home HAVE_REFCACHE	/*(2.4nuses a+NFS reference cacht;(2.6+ doeon_ty -/
+#undef  HAVE_SENDFILE	/*(sSnd.ile(2)ndona(2.6+ system ca2_,n_ty in 2.4n-/
+
+#ifndef EVMS_MAJOR
+# /home EVMS_MAJOR 117
+#end(+
+
+4-
+68 State fc lffoSAunw   tetnextSnk,buffers.p+ -
+68 Wt need to(be ableuto(distdlguish(betweei2OHeseAand delayed
+68( 2_HWate buffers winvin XFS.  THeAgeneric IO path code doeo
+68(_ty need to(distdlguish(- wt use OHeABH_Delay fc lffoSAbonvp+f* dela2_HWAand OHeseAond(sk-uninitialised buffers.p+ -/
+# /home BH_Unw   tet		BH_PrivateStart
+# /home buffer_unw   tet(bh)	__buffer_state(bh, Unw   tet)
+s,atIc(inlome vic (set_buffer_unw   tet_io(s,* Ok,buffer_H ad *bh)-+{p+	bh->b_end_io =olinvfs_unw   tet_done;p+}
+BUFFER_FNS(Unw   tet,Aunw   tet)
+
+# /home xfs_refcacht_snit	xfs_params.refcacht_snit.val
+# /home xfs_refcacht_purge_c*/in xfs_params.refcacht_purge.val
+# /home restricted_chown	xfs_params.restrict_chown.val
+# /home irix_sgid_inHerit	xfs_params.sgid_inHerit.val
+# /home irix_symlink_mode	xfs_params.symlink_mode.val
+# /home xfs_panic_mask		xfs_params.panic_mask.val
+# /home xfs_error_level		xfs_params.error_level.val
+# /home xfs_syncd_cSnkisecs	xfs_params.syncd_tImer.val
+# /home xfs_stats_clear		xfs_params.stats_clear.val
+# /home xfs_inHerit_sync	xfs_params.inHerit_sync.val
+# /home xfs_inHerit_nodump	xfs_params.inHerit_nodump.val
+# /home xfs_inHerit_noatIme	xfs_params.inHerit_noatIm.val
+# /home xfs_buf_tImer_cSnkisecs	xfs_params.xfs_buf_tImer.val
+# /home xfs_buf_age_cSnkisecs	xfs_params.xfs_buf_age.val
+
+# /home currSnt_cpu()		smp_processor_id()
+# /home currSnt_pid()		(currSnt->pid)
+# /home currSnt_fsuid(crt )	(currSnt->fsuid)
+# /home currSnt_fsgid(crt )	(currSnt->fsgid)
+
+# /home NBPP		PAGE_SIZE
+# /home DPPSHFT		(PAGE_SHIFT(- 9)
+# /home NDPP		(1 << (PAGE_SHIFT(- 9))
+# /home dtop(DD)	(((DD) + NDPP(- 1) >> DPPSHFT)
+# /home dtopt(DD)	((DD) >> DPPSHFT)
+# /home dpoff(DD)	((DD) & (NDPP-1))
+
+# /home NBBY		8		/*(number o++bits6pIS byte -/
+# /home	NBPC		PAGE_SIZE	/*(Number o++by  s pIS click -/
+# /home	BPCSHIFT	PAGE_SHIFT	/*(LOG2(NBPC)A(++exact -/
+
+4-
+68 Snit of b12B, device i/o donparameternitd H re.
+68 CurrSntly(OH usystem supportonpage-snitd i/o.p+ -/
+# /home	BLKDEV_IOSHIFT		BPCSHIFT
+# /home	BLKDEV_IOSIZE		(1<<BLKDEV_IOSHIFT)
+4-(number o++BB's6pIS b12B, device b12B, -/
+# /home	BLKDEV_BB		BTOBB(BLKDEV_IOSIZE)
+
+4-+by  s to(clicks -/
+# /home	btoc(x)		(((__psunsigted_t)(x)+(NBPC-1))>>BPCSHIFT)
+# /home	btoct(x)	((__psunsigted_t)(x)>>BPCSHIFT)
+# /home	btoc64(x)	(((__uiny64_t)(x)+(NBPC-1))>>BPCSHIFT)
+# /home	btoct64(x)	((__uiny64_t)(x)>>BPCSHIFT)
+# /home	io_btoc(x)	(((__psunsigted_t)(x)+(IO_NBPC-1))>>IO_BPCSHIFT)
+# /home	io_btoct(x)	((__psunsigted_t)(x)>>IO_BPCSHIFT)
+
+4-+off_t+by  s to(clicks -/
+# /home+offtoc(x)       (((__uiny64_t)(x)+(NBPC-1))>>BPCSHIFT)
+# /home+offtoct(x)      ((xfs_off_t)(x)>>BPCSHIFT)
+
+4-+clicks to(off_t+by  s -/
+# /home	ctooff(x)	((xfs_off_t)(x)<<BPCSHIFT)
+
+4-+clicks to(by  s -/
+# /home	ctob(x)		((__psunsigted_t)(x)<<BPCSHIFT)
+# /home btoct(x)        ((__psunsigted_t)(x)>>BPCSHIFT)
+# /home	ctob64(x)	((__uiny64_t)(x)<<BPCSHIFT)
+# /home	io_ctob(x)	((__psunsigted_t)(x)<<IO_BPCSHIFT)
+
+4-+by  s to(clicks -/
+# /home+btoc(x)         (((__psunsigted_t)(x)+(NBPC-1))>>BPCSHIFT)
+
+#ifndef CELL_CAPABLE
+# /home+FSC_NOTIFY_NAME_CHANGED(vp)
+#end(+
+
+#ifndef ENOATTR
+# /home ENOATTR		ENODATA		/*(Attribute _ty fouid -/
+#end(+
+
+4- Note: EWRONGFS nevIS visibleuoutside OHeAkernel -/
+# /home	EWRONGFS	EINVAL		/*(Mouin winv2wrSFgr.ilesystem Oypef-/
+
+4-
+68 XXX EFSCORRUPTED needs aAr al+value in errno.h. asm-i386/errno.h won't
+68     r dirt codes,out o++its6known(range in errno.
+68 XXX Also+_tye: needs Oo(be < 1000 and fairly(uniqueAon(Linuxn(mustn't
+68     conflicn winv2anyrcode wt use already or anyrcode a drivIS maynuse)
+68 XXX SomeroptISFs((currSntly(we do #2):
+ -	1/ New errorrcode ["Filesystem doncorrupted", _after_ glibc updated]
+ -	2/ 990 ["Unknown(errorr990"]
+ -	3/ EUCLEAN ["S,* Okurerneeds cleaniig"]
+ -	4/(Coivert(EFSCORRUPTED Oo(EIO [justnpriorrOo+r dirt into+userspace]p+ -/
+# /home EFSCORRUPTED    990		/*(Filesystem doncorruptedn-/
+
+# /home SYNCHRONIZE()	barrier()
+# /home __r dirt_address __builtdl_r dirt_address(0)
+
+4-
+68 IRIX (BSD) quotactl makes use o++separa   commandsffoSAuser/group,
+68+wH reasAon(LinuxnOH usysca2_nencodes,OHdoninformatISF into+OH ucmd
+68(field (see OHeAQCMDrmacro in quota.h).  THesermacros helpAkeep OHe
+68 code portableu- OHey are _ty visibleufromrOHe sysca2_ninterface.
+ -/
+# /home Q_XSETGQLIM	XQM_CMD(0x8)	/*(sSt groups disk,limits68/
+# /home Q_XGETGQUOTA	XQM_CMD(0x9)	/*(gSt groups disk,limits68/
+
+4- IRIX uses a+dynamic snidlg algorithm (ndquot =o200 +(numprocs*2)68/
+/8 wt maynwell need to(home-tune OHdonif it eveS becomes aF issue.  8/
+# /home DQUOT_MAX_HEURISTIC	1024	/*(NR_DQUOTS 8/
+# /home ndquot			DQUOT_MAX_HEURISTIC
+
+4- IRIX uses OH ucurrSnt snit o++OHeAnamtrcacht to(guess a good+value 8/
+/8 - OHdonisn't OHe samtrbut is a good+enough startdlg point for-now. 8/
+# /home DQUOT_HASH_HEURISTIC	.iles_stat.nr_.iles
+
+4- IRIX inodes maiinain OHe project ID also, zero+OHdonfield on(Linuxn8/
+# /home DEFAULT_PROJID	0
+# /home dfltprid	DEFAULT_PROJID
+
+#ifndef pgoff_t		/*(2.6 compatn8/
+# /home pgoff_t		unsigted long
+#end(+
+
+# /home MAXPATHLEN	1024
+
+# /home MIN(a,b)	(min(a,b))
+# /home MAX(a,b)	(max(a,b))
+# /home howmany(x, y)	(((x)+((y)-1))/(y))
+# /home rouidup(x, y)	((((x)+((y)-1))/(y))*(y))
+
+4-
+68 JuggleuIRIX device numbers - still used in ond(sk s,* Okures
+ -/
+# /home XFS_DEV_BITSMAJOR	14
+# /home XFS_DEV_BITSMINOR	18
+# /home XFS_DEV_MAXMAJ		0x1ff
+# /home XFS_DEV_MAXMIN		0x3ffff
+# /home XFS_DEV_MAJOR(dev)	((int)(((unsigted)(dev)>>XFS_DEV_BITSMINOR) \p+	sss    & XFS_DEV_MAXMAJ))
+# /home XFS_DEV_MINOR(dev)	((int)((dev)&XFS_DEV_MAXMIN))
+# /home XFS_MKDEV(major,minor)o((xfs_dev_t)(((major)<<XFS_DEV_BITSMINOR) \p+	sss    | (minor&XFS_DEV_MAXMIN)))
+
+# /home XFS_DEV_TO_KDEVT(dev)	mk_kdev(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev))
+
+# /home xfs_stack_trace()	dump_stack()
+
+# /home xfs_i,* ncatt_ ata(ip,,off)	\p+	(-vm,* ncatt(LINVFS_GET_IP(XFS_ITOV(ip)), (off)))
+
+
+4- Move OHeAkernel do_div  /hom(tISF,off to(ome side -/
+
+#if  /homed __i386__
+/*(For ia32 wt need to(pu2_ somertricks to(gSt pastnvarious versISFo
+68(o++OHeAcompi_er+wHich do+_tyAloke us usdlg do_div in OHe middle
+68(o++largen+unctISFs.p+ -/
+s,atIc(inlome __u32 xfs_do_div(vic (*a, __u32 b, int n)-+{p+	__u32	mod;p+p+Eswinch (n)o{p+	scasef4:p+	s	mod =o*(__u32 *)a % b;p+			*(__u32 *)a =o*(__u32 *)a / b;p+			r dirt mod;p+	scasef8:p+	s	{p+	s	unsigted long __upper,+__low,+__high,+__mod;p+	s	__u64	c =o*(__u64 *)a;p+	s	__upper = __high = c >> 32;p+	s	__low = c;p+	s	if (__high)o{p+EE		__upper = __high % (b);
+			s__high = __high / (b);
+			}p+	s	asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));p+	s	asm("":"=A" (c):"a" (__low),"d" (__high));p+			*(__u64 *)a = c;p+	s	r dirt __mod;p+	s	}
+	}p+p+	/*(NOTREACHED68/
+	r dirt 0;p+}
+
+/8 Snde effect +/ho(64 bit mod operatISF -/
+s,atIc(inlome __u32 xfs_do_mod(vic (*a, __u32 b, int n)-+{p+	swinch (n)o{p+	scasef4:p+	s	r dirt *(__u32 *)a % b;p+		casef8:p+	s	{p+	s	unsigted long __upper,+__low,+__high,+__mod;p+	s	__u64	c =o*(__u64 *)a;p+	s	__upper = __high = c >> 32;p+	s	__low = c;p+	s	if (__high)o{p+EE		__upper = __high % (b);
+			s__high = __high / (b);
+			}p+	s	asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));p+	s	asm("":"=A" (c):"a" (__low),"d" (__high));p+			r dirt __mod;p+	s	}
+	}p+p+	/*(NOTREACHED68/
+	r dirt 0;p+}
+#e_HWp+s,atIc(inlome __u32 xfs_do_div(vic (*a, __u32 b, int n)-+{p+	__u32	mod;p+p+Eswinch (n)o{p+	scasef4:p+	s	mod =o*(__u32 *)a % b;p+			*(__u32 *)a =o*(__u32 *)a / b;p+			r dirt mod;p+	scasef8:p+	s	mod =odo_div(*(__u64 *)a, b);p+			r dirt mod;p+	}p+p+	/*(NOTREACHED68/
+	r dirt 0;p+}
+
+/8 Snde effect +/ho(64 bit mod operatISF -/
+s,atIc(inlome __u32 xfs_do_mod(vic (*a, __u32 b, int n)-+{p+	swinch (n)o{p+	scasef4:p+	s	r dirt *(__u32 *)a % b;p+		casef8:p+	s	{p+	s	__u64	c =o*(__u64 *)a;p+	s	r dirt do_div(c, b);p+			}
+	}p+p+	/*(NOTREACHED68/
+	r dirt 0;p+}
+#end(+
+
+#undef do_div
+# /home do_div(a, b)	xfs_do_div(&(a), (b), snitof(a))
+# /home do_mod(a, b)	xfs_do_mod(&(a), (b), snitof(a))
+
+s,atIc(inlome __uiny64_t rouidup_64(__uiny64_t x, __uiny32_t y)-+{p+	x += y(- 1;p+	do_div(x, y);p+	r dirt(xn8 y);p+}
+
+#end(+ 4- __XFS_LINUX__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_lrw.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_lrw.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_lrw.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_lrw.c	2004-07-30 16:25:10.000000000 +0000
@@ -0,0 +1,979 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+4-
+68  fs/xfs/linux/xfs_lrw.c (LinuxnR ad W     stuff)
+ -
+68/
+
+#include "xfs.h"
+
+#include "xfs_fs.h"
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_,*ans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_a2_HW.h"
+#include "xfs_dmapi.h"
+#include "xfs_quota.h"
+#include "xfs_m*/in.h"
+#include "xfs_a2_HW_btree.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_ia2_HW_btree.h"
+#include "xfs_btree.h"
+#include "xfs_ia2_HW.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_bmap.h"
+#include "xfs_bin.h"
+#include "xfs_rta2_HW.h"
+#include "xfs_error.h"
+#include "xfs_itable.h"
+#include "xfs_rw.h"
+#include "xfs_refcacht.h"
+#include "xfs_acl.h"
+#include "xfs_cap.h"
+#include "xfs_maW.h"
+#include "xfs_attr.h"
+#include "xfs_inode_item.h"
+#include "xfs_buf_item.h"
+#include "xfs_utils.h"
+#include "xfs_iomap.h"
+
+#include <linux/capability.h>
+
+
+#if  /homed(XFS_RW_TRACE)p+vic 
+xfs_rw_enter_trace(p+	ints	tag,
+	xfs_iocore_t	*io,
+	coist char	*buf,
+	snit_ts	snit,
+	loff_t		offset,
+	ints	io+c ls)
+{p+	xfs_inode_t	*ipr=,XFS_IO_INODE(io);p+
+Eif ((p->i_rwtracef== ct a)p+	sr dirt;p+	ktrace_enter((p->i_rwtrace,
+		(vic (*)(unsigted long)tag,
+		(vic (*)ip,
+		(vic (*)((unsigted long)(((p->i_d.di_snit >> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)((p->i_d.di_snit & 0xffffffff)),
+		(vic (*)(__psint_t)buf,
+		(vic (*)((unsigted long)snit),
+		(vic (*)((unsigted long)((offset >> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)(offset & 0xffffffff)),
+		(vic (*)((unsigted long)io+c ls),
+		(vic (*)((unsigted long)(((o->io_new_snit >> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)((o->io_new_snit & 0xffffffff)),
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a);p+}
+
+vic 
+xfs_inval_cachtd_trace(p+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	xfs_off_t	len,
+	xfs_off_t	first,
+	xfs_off_t	last)
+{p+	xfs_inode_t	*ipr=,XFS_IO_INODE(io);p+
+Eif ((p->i_rwtracef== ct a)p+	sr dirt;p+	ktrace_enter((p->i_rwtrace,
+		(vic (*)(__psint_t)XFS_INVAL_CACHED,
+		(vic (*)ip,
+		(vic (*)((unsigted long)((offset >> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)(offset & 0xffffffff)),
+		(vic (*)((unsigted long)((lenf>> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)(lenf& 0xffffffff)),
+		(vic (*)((unsigted long)((firstf>> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)(firstf& 0xffffffff)),
+		(vic (*)((unsigted long)((lastf>> 32) & 0xffffffff)),
+		(vic (*)((unsigted long)(lastf& 0xffffffff)),
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a,
+		(vic (*)ct a);p+}
+#end(+
+
+4-
+68	xfs_iozero
+ -
+68	xfs_iozero clears OH uspecifiBd range of buffer suppliBd,
+68	and marks a2_ tH uaffectt }b12B,s as+valid and modifiBd.  If
+68	anuaffectt }b12B, don_ty( 2_HWated,(itiwill be a2_HWated.  If
+68	anuaffectt }b12B, don_ty(completely overw   tet,Aand don_ty
+68	valid befor  OH uoperatISF,(itiwill be read(fromr isk befor 
+68	beiig partdally zeroed.
+ -/
+STATIC iny
+xfs_iozero(
+	s,* Ok,inode		*ip,	/*(inode			*/
+	loff_t			pos,	/*(offset in .ile		*/
+	snit_ts		c*/in,	/*(snit o++data to(zero		*/
+	loff_t			end_snit)	/*(max,file snit to+setn8/
+{p+	unsigted		by  s;
+	s,* Ok,page		*page;
+	s,* Ok,address_space	*mapping;p+	char			*kaddr;p+	ints		s,atus;
+
+	mapping =+ip->i_mapping;p+	doo{p+	sunsigted long index,(offset;
+
+		offset = (pos & (PAGE_CACHE_SIZE -1)); 4- Winvin page 8/
+		index = pos >> PAGE_CACHE_SHIFT;p+		by  s = PAGE_CACHE_SIZE -(offset;
+s	if (by  s > c*/in)p+	s	by  s = c*/in;
+
+		s,atus = -ENOMEM;p+	spage = grab_cacht_page(mapping, (ndex);p+Esif (!page)p+	s	break;p+p+	skaddr = kmap(page);
+		s,atus = mapping->a_ops->prepare_w    (ct a, page,(offset,
+			s			offset ++by  s);p+Esif (s,atus)o{p+EE	goto+un12B,;p+Es}p+p+		memset((vic (*) (kaddr +(offset), 0, by  s);p+Esflush_dcacht_page(page);
+		s,atus = mapping->a_ops->commit_w    (ct a, page,(offset,
+			s			offset ++by  s);p+Esif (!s,atus)o{p+EE	pos += by  s;
+			c*/in -= by  s;
+			if (pos > i_snit_read(ip))
+			si_snit_w    (ip,,pos < end_snit ?,pos : end_snit);p+Es}p+p+un12B,:p+	skunmap(page);
+		un12B,_page(page);
+		page_cacht_release(page);
+		if (s,atus)p+	s	break;p+	}+wHile (c*/in);p+p+	r dirt (-s,atus);p+}
+
+4-
+68 xfs_inval_cachtd_pages
+68 
+68 THdonroutinendonrespoisibleuforAkeepdlg direct I/OAand buffered I/O
+68 somewHat c*H rent.  FromrHere wt make surf tHat(we'rf at(least
+68 temporarily holdiig OHe inode I/OA12B, exclusivelyAand OHen ca2_
+68 tHe page cacht to(flushAand dnvalidate anyrcachtd pages.  If tHer 
+68 are _trcachtd pagesAOHisAroutinenwill be very quick.
+ -/
+vic 
+xfs_inval_cachtd_pages(
+	vnode_t		*vp,p+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	ints	w    ,
+	ints	rel2B,)
+{p+	xfs_m*/in_t	*mp;p+
+Eif (!VN_CACHED(vp))o{p+EEr dirt;p+	}p+p+	mpr=,(o->io_m*/in;
+
+	4-
+	68 Wt need to(gSt tHe I/OA12B, exclusivelyAin ordIS
+	68 to+safelyAinvalidate pagesAand mappings.
+	 */p+	if (rel2B,)o{p+EEXFS_IUNLOCK(mp,,io, XFS_IOLOCK_SHARED);
+		XFS_ILOCK(mp,,io, XFS_IOLOCK_EXCL);p+E}p+p+E4- W   iig beyond EOF creatts a holf tHat(must be zeroed */p+	if (w     && (offset > XFS_SIZE(mp,,io)))o{p+	sxfs_fsnit_tsisnit;p+p+		XFS_ILOCK(mp,,io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+		isnit = XFS_SIZE(mp,,io);
+		if (offset > isnit)o{p+	ssxfs_zero_tof(vp,,io, offset, isnit, offset);p+		}
+	EXFS_IUNLOCK(mp,,io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	}p+p+Exfs_inval_cachtd_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
+	VOP_FLUSHINVAL_PAGES(vp,,ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
+	if (rel2B,)o{p+EEXFS_ILOCK_DEMOTE(mp,,io, XFS_IOLOCK_EXCL);p+E}p+}p+p+ssnit_ts		4-+by  s read, or (-) (errorr*/p+xfs_read(
+	bhv_desc_t      *bdp,
+	s,* Ok,.ile	*.ile,
+	char		*buf,
+	snit_ts	snit,
+	loff_t		*offset,
+	ints	io+c ls,
+	crtd_t          *crtdp)-+{p+	ssnit_ts	ret;
+sxfs_fsnit_tsn;
+	xfs_inode_t	*ip;
+	xfs_m*/in_t	*mp;p+
+Eipr=,XFS_BHVTOI(bdp);p+Empr=,(p->i_m*/in;
+
+	XFS_STATS_INC(xs_read_ca2_s);p+p+	if (unlikely(io+c ls & IO_ISDIRECT))o{p+	sif (((__psint_t)buf & BBMASK) ||p+	s    (*offset & mp->m_b12B,mask) ||p+	s    (snit & mp->m_b12B,mask))o{p+	ssif (*offset >=,(p->i_d.di_snit)o{p+EE		r dirt (0);
+			}p+	s	r dirt -XFS_ERROR(EINVAL);p+		}
+	}p+p+Enr=,XFS_MAXIOFFSET(mp) -(*offset;
+sif ((n <= 0) || (snit == 0))p+	sr dirt 0;p+p+	if (n < snit)
+	ssnit = n;p+p+	if (XFS_FORCED_SHUTDOWN(mp))o{p+EEr dirt -EIO;
+	}p+p+Eif (!(io+c ls & IO_ISLOCKED))p+	sxfs_i12B,(ip,,XFS_IOLOCK_SHARED);
+p+Eif (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp,,ip,,DM_EVENT_READ)r&&
+	    !(io+c ls & IO_INVIS))o{p+	siin error;p+		vrw12B,_,A12B,Oypef= VRWLOCK_READ;p+	siin dm+c ls = FILP_DELAY_FLAG(.ile) |,DM_SEM_FLAG_RD(io+c ls);
+p+E	error = XFS_SEND_DATA(mp,,DM_EVENT_READ, BHV_TO_VNODE(bdp),(*offset, snit,p+EE		      dm+c ls, &12B,Oype);
+		if (error)o{p+	sEif (!(io+c ls & IO_ISLOCKED))p+	s	sxfs_iun12B,(ip,,XFS_IOLOCK_SHARED);
+		sr dirt -error;p+s	}
+	}p+p+Eif (unlikely(io+c ls & IO_ISDIRECT))o{p+	sxfs_rw_enter_trace(XFS_DIORD_ENTER, &(p->i_iocore,
+			s	buf, snit, *offset, io+c ls);
+	sr d =odo_generic_direct_read(.ile, buf, snit, offset);p+		UPDATE_ATIME(.ile->f_dentry->d_inode);p+	} e_HWo{p+	sxfs_rw_enter_trace(XFS_READ_ENTER, &(p->i_iocore,
+			s	buf, snit, *offset, io+c ls);
+	sr d =ogeneric_file_read(.ile, buf, snit, offset);p+	}p+p+Eif (!(io+c ls & IO_ISLOCKED))p+	sxfs_iun12B,(ip,,XFS_IOLOCK_SHARED);
+
+	XFS_STATS_ADD(xs_read_by  s,+r d);p+p+	if (unlikely(io+c ls & IO_INVIS))o{p+	s/*(gSneric_file_read updates OH uatImerbut wt need top+	s 8+undo tHat(because OHisAI/OAwas supposed to(be invisible.p+	s 8/
+		s,* Ok,inode *inode =+LINVFS_GET_IP(BHV_TO_VNODE(bdp));
+		inode->i_atImer=,(p->i_d.di_atIme.t_sec;p+	} e_HWo{p+	sxfs_ichgtIme(ip,,XFS_ICHGTIME_ACC);p+	}p+p+Er dirt r t;p+}
+
+/*
+68 THdonroutinendonca2_ed to(handle zerodlg anyrspace in2OHeAlast
+68 b12B, o++OHeAfile tHat(is beyond OHeAEOF.  We do OHdonsince OHe
+68 snit is beiig increased winvout w   iig anynving Oo+OHat(b12B,
+68( nd(we don't want anyome Oo+r ad OHeAgarbage oi2OHeA isk.
+ -/
+STATIC iny	s		4-+error (pos  ive)r*/p+xfs_zero_last_b12B,(
+	s,* Ok,inode	*ip,p+	xfs_iocore_t	*io,
+	xfs_off_t	offset,
+	xfs_fsnit_tsisnit,
+	xfs_fsnit_tsend_snit)
+{p+	xfs_fileoff_t	last_fsb;
+	xfs_m*/in_t	*mp;p+	ints	nimaps;p+	ints	zero_offset;
+sints	zero_len;p+	ints	isnit_fsb_offset;
+sints	error = 0;
+	xfs_bmbt_irec_tsimap;
+	loff_t		loff;
+	snit_ts	lsnit;p+p+	ASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE) != 0);p+	ASSERT(offset > isnit);p+p+	mpr=,(o->io_m*/in;
+
+	isnit_fsb_offsetr=,XFS_B_FSB_OFFSET(mp, isnit);p+Eif ((snit_fsb_offsetr== 0) {p+	s/*p+	s 8+THere are _trextra+by  s in2OHeAlast b12B, onr isk top+	s 8+zero, so+r dirt.p+	s 8/
+		r dirt 0;p+	}-+
+	last_fsbr=,XFS_B_TO_FSBT(mp, isnit);p+Enimaps = 1;
+	error = XFS_BMAPI(mp, ct a, io, last_fsb, 1, 0, ct a, 0, &(map,
+			  &nimaps, ct a);p+	if (error)o{p+EEr dirt error;p+	}-+	ASSERT(nimaps > 0);p+	4-
+	68 If tHe b12B, undISlyiig isnit is justna holf, OHen tHer 
+	68 don_tyving Oo+zero.
+	 */p+	if (imap.br_startb12B, == HOLESTARTBLOCK)o{p+EEr dirt 0;p+	}p+E4-
+	68 Zero+OHe part o++OHeAlast b12B, beyond OHeAEOF,Aand w     it
+	68 out sync.  Wt need to(drop OHe i12B, wHile we do OHdonso we
+	68 don't deadl2B, wHei2OHeAbuffer cacht ca2_s back to+us.
+	 */p+	XFS_IUNLOCK(mp,,io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
+	loff = XFS_FSB_TO_B(mp,,last_fsb);
+	lsnit = XFS_FSB_TO_B(mp,,1);p+p+	zero_offsetr=,(snit_fsb_offset;
+szero_len = mp->m_sb.sb_b12B,snit - (snit_fsb_offset;
+
+	error = xfs_iozero(ip,,loff + zero_offset, zero_len, end_snit);p+p+	XFS_ILOCK(mp,,io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	ASSERT(error >= 0);p+	r dirt error;p+}
+
+/*
+68 Zero+anyronr isk space betweei2OHeucurrSnt EOF and OHe new,
+68+largerAEOF.  THdonhandles OH unormal casefo++zerodlg OHeAremaiidIS
+68(o++OHeAlast b12B, in2OHeAfile and OHe unusual casefo++zerodlg b12B,s
+68(out beyond OHeAsnit o++OHeA.ile.  THdonsecond casefonly happeFo
+68(winv2fixed snit extSnksAand wHei2OHeAsystem crashes befor  OH uinode
+68 snit was updatedrbut after}b12B,s were a2_HWated.  IfA.ill donset,
+68 tHen+anyrholfs in2OHeArange aren.il_ed and zeroed.  IfA_ty, OHeAholes
+68 arenleftAaloneAasAholes.
+68/
+
+iny	s			4-+error (pos  ive)r*/p+xfs_zero_tof(
+	vnode_t		*vp,p+	xfs_iocore_t	*io,
+	xfs_off_t	offset,		4-+startdlg I/OAoffsetr*/p+	xfs_fsnit_tsisnit,		/*(currSnt inode snit */p+	xfs_fsnit_tsend_snit)	/*(cermiFal inode snit */p+{
+	s,* Ok,inode	*ip =+LINVFS_GET_IP(vp);p+	xfs_fileoff_t	start_zero_fsb;
+	xfs_fileoff_t	end_zero_fsb;
+	xfs_fileoff_t	prev_zero_fsb;
+	xfs_fileoff_t	zero_c*/in_fsb;
+	xfs_fileoff_t	last_fsb;
+	xfs_extlen_t	buf_len_fsb;
+	xfs_extlen_t	prev_zero_c*/in;
+	xfs_m*/in_t	*mp;p+	ints	nimaps;p+	ints	error = 0;
+	xfs_bmbt_irec_tsimap;
+	loff_t		loff;
+	snit_ts	lsnit;p+p+	ASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE));
+	ASSERT(ismr12B,ed((o->io_io12B,, MR_UPDATE));
+p+	mpr=,(o->io_m*/in;
+
+	4-
+	68 Firstfhandle zerodlg tHe b12B, onrwHich isnit resides.
+	 * Wt only zero a part o++OHat(b12B,nso itiisfhandleduspecially.
+	 */p+	error = xfs_zero_last_b12B,(ip,,io, offset, isnit, end_snit);p+Eif (error)o{p+EEASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE));
+		ASSERT(ismr12B,ed((o->io_io12B,, MR_UPDATE));
+EEr dirt error;p+	}-+
+	4-
+	68 Calcula   OH urange betweei2OHeunew snit and OHe old
+	68 wH re}b12B,s needing Oo+be zeroed maynexist.  To(gSt tHe
+	68 bl2B, wHer  OH ulast byte in2OHeAfile currSntly(resides,
+	68 wt need to(subtract(ome fromrOHe snit and O* ncatt back
+	68 to+a b12B, bouidary.  Wt subtract(1 in2casefOHe snit is
+	68 exactlyronra b12B, bouidary.
+	 */p+	last_fsbr=,isnit ?,XFS_B_TO_FSBT(mp, isnit(- 1) : (xfs_fileoff_t)-1;
+	start_zero_fsbr=,XFS_B_TO_FSB(mp, (xfs_ufsnit_t)isnit);p+Eend_zero_fsbr=,XFS_B_TO_FSBT(mp, offsetr-,1);p+	ASSERT((xfs_sfiloff_t)last_fsbr< (xfs_sfiloff_t)start_zero_fsb);p+Eif (last_fsbr== end_zero_fsb) {p+	s/*p+	s 8+THe snit was only incremSnted on(its6last b12B,.p+	s 8 Wt took2care o++OHat(above, so+justnr dirt.p+	s 8/
+		r dirt 0;p+	}-+
+	ASSERT(start_zero_fsbr<= end_zero_fsb);p+	prev_zero_fsb =,ct aFILEOFF;p+	prev_zero_c*/in = 0;
+	wHile (start_zero_fsbr<= end_zero_fsb) {p+	snimaps = 1;
+		zero_c*/in_fsb = end_zero_fsb - start_zero_fsbr+ 1;
+		error = XFS_BMAPI(mp, ct a, io, start_zero_fsb, zero_c*/in_fsb,p+EE		  0, ct a, 0, &(map, &nimaps, ct a);p+		if (error)o{p+	sEASSERT(ismr12B,ed((o->io_12B,, MR_UPDATE));
+			ASSERT(ismr12B,ed((o->io_io12B,, MR_UPDATE));
+EEEr dirt error;p+		}p+	sASSERT(nimaps > 0);p+p+		if (imap.br_statt == XFS_EXT_UNWRITTEN ||p+	s    imap.br_startb12B, == HOLESTARTBLOCK)o{p+EEs/*p+	s	68 THdonloop handles initializiig pagesAOHat(wer 
+	s	68 partdally initializt }by(OH ucode below OHdo
+	s	68 loop. It basically zeroes+OHe part o++OHeApage
+	s	68 OHat(sits6onra holf and sets+OHeApageAasAP_HOLE
+	s	68 and ca2_s remapfnif it is a mappt }.ile.
+	s	68/
+			prev_zero_fsb =,ct aFILEOFF;p+			prev_zero_c*/in = 0;
+			start_zero_fsbr=,imap.br_startoff +p+EE			,imap.br_b12B,c*/in;
+			ASSERT(start_zero_fsbr<= (end_zero_fsb + 1));
+EEEcontdlue;p+		}p+p+	s/*p+	s 8+THere are b12B,s in2OHeArange r quested.
+		68 Zero+OHem a sdlgle w     at(a tIme.  Wt actually
+		68 don't zero+OHe SnkireArange r dirted if(itiis
+s	68 Ooo+big and simplynloop arouid to(gSt tHe rest.p+	s 8+THat(is _ty(OHe mostnefficiSnt yving Oo+do,rbut itp+	s 8+donsimple and OHdonpanv2deGuld _ty(bt exercised oftet.p+	s 8/
+		buf_len_fsb = XFS_FILBLKS_MIN(imap.br_b12B,c*/in,
+			s	      mp->m_w    io_b12B,s << 8);
+EE/*p+	s 8+Drop OHe inode 12B, wHile we'rf dodlg tHe I/O.p+	s 8 Wt'2_ still igaf OHe io12B, to(protect us.
+	s 8/
+		XFS_IUNLOCK(mp,,io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+
+		loff = XFS_FSB_TO_B(mp,,start_zero_fsb);p+E	lsnit = XFS_FSB_TO_B(mp,,buf_len_fsb);
+p+E	error = xfs_iozero(ip,,loff,,lsnit, end_snit);p+p+		if (error)o{p+	sEgoto+out_12B,;p+Es}p+p+		prev_zero_fsb =,start_zero_fsb;
+		prev_zero_c*/in = buf_len_fsb;
+		start_zero_fsbr=,imap.br_startoff + buf_len_fsb;
+		ASSERT(start_zero_fsbr<= (end_zero_fsb + 1));
+
+		XFS_ILOCK(mp,,io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	}p+p+Er dirt 0;p+p+out_12B,:p+p+	XFS_ILOCK(mp,,io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
+	ASSERT(error >= 0);p+	r dirt error;p+}
+
+ssnit_ts			4-+by  s w   tet,Aor (-) errorr*/p+xfs_w    (
+	bhv_desc_t      *bdp,
+	s,* Ok,.ile	*.ile,
+	coist char	*buf,
+	snit_ts	snit,
+	loff_t		*offset,
+	ints	io+c ls,
+	crtd_t          *crtdp)-+{p+	xfs_inode_t	*xip;
+	xfs_m*/in_t	*mp;p+	ssnit_ts	ret;
+sints	error = 0;
+	xfs_fsnit_t     isnit, new_snit;
+	xfs_fsnit_t	t,Alimit;
+	xfs_iocore_t    *io;
+	vnode_t		*vp;p+	ints	io12B,;p+Eints	evSnksein = 0;
+	vrw12B,_,	12B,Oype;
+
+	XFS_STATS_INC(xs_w    _ca2_s);p+p+	vpr=,BHV_TO_VNODE(bdp);
+	xipr=,XFS_BHVTOI(bdp);p+p+Eif (snit == 0)
+		r dirt 0;p+p+Eio =o&x(p->i_iocore;p+	mpr=,(o->io_m*/in;
+
+	xfs_cheB,_frozen(mp,,bdp,,XFS_FREEZE_WRITE);p+p+Eif (XFS_FORCED_SHUTDOWN(x(p->i_m*/in))o{p+EEr dirt -EIO;
+	}p+p+Eif (unlikely(io+c ls & IO_ISDIRECT))o{p+	sif (((__psint_t)buf & BBMASK) ||p+	s    (*offset & mp->m_b12B,mask) ||p+	s    (snit  & mp->m_b12B,mask))o{p+	ssr dirt XFS_ERROR(-EINVAL);p+		}
+		io12B,r=,XFS_IOLOCK_SHARED;p+E	l2B,Oypef= VRWLOCK_WRITE_DIRECT;p+	} e_HWo{p+	sif (io->io_+c ls & XFS_IOCORE_RT)p+	ssr dirt XFS_ERROR(-EINVAL);p+		io12B,r=,XFS_IOLOCK_EXCL;p+E	l2B,Oypef= VRWLOCK_WRITE;
+	}p+p+Eif (io+c ls & IO_ISLOCKED)p+		io12B,r=,0;
+
+	xfs_i12B,(xip,,XFS_ILOCK_EXCL|io12B,);p+p+Eisnit = x(p->i_d.di_snit;
+	limitr=,XFS_MAXIOFFSET(mp);p+p+Eif (.ile->f_+c ls & O_APPEND)p+		*offsetr=,(snit;
+
+s,art:p+	n =olimitr-(*offset;
+sif (n <= 0) {p+	sxfs_iun12B,(xip,,XFS_ILOCK_EXCL|io12B,);p+EEr dirt -EFBIG;p+	}p+Eif (n < snit)
+	ssnit = n;p+p+	new_snit =(*offset + snit;
+	if (new_snit > isnit)o{p+	s(o->io_new_snit = new_snit;
+	}p+p+Eif ((DM_EVENT_ENABLED(vp->v_vfsp,,xip,,DM_EVENT_WRITE)r&&
+	    !(io+c ls & IO_INVIS) && !evSnksein))o{p+	sloff_t		sgafdsnit =(*offset;p+		iin dm+c ls = FILP_DELAY_FLAG(.ile) |,DM_SEM_FLAG_RD(io+c ls);
+p+E	xfs_iun12B,(xip,,XFS_ILOCK_EXCL);
+		error = XFS_SEND_DATA(x(p->i_m*/in,,DM_EVENT_WRITE, vp,p+EE		      *offset, snit,p+EE		      dm+c ls, &12B,Oype);
+		if (error)o{p+	sEif (io12B,) xfs_iun12B,(xip,,io12B,);p+EEsr dirt -error;p+s	}
+		xfs_i12B,(xip,,XFS_ILOCK_EXCL);
+		evSnksein = 1;p+p+	s/*p+	s 8+THe io12B, was dropped and reaquired in2XFS_SEND_DATAp+	s 8+so we igaf Oo+r cheB,fOHe snit wHei2appeFding.p+	s 8 Wt will only "goto+s,art;" once, since igailg sSnt yvep+	s 8 evSnk prevSnksAanoOH rnca2_nto+XFS_SEND_DATA,rwHich isp+	s 8 wHat a2_HwsfOHe snit to(change in OHeAfirstfplace.
+	s 8/
+		if ((.ile->f_+c ls & O_APPEND)r&&
+		    sgafdsnit != x(p->i_d.di_snit)o{p+	sE*offsetr=,(snit = x(p->i_d.di_snit;
+	sEgoto+s,art;p+s	}
+	}-+
+	4-
+	68 If tHe offset is beyond OHeAsnit o++OHeA.ile, we igaf a(couple
+	68 o++OHdngs Oo+do. First,+(+ tHer  is already space a2_HWated
+	68 wt need to(eiOH rncreattrholfs or zero+OHe  isk or ...
+	 *
+	68 If tHer  is aApageAwHer  OH uprevious snit lands, wt need
+	68 to+zero+itrout up to+OH unew snit.
+	 */p+
+Eif (!(io+c ls & IO_ISDIRECT) && (*offset >,(snit && isnit))o{p+	serror = xfs_zero_tof(BHV_TO_VNODE(bdp),(io, *offset,
+	s	isnit,(*offset + snit);
+		if (error)o{p+	sExfs_iun12B,(xip,,XFS_ILOCK_EXCL|io12B,);p+EE	r dirt(-error);p+		}
+	}p+	xfs_iun12B,(xip,,XFS_ILOCK_EXCL);
+
+	4-
+	68 If we'rf w   iig OHeAfile tHei2make surf to clear tHe
+	68 setuid and setgid bits6if OHe process(is _ty(beiig run
+	68 by root.  THdonkeeps6pIopleufromrmodifyilg sStuid and
+	68 setgid binaries.
+	 */p+
+Eif (((x(p->i_d.di_mode & S_ISUID) ||p+	    ((x(p->i_d.di_mode & (S_ISGID |,S_IXGRP))o==p+		(S_ISGID |,S_IXGRP)))r&&
+	     !capable(CAP_FSETID))o{p+	serror = xfs_w    _clear_sStuid(x(p);
+		if (error)o{p+	sExfs_iun12B,(xip,,io12B,);p+EEsr dirt -error;p+s	}
+	}
+
+
+Eif ((ssnit_t) snit < 0) {p+	sr d =o-EINVAL;p+s	goto+error;p+	}-+
+	if (!access_ok(VERIFY_READ, buf, snit)) {p+	sr d =o-EINVAL;p+s	goto+error;p+	}-+
+r dry:p+Eif (unlikely(io+c ls & IO_ISDIRECT))o{p+	sxfs_inval_cachtd_pages(vp,,io, *offset, 1,,1);p+	sxfs_rw_enter_trace(XFS_DIOWR_ENTER,p+EE			io, buf, snit, *offset, io+c ls);
+	sr d =odo_generic_direct_w    (.ile, buf, snit, offset);p+	} e_HWo{p+	sxfs_rw_enter_trace(XFS_WRITE_ENTER,p+EE			io, buf, snit, *offset, io+c ls);
+	sr d =odo_generic_file_w    (.ile, buf, snit, offset);p+	}p+p+	if (unlikely(io+c ls & IO_INVIS))o{p+	s/*(gSneric_file_w     updates OH umtIme/ctImerbut wt need
+s	68 Oo+undo tHat(because OHisAI/OAwas supposed to(be
+s	68 invisible.p+	s 8/
+		s,* Ok,inode	*inode =+LINVFS_GET_IP(vp);
+		inode->i_mtImer=,x(p->i_d.di_mtIme.t_sec;p+		inode->i_ctImer=,x(p->i_d.di_ctIme.t_sec;p+	} e_HWo{p+	sxfs_ichgtIme(xip,,XFS_ICHGTIME_MOD |,XFS_ICHGTIME_CHG);p+	}p+p+	if ((retr== -ENOSPC)A&&
+	    DM_EVENT_ENABLED(vp->v_vfsp,,xip,,DM_EVENT_NOSPACE)r&&
+	    !(io+c ls & IO_INVIS))o{p+p+	sxfs_rwun12B,(bdp,,12B,Oype);
+		error = XFS_SEND_NAMESP(x(p->i_m*/in,,DM_EVENT_NOSPACE, vp,p+EE		DM_RIGHT_Nt a, vp,,DM_RIGHT_Nt a, Nt a, Nt a,p+EE		0, 0, 0); 4- Delay fc lfintentISFally  unused */p+		if (error)p+EEsr dirt -error;p+s	xfs_rw12B,(bdp,,12B,Oype);
+		*offsetr=,x(p->i_d.di_snit;
+	sgoto+r dry;p+	}p+p+error:p+Eif (retr<= 0) {p+	sif (io12B,)p+	sExfs_rwun12B,(bdp,,12B,Oype);
+		r dirt r t;p+	}p+p+	XFS_STATS_ADD(xs_w    _by  s,+r d);p+p+	if (*offset >,x(p->i_d.di_snit)o{p+	sxfs_i12B,(xip,,XFS_ILOCK_EXCL);
+		if (*offset >,x(p->i_d.di_snit)o{p+	s	s,* Ok,inode	*inode =+LINVFS_GET_IP(vp);
+p+	sEx(p->i_d.di_snit =(*offset;p+		si_snit_w    (inode, *offset);p+EEsx(p->i_update_core = 1;
+		sx(p->i_update_snit =(1;
+		smark_inode_dirty_sync(inode);p+		}
+		xfs_iun12B,(xip,,XFS_ILOCK_EXCL);
+	}p+p+E4- Handle various SYNC-Oypefw    s */p+	if ((.ile->f_+c ls & O_SYNC) || IS_SYNC(.ile->f_dentry->d_inode))o{p+p+	s/*p+	s 8+If we'rf treatiig OHdonas O_DSYNC( nd(we igaf _ty(updatedryvep+	s 8 snit, forc  OH ulog.p+	s 8/
+
+		if (!(mp->m_+c ls & XFS_MOUNT_OSYNCISOSYNC)p+	sE&& !(x(p->i_update_snit))o{p+EEs/*p+	s	68 If(an a2_HWatISF ,*ansactISF,occurrSdp+	s	68 winvout extSndiig OHe snit, tHei2we igaf Oo+forc p+	s	68 OH ulog up tHe proper point to+ensurf tHat(yvep+	s	68( 2_HWatISF is6pISmanent.  Wt can't c*/in onp+	s	68 OH ufact(tHat(buffered w    s 12B, out direct I/Op+	s	68 w    s -+OHe  irect I/OAw     cGuld igaf extSndSdp+	s	68 OHeAsnit non,*ansactISFally, tHei2hom(sht }befor 
+	s	68 we+s,arted.  xfs_w    _file will OHdnk tHat(yveAfile
+	s	68 didn't growrbut OHe updatenisn't safe+un1ess(yvep+	s	68(snit change is 12gged.
+			 *
+	s	68(Forc  OH ulog6if we'v  comm  ted a(,*ansactISFp+	s	68( gaiist OHe inode or if someome e_HWohas and
+	s	68 OHeAcomm  +r cord igsn't gome Oo+ isk (e.g.
+	s	68 OHeAinode is6pinted).  THdonguaranteesAOHatp+	s	68( 2_ changesuaffectiig OHe inode are pISmanent
+	s	68 wHei2we r dirt.p+	ss 8/
+
+			xfs_inode_log_item_t *iip;
+			xfs_lsn_,A1sn;
+p+	sEiipr=,x(p->i_itemp;p+		sif (iipr&& i(p->ili_last_1sn)o{p+EE		1snr=,((p->ili_last_1sn;p+		s	xfs_log_forc (mp,,lsn,
+			s		XFS_LOG_FORCE |,XFS_LOG_SYNC);p+		s} e_HWoif (xfs_ipinc*/in(x(p) > 0)o{p+EE		xfs_log_forc (mp,,(xfs_lsn_,)0,
+			s		XFS_LOG_FORCE |,XFS_LOG_SYNC);p+		s}
+p+	s} e_HWo{p+	s	xfs_,*ans_t	*tp;
+p+	sE/*p+	s	68 O_SYNC or O_DSYNC(_winv_ a sdze updatenare handledp+	s	68 OHeAsamtrway.
+			 *
+	s	68(If tHe w     was synchronous tHei2we need to(makep+	s	68(surf tHat(yve inode modifiWatISF ,Imeris6pISmanent.p+	s	68(Wt'2_ igaf updatedryve ,Imes,amp(above, so+her 
+	s	68 we+use a synchronous t*ansactISF,to(log6yve inode.p+	s	68(It's _ty(fast,+but it's _ecessary.
+			 *
+	s	68(If tHis aAdsync w     and OHeAsnit got changedp+	s	68 non-,*ansactISFally, tHei2wt need to(ensurf tHatp+	s	68 OHeAsnit change gets+12gged in a synchronousp+	s	68 O*ansactISF.p+	ss 8/
+
+			tp = xfs_,*ans_ 2_HW(mp,,XFS_TRANS_WRITE_SYNC);p+		sif ((error = xfs_,*ans_r serve(tp, 0,
+			s		      XFS_SWRITE_LOG_RES(mp),
+			s		      0, 0, 0)))o{p+EEsE4- T*ansactISF,r serve failed */p+		s	xfs_,*ans_cancel(tp, 0);p+		s} e_HWo{p+EEsE4- T*ansactISF,r serve successful */p+		s	xfs_i12B,(xip,,XFS_ILOCK_EXCL);
+		s	xfs_,*ans_ijoin(tp, xip,,XFS_ILOCK_EXCL);
+		s	xfs_,*ans_ihold(tp, xip);
+		s	xfs_,*ans_log_inode(tp, xip,,XFS_ILOG_CORE);
+		s	xfs_,*ans_set_sync(tp);
+		s	error = xfs_,*ans_comm  (tp, 0, ct a);p+		E	xfs_iun12B,(xip,,XFS_ILOCK_EXCL);
+			}
+		}
+	} 4- (io+c ls & O_SYNC) 8/
+
+	4-
+	68 If wenare comiig fromran nfsd OHr ad OHeF insert(into+OH 
+	68 reference cacht.
+	 */p+
+Eif (!s,*cmp(currSnt->comm, "nfsd"))p+	sxfs_refcacht_insert(x(p);
+p+E4- Drop 12B, tHis way -+OHe old refcacht release doninrHere */p+	if (io12B,)p+	sxfs_rwun12B,(bdp,,12B,Oype);
+
+	r dirt(r d);p+}
+
+/*
+68 All xfs metadata buffers except(log6statt machome buffers
+68 gSt tHis attachtd as tHeir b_bds,*at c 2_back +unctISF.
+68 THdondonso OHat(we can Watch a buffer
+68 after}premakurely(unpintiig it Oo+forcibly(shutdown(yveAfilesystem.
+68/
+iny
+xfs_bds,*at_cb(s,* Ok,xfs_buf *bp)
+{p+	xfs_m*/in_t	*mp;p+
+Empr=,XFS_BUF_FSPRIVATE3(bp, xfs_m*/in_t *);p+Eif (!XFS_FORCED_SHUTDOWN(mp))o{p+EEpagebuf_ior quest(bp);
+		r dirt 0;p+	} e_HWo{p+	sxfs_buftrace("XFS__BDSTRAT IOERROR",+bp);
+EE/*p+	s 8+Metadata w     OHat didn't get+12gged but
+s	68 w   tSn delayed anyway. THeseraren't associated
+		68 winv a(,*ansactISF, and can(be ignor d.
+	s 8/
+		if (XFS_BUF_IODONE_FUNC(bp)f== ct ar&&
+		    (XFS_BUF_ISREAD(bp)) == 0)
+			r dirt (xfs_bioerror_re_HW(bp));
+		e_HWp+			r dirt (xfs_bioerror(bp));
+	}p+}p+p+
+iny
+xfs_bmap(bhv_desc_t	*bdp,
+	xfs_off_t	offset,
+	ssnit_ts	c*/in,
+	ints	+c ls,
+	xfs_iomap_t	*iomapp,
+	ints	*niomaps)
+{p+	xfs_inode_t	*ipr=,XFS_BHVTOI(bdp);p+Exfs_iocore_t	*io =o&(p->i_iocore;p+
+	ASSERT(((p->i_d.di_mode & S_IFMT) == S_IFREG);p+	ASSERT((((p->i_d.di_+c ls & XFS_DIFLAG_REALTIME) != 0)o==p+	       (((p->i_iocore.io_+c ls & XFS_IOCORE_RT) != 0));p+p+	r dirt xfs_iomap(io, offset, c*/in, +c ls, iomapp, niomaps);p+}
+
+/*
+68 Wrapper arouid bds,*at so OHat(we can stop data
+68 +/omrgoing Oo+disk in2casefwenare shuttdlg down(yveAfilesystem.
+68 Typically user+data goes+OHru OHdonpanv;(ome o++OHeAexceptISFo
+68(isfOHe superb12B,.p+68/
+iny
+xfsbds,*at(
+	s,* Ok,xfs_m*/in	*mp,
+	s,* Ok,xfs_buf		*bp)
+{p+	ASSERT(mp);p+Eif (!XFS_FORCED_SHUTDOWN(mp))o{p+EE4- Grio redirectISF,wGuld go+her 
+	s68(if (XFS_BUF_IS_GRIO(bp)) {p+	s 8/
+
+		pagebuf_ior quest(bp);
+		r dirt 0;p+	}
+
+	xfs_buftrace("XFSBDSTRAT IOERROR",+bp);
+Er dirt (xfs_bioerror_re_HW(bp));
+}
+
+/*
+68 If tHe undISlyiig (data/12g/rt) device is readonly, tHer  are some
+68(operatISFsAOHat(can_ty(proceed.
+ -/
+iny
+xfs_dev_is_read_only(p+	xfs_m*/in_t		*mp,
+	char			*messagt)
+{p+	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||p+	    xfs_readonly_buftarg(mp->m_12gdev_targp) ||p+	    (mp->m_rtdev_targpr&& xfs_readonly_buftarg(mp->m_rtdev_targp)))o{p+EEcmn_err(CE_NOTE,
+			"XFS: %s r quired SF,r ad-only device.",+messagt);p+EEcmn_err(CE_NOTE,
+			"XFS: w     access unavailable,(can_ty(proceed.");
+		r dirt EROFS;p+	}p+Er dirt 0;p+}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_lrw.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_lrw.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_lrw.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_lrw.h	2004-07-30 16:29:08.000000000 +0000
@@ -0,0 +1,111 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifndef __XFS_LRW_H__
+# /home __XFS_LRW_H__
+
+s,* Ok,vnode;
+s,* Ok,bhv_desc;
+s,* Ok,xfs_m*/in;
+s,* Ok,xfs_iocore;p+s,* Ok,xfs_inode;
+s,* Ok,xfs_bmbt_irec;
+s,* Ok,xfs_buf;
+s,* Ok,xfs_iomap;
+
+#if  /homed(XFS_RW_TRACE)p+4-
+68 D/homesuforAOHeAcracefmechanismoninrxfs_lrw.c.
+ -/
+# /home	XFS_RW_KTRACE_SIZE	128
+
+# /home	XFS_READ_ENTER		1
+# /home	XFS_WRITE_ENTER		2
+# /home XFS_IOMAP_READ_ENTER	3
+# /home	XFS_IOMAP_WRITE_ENTER	4
+# /home	XFS_IOMAP_READ_MAP	5
+# /home	XFS_IOMAP_WRITE_MAP	6
+# /home	XFS_IOMAP_WRITE_NOSPACE	7
+# /home	XFS_ITRUNC_START	8
+# /home	XFS_ITRUNC_FINISH1	9
+# /home	XFS_ITRUNC_FINISH2	10
+# /home	XFS_CTRUNC1		11
+# /home	XFS_CTRUNC2		12
+# /home	XFS_CTRUNC3		13
+# /home	XFS_CTRUNC4		14
+# /home	XFS_CTRUNC5		15
+# /home	XFS_CTRUNC6		16
+# /home	XFS_BUNMAPI		17
+# /home	XFS_INVAL_CACHED	18
+# /home	XFS_DIORD_ENTER		19
+# /home	XFS_DIOWR_ENTER		20
+# /home	XFS_SENDFILE_ENTER	21
+# /home	XFS_WRITEPAGE_ENTER	22
+# /home	XFS_RELEASEPAGE_ENTER	23
+# /home	XFS_IOMAP_ALLOC_ENTER	24
+# /home	XFS_IOMAP_ALLOC_MAP	25
+# /home	XFS_IOMAP_UNWRITTEN	26
+extSrt vic (xfs_rw_enter_trace(iin, s,* Ok,xfs_iocore *,
+			coist char *, snit_t,,loff_t,,iin);p+extSrt vic (xfs_inval_cachtd_trace(s,* Ok,xfs_iocore *,
+			xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);p+#e_HWp+# /home xfs_rw_enter_trace(tag, io, buf, snit, offset, io+c ls)
+# /home xfs_inval_cachtd_trace(io, offset, len, first, last)
+#end(+
+
+4-
+68 Maximum c*/in of bmaps used by r ad and w     panvs.
+ -/
+# /home	XFS_MAX_RW_NBMAPS	4
+p+extSrt int xfs_bmap(s,* Ok,bhv_desc *, xfs_off_t, ssnit_t,,iin,
+			s,* Ok,xfs_iomap *, int *);p+extSrt int xfsbds,*at(s,* Ok,xfs_m*/in *, s,* Ok,xfs_buf *);p+extSrt int xfs_bds,*at_cb(s,* Ok,xfs_buf *);p+p+extSrt int xfs_zero_tof(s,* Ok,vnode *, s,* Ok,xfs_iocore *, xfs_off_t,p+		E	xfs_fsnit_t,,xfs_fsnit_t);p+extSrt vic (xfs_inval_cachtd_pages(s,* Ok,vnode	*, s,* Ok,xfs_iocore *,p+		E	xfs_off_t,,iin,,iin);p+extSrt ssnit_t xfs_read(s,* Ok,bhv_desc *, s,* Ok,.ile *, char	*,p+		E	snit_t,,loff_t *, int, s,* Ok,crtd *);p+extSrt ssnit_t xfs_w    (s,* Ok,bhv_desc *, s,* Ok,.ile *, coist char *,p+		E	snit_t,,loff_t *, int, s,* Ok,crtd *);p+p+extSrt int xfs_dev_is_read_only(s,* Ok,xfs_m*/in *, char *);p+p+# /home XFS_FSB_TO_DB_IO(io,fsb) \p+		((((o)->io_+c ls & XFS_IOCORE_RT) ? \p+		 XFS_FSB_TO_BB(((o)->io_m*/in,,(fsb)) : \p+		 XFS_FSB_TO_DADDR(((o)->io_m*/in,,(fsb)))
+
+#end(+	4- __XFS_LRW_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_stats.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_stats.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_stats.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_stats.c	2004-07-30 16:26:14.000000000 +0000
@@ -0,0 +1,117 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+#include <linux/proc_fs.h>
+
+s,* Ok,xfsstats,xfsstats;p+p+STATIC iny
+xfs_read_xfsstats(
+	char		*buffer,
+	char		**s,art,
+	off_t		offset,
+	ints	c*/in,
+	ints	*tof,
+	vic s	*data)
+{p+	ints	i, j, len;
+	s,atIc s,* Ok,xstats_entryo{p+EEchar	*desc;
+		iinEendpoint;p+	} xstats[] =o{p+EE{ "extSnk_ 2_HW",	XFSSTAT_END_EXTENT_ALLOC	},p+EE{ "abt",		XFSSTAT_END_ALLOC_BTREE		},p+EE{ "blk_map",		XFSSTAT_END_BLOCK_MAPPING	},p+EE{ "bmbt",		XFSSTAT_END_BLOCK_MAP_BTREE	},p+EE{ "dir",		XFSSTAT_END_DIRECTORY_OPS	},p+EE{ ",*ans",		XFSSTAT_END_TRANSACTIONS	},p+EE{ "ig",			XFSSTAT_END_INODE_OPS		},p+EE{ "log",		XFSSTAT_END_LOG_OPS		},p+EE{ "push_ail",		XFSSTAT_END_TAIL_PUSHING	},p+EE{ "xs,*at",		XFSSTAT_END_WRITE_CONVERT	},p+EE{ "rw",			XFSSTAT_END_READ_WRITE_OPS	},p+EE{ "attr",		XFSSTAT_END_ATTRIBUTE_OPS	},p+EE{ "icluscer",		XFSSTAT_END_INODE_CLUSTER	},p+EE{ "vnodes",		XFSSTAT_END_VNODE_OPS		},p+EE{ "buf",		XFSSTAT_END_BUF			},p+E};p+p+	forA(i=j=len = 0;A( < snitof(xstats)/snitof(s,* Ok,xstats_entry);A(++)o{p+	slen += sprdltf(buffer + len, xstats[i].desc);
+EE/* internloop does+each group 8/
+		wHile (j < xstats[i].endpoint)o{p+EEslen += sprdltf(buffer + len, " %u",
+			s	*(((__u32*)&xfsstats) + j));
+EEEj++;p+		}
+		buffer[len++] =o'\n';p+	}p+E4-+extra+precisISF c*/iners */p+	len += sprdltf(buffer + len, "xpc %Lu %Lu %Lu\n",
+			xfsstats.xs_xs,*at_by  s,
+			xfsstats.xs_w    _by  s,
+			xfsstats.xs_read_by  s);
+	len += sprdltf(buffer + len, "debug %u\n",
+#if  /homed(DEBUG)
+		1);p+#e_HWp+		0);p+#end(+
+
+	if (offset >= len)o{p+EE*s,art = buffer;
+		*tof =(1;
+		r dirt 0;p+	}p+E*s,art = buffer +(offset;p+Eif ((lenf-= offset) > c*/in)p+	sr dirt c*/in;
+	*tof =(1;
+p+Er dirt len;
+}
+
+vic 
+xfs_init_procfs(vic )
+{p+	if (!proc_mkdir("fs/xfs", 0))p+	sr dirt;
+	creatt_proc_read_entry("fs/xfs/stat", 0, 0, xfs_read_xfsstats, ct a);p+}
+
+vic 
+xfs_cleanup_procfs(vic )
+{p+	removt_proc_entry("fs/xfs/stat", ct a);p+	removt_proc_entry("fs/xfs", ct a);p+}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_stats.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_stats.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_stats.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_stats.h	2004-07-30 16:28:38.000000000 +0000
@@ -0,0 +1,160 @@
+4-
+68 Copyright (c) 2000 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifndef __XFS_STATS_H__
+# /home __XFS_STATS_H__
+
+
+#if  /homed(CONFIG_PROC_FS) && ! /homed(XFS_STATS_OFF)
+
+4-
+68 XFS global6statistics
+ -/
+s,* Ok,xfsstats,{p+#  /home XFSSTAT_END_EXTENT_ALLOC	4p+	__udlt32_t		xs_ 2_HWx;p+	__udlt32_t		xs_ 2_HWb;p+	__udlt32_t		xs_+/hox;p+	__udlt32_t		xs_+/hob;p+#  /home XFSSTAT_END_ALLOC_BTREE	(XFSSTAT_END_EXTENT_ALLOC+4)p+	__udlt32_t		xs_ bt_12okup;p+	__udlt32_t		xs_ bt_compare;p+	__udlt32_t		xs_ bt_insrec;
+	__udlt32_t		xs_ bt_delrec;
+#  /home XFSSTAT_END_BLOCK_MAPPING	(XFSSTAT_END_ALLOC_BTREE+7)p+	__udlt32_t		xs_blk_mapr;
+	__udlt32_t		xs_blk_mapw;
+	__udlt32_t		xs_blk_unmap;
+	__udlt32_t		xs_ dd_exlist;
+	__udlt32_t		xs_del_exlist;
+	__udlt32_t		xs_12ok_exlist;
+	__udlt32_t		xs_cmp_exlist;
+#  /home XFSSTAT_END_BLOCK_MAP_BTREE	(XFSSTAT_END_BLOCK_MAPPING+4)p+	__udlt32_t		xs_bmbt_12okup;p+	__udlt32_t		xs_bmbt_compare;p+	__udlt32_t		xs_bmbt_insrec;
+	__udlt32_t		xs_bmbt_delrec;
+#  /home XFSSTAT_END_DIRECTORY_OPS	(XFSSTAT_END_BLOCK_MAP_BTREE+4)p+	__udlt32_t		xs_dir_12okup;p+	__udlt32_t		xs_dir_creatt;p+	__udlt32_t		xs_dir_removt;p+	__udlt32_t		xs_dir_getdents;
+#  /home XFSSTAT_END_TRANSACTIONS	(XFSSTAT_END_DIRECTORY_OPS+3)p+	__udlt32_t		xs_,*ans_sync;
+	__udlt32_t		xs_,*ans_ sync;
+	__udlt32_t		xs_,*ans_empty;
+#  /home XFSSTAT_END_INODE_OPS		(XFSSTAT_END_TRANSACTIONS+7)p+	__udlt32_t		xs_ig_attempts;
+	__udlt32_t		xs_ig_fouid;
+	__udlt32_t		xs_ig_frecycle;
+	__udlt32_t		xs_ig_missed;
+	__udlt32_t		xs_ig_dup;p+	__udlt32_t		xs_ig_reclaims;
+	__udlt32_t		xs_ig_attrchg;
+#  /home XFSSTAT_END_LOG_OPS		(XFSSTAT_END_INODE_OPS+5)p+	__udlt32_t		xs_log_w    s;
+	__udlt32_t		xs_12g_b12B,s;
+	__udlt32_t		xs_12g_noic12gs;
+	__udlt32_t		xs_12g_forc ;
+	__udlt32_t		xs_12g_forc _sleep;
+#  /home XFSSTAT_END_TAIL_PUSHING	(XFSSTAT_END_LOG_OPS+10)p+	__udlt32_t		xs_,*y_12gspace;
+	__udlt32_t		xs_sleep_12gspace;
+	__udlt32_t		xs_push_ail;
+	__udlt32_t		xs_push_ail_success;
+	__udlt32_t		xs_push_ail_pushbuf;
+	__udlt32_t		xs_push_ail_pinted;
+	__udlt32_t		xs_push_ail_12B,ed;
+	__udlt32_t		xs_push_ail_flushiig;
+	__udlt32_t		xs_push_ail_restarts;
+	__udlt32_t		xs_push_ail_flush;
+#  /home XFSSTAT_END_WRITE_CONVERT	(XFSSTAT_END_TAIL_PUSHING+2)p+	__udlt32_t		xs_xs,*at_quick;
+	__udlt32_t		xs_xs,*at_split;
+#  /home XFSSTAT_END_READ_WRITE_OPS	(XFSSTAT_END_WRITE_CONVERT+2)p+	__udlt32_t		xs_w    _ca2_s;
+	__udlt32_t		xs_read_ca2_s;p+#  /home XFSSTAT_END_ATTRIBUTE_OPS	(XFSSTAT_END_READ_WRITE_OPS+4)p+	__udlt32_t		xs_ ttr_get;
+	__udlt32_t		xs_ ttr_set;
+	__udlt32_t		xs_ ttr_removt;p+	__udlt32_t		xs_ ttr_list;
+#  /home XFSSTAT_END_INODE_CLUSTER	(XFSSTAT_END_ATTRIBUTE_OPS+3)p+	__udlt32_t		xs_iflush_c*/in;
+	__udlt32_t		xs_icluscer_flushcin;
+	__udlt32_t		xs_icluscer_flushinode;
+#  /home XFSSTAT_END_VNODE_OPS		(XFSSTAT_END_INODE_CLUSTER+8)p+	__udlt32_t		vn_actIvt;E4-+#,vnodes _ty(SF +/ho(lists */p+	__udlt32_t		vn_a2_HW;E4-+#,,Imes vn_a2_HWnca2_ed */p+	__udlt32_t		vn_get;	E4-+#,,Imes vn_get+ca2_ed */p+	__udlt32_t		vn_hold;E4-+#,,Imes vn_hold+ca2_ed */p+	__udlt32_t		vn_rele;E4-+#,,Imes vn_rele+ca2_ed */p+	__udlt32_t		vn_reclaim;E4-+#,,Imes vn_reclaim ca2_ed */p+	__udlt32_t		vn_removt;E4-+#,,Imes vn_removt ca2_ed */p+	__udlt32_t		vn_+/ho;E4-+#,,Imes vn_+/ho(ca2_ed */p+# /home XFSSTAT_END_BUF			(XFSSTAT_END_VNODE_OPS+9)p+	__udlt32_t		pb_get;
+	__udlt32_t		pb_creatt;p+	__udlt32_t		pb_get_12B,ed;
+	__udlt32_t		pb_get_12B,ed_wa   d;
+	__udlt32_t		pb_busy_12B,ed;
+	__udlt32_t		pb_miss_12B,ed;
+	__udlt32_t		pb_page_r dri s;
+	__udlt32_t		pb_page_fouid;
+	__udlt32_t		pb_get_read;
+4- Extra+precisISF c*/iners */p+	__udlt64_t		xs_xs,*at_by  s;p+	__udlt64_t		xs_w    _by  s;p+	__udlt64_t		xs_read_by  s;p+};p+p+extSrt s,* Ok,xfsstats,xfsstats;p+p+#  /home XFS_STATS_INC(c*/in)		(,xfsstats.c*/in++ )p+#  /home XFS_STATS_DEC(c*/in)		(,xfsstats.c*/in-- )p+#  /home XFS_STATS_ADD(c*/in, inc)	(,xfsstats.c*/in += (inc) )p+p+extSrt vic (xfs_init_procfs(vic );p+extSrt vic (xfs_cleanup_procfs(vic );
+
+
+#e_HWE4-+!CONFIG_PROC_FS -/
+
+#  /home XFS_STATS_INC(c*/in)p+#  /home XFS_STATS_DEC(c*/in)p+#  /home XFS_STATS_ADD(c*/in, inc)
+
+s,atIc __inlome vic (xfs_init_procfs(vic ) { };
+s,atIc __inlome vic (xfs_cleanup_procfs(vic ) { };
+
+#end(+	4- !CONFIG_PROC_FS -/
+
+#end(+ 4- __XFS_STATS_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_super.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_super.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_super.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_super.c	2004-07-30 16:29:56.000000000 +0000
@@ -0,0 +1,930 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_clnt.h"
+#include "xfs_,*ans.h"
+#include "xfs_sb.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_a2_HW.h"
+#include "xfs_dmapi.h"
+#include "xfs_quota.h"
+#include "xfs_m*/in.h"
+#include "xfs_a2_HW_btree.h"
+#include "xfs_bmap_btree.h"
+#include "xfs_ia2_HW_btree.h"
+#include "xfs_btree.h"
+#include "xfs_ia2_HW.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_bmap.h"
+#include "xfs_bin.h"
+#include "xfs_rta2_HW.h"
+#include "xfs_error.h"
+#include "xfs_itable.h"
+#include "xfs_rw.h"
+#include "xfs_acl.h"
+#include "xfs_cap.h"
+#include "xfs_maW.h"
+#include "xfs_attr.h"
+#include "xfs_buf_item.h"
+#include "xfs_utils.h"
+#include "xfs_versISF.h"
+
+#include <linux/init.h>
+
+STATIC s,* Ok,quotactl_ops linvfs_qops;p+STATIC s,* Ok,super_operatISFsAlinvfs_sops;p+STATIC kmem_zont_t *linvfs_inode_zont;p+STATIC kmem_shaker_t,xfs_inode_shaker;
+
+STATIC s,* Ok,xfs_m*/in_args -
+xfs_args_a2_HWate(
+	s,* Ok,super_b12B,	*sb)p+{
+	s,* Ok,xfs_m*/in_args	*args;
+p+Eargs = kmem_z 2_HW(snitof(s,* Ok,xfs_m*/in_args), KM_SLEEP);p+	args->logbufs = args->logbufsnit =(-1;
+	strncpy(args->fsname, bdevname(sb->s_dev), MAXNAMELEN);
+p+E4- Copy OH ualready-parsed m*/in(2) +c ls we'rf interested in2*/p+	if (sb->s_+c ls & MS_NOATIME)p+	sargs->fc ls |=,XFSMNT_NOATIME;
+p+E4- Default Oo+32 bit inodes6onrLinux( 2_ yve ,Ime2*/p+	args->fc ls |=,XFSMNT_32BITINODES;
+p+Er dirt args;
+}
+
+__udlt64_t
+xfs_max_file_offset(
+	unsigted ints	b12B,shift)p+{
+	unsigted ints	pagefactor = 1;
+	unsigted ints	bitshiftr=,BITS_PER_LONGr-,1;
+p+E4- Figurf out maximum filesnit, onrLinux(OHdoncan depeFd onp+	68 OH ufilesystem b12B,snit (onr32 bit platforms).
+	 * __b12B,_prepare_w     does+OHdoninran [unsigted] long...
+	 *      page->iidIx << (PAGE_CACHE_SHIFTr-,bbits)
+	 * So, forApageAsizt }b12B,s (4K onr32 bit platforms),p+	68 OHis wraps at arouid 8Tb (hence MAX_LFS_FILESIZErwHich isp+	 *      (((u64)PAGE_CACHE_SIZEr<< (BITS_PER_LONG-1))-1)p+	 * but forAsma2_er b12B,snits it is 1ess((bbits =olog2 bsnit).
+	 * Ntye1: get_b12B,_t Oakes aAlong (implicit+cast fromrabove)
+	 * Ntye2:+THe Large B12B, Device (LBD and HAVE_SECTOR_T) panch
+	 * can optISFally convert(OH u[unsigted] long fromrabove(into
+	 * an [unsigted] long long.
+	 */p+
+#if BITS_PER_LONGr==r32
+	pagefactor = PAGE_CACHE_SIZEr>> (PAGE_CACHE_SHIFTr-,b12B,shift);p+#end(+
+
+	r dirt (((__udlt64_t)pagefactor)r<< bitshift)r-,1;
+}
+
+STATIC __inlome__ vic 
+xfs_set_inodeops(
+	s,* Ok,inode		*inode)p+{
+	vnode_t			*vp =+LINVFS_GET_VP(inode);p+p+	if (vp->v_Oypef== VNON) {p+	sr movt_inode_hash(inode);p+		make_bad_inode(inode);p+	} e_HWoif (S_ISREG(inode->i_mode))o{p+		inode->i_op =+&linvfs_file_inode_operatISFs;p+		inode->i_fop =+&linvfs_file_operatISFs;p+		inode->i_mappiig->a_ops =+&linvfs_aops;p+	} e_HWoif (S_ISDIR(inode->i_mode))o{p+		inode->i_op =+&linvfs_dir_inode_operatISFs;p+		inode->i_fop =+&linvfs_dir_operatISFs;p+	} e_HWoif (S_ISLNK(inode->i_mode))o{p+		inode->i_op =+&linvfs_symlink_inode_operatISFs;p+		if (inode->i_b12B,s)
+			inode->i_mappiig->a_ops =+&linvfs_aops;p+	} e_HWo{p+		inode->i_op =+&linvfs_file_inode_operatISFs;p+		init_specia2_inode(inode, inode->i_mode,
+			s	kdev_t_to_nr(inode->i_rdev));
+	}p+}p+p+STATIC __inlome__ vic 
+xfs_revalidate_inode(
+	xfs_m*/in_t		*mp,
+	vnode_t			*vp,
+	xfs_inode_t		*ip)p+{
+	s,* Ok,inode		*inode =+LINVFS_GET_IP(vp);
+p+	inode->i_mode	= (ip->i_d.di_mode & MODEMASK) | VTTOIF(vp->v_Oype);p+Einode->i_nlomk	= ip->i_d.di_nlomk;p+Einode->i_uid	= ip->i_d.di_uid;p+Einode->i_gid	= ip->i_d.di_gid;p+Eif (((1r<< vp->v_Oype) & ((1<<VBLK) | (1<<VCHR))) == 0)o{p+		inode->i_rdev =,cODEV;p+	} e_HWo{p+		xfs_dev_t dev =,ip->i_df.if_u2.if_rdev;p+		inode->i_rdev =,XFS_DEV_TO_KDEVT(dev);
+	}p+	inode->i_b1ksnit =(PAGE_CACHE_SIZE;p+Einode->i_generatISF = ip->i_d.di_gen;
+	i_snit_w    (inode, (p->i_d.di_snit);p+	inode->i_b12B,s =p+		XFS_FSB_TO_BB(mp,,ip->i_d.di_nb12B,s +,ip->i_delayed_b1ks);p+	inode->i_a,Ime	= ip->i_d.di_atIme.t_sec;p+	inode->i_mtIme	= ip->i_d.di_mtIme.t_sec;p+	inode->i_ctIme	= ip->i_d.di_ctIme.t_sec;p+	if (ip->i_d.di_+c ls & XFS_DIFLAG_IMMUTABLE)p+		inode->i_fc ls |=,S_IMMUTABLE;p+	e_HWp+		inode->i_fc ls &= ~S_IMMUTABLE;p+	if (ip->i_d.di_+c ls & XFS_DIFLAG_APPEND)p+		inode->i_fc ls |=,S_APPEND;p+	e_HWp+		inode->i_fc ls &= ~S_APPEND;p+	if (ip->i_d.di_+c ls & XFS_DIFLAG_SYNC)p+	sinode->i_fc ls |=,S_SYNC;p+	e_HWp+		inode->i_fc ls &= ~S_SYNC;p+	if (ip->i_d.di_+c ls & XFS_DIFLAG_NOATIME)p+	sinode->i_fc ls |=,S_NOATIME;
+	e_HWp+		inode->i_fc ls &= ~S_NOATIME;
+p+Evp->v_fc lf&= ~VMODIFIED;p+}
+
+vic 
+xfs_initializt_vnode(
+	bhv_desc_t		*bdp,
+	vnode_t			*vp,
+	bhv_desc_t		*inode_bhv,
+	ints		un12B,)
+{p+	xfs_inode_t		*ipr=,XFS_BHVTOI(inode_bhv);
+	s,* Ok,inode		*inode =+LINVFS_GET_IP(vp);
+p+	if (!inode_bhv->bd_vobj)o{p+		vp->v_vfsp = bhvtovfs(bdp);p+E	bhv_desc_init(inode_bhv,,ip, vp,,&xfs_vnodeops);p+E	bhv_insert(VN_BHV_HEAD(vp),(inode_bhv);
+	}
+p+Evp->v_Oypef= IFTOVT(ip->i_d.di_mode);
+p+E4- Hgaf we been(ca2_ed duriig OHe new inode creattrprocess,p+	68 inrwHich casefwenare Ooo+early to(fill in2OHeALinux(inode.p+	2*/p+	if (vp->v_Oypef== VNON)
+	sr dirt;
+p+	xfs_revalidate_inode(XFS_BHVTOM(bdp),(vp,,ip);
+p+E4- For new inodes2wt need to(sSt tHe ops vectors,p+	68 and un12B,6yve inode.p+	2*/p+	if (un12B,6&& (inode->i_statt & I_NEW))o{p+	sxfs_set_inodeops(inode);p+		un12B,_new_inode(inode);p+	}p+}
+
+iny
+xfs_inode_shake(
+	ints	prio   y,
+	unsigted intsgfp_mask)
+{p+	ints	pages;
+p+Epages = kmem_zont_shriik(linvfs_inode_zont);p+	pages += kmem_zont_shriik(xfs_inode_zont);p+	r dirt pages;
+}
+
+s,* Ok,inode -
+xfs_get_inode(
+	bhv_desc_t	*bdp,
+	xfs_ino_t	ino,
+	ints	+c ls)p+{
+	s,* Ok,vfs	*vfsp = bhvtovfs(bdp);p+p+	r dirt iget_12B,ed(vfsp->vfs_super,(ino);p+}
+
+vic 
+xfs_flush_inode(
+	xfs_inode_t	*ip)p+{
+	s,* Ok,inode	*inode =+LINVFS_GET_IP(XFS_ITOV(ip));p+p+	filemap_fdataw    (inode->i_mappiig);p+}
+
+vic 
+xfs_flush_device(
+	xfs_inode_t	*ip)p+{
+	s,* Ok,inode	*inode =+LINVFS_GET_IP(XFS_ITOV(ip));p+p+	fsync_no_super(inode->i_dev);
+	xfs_log_forc ((p->i_m*/in,,(xfs_lsn_,)0,,XFS_LOG_FORCE|XFS_LOG_SYNC);p+}
+
+s,* Ok,dentry -
+d_a2_HW_anon(s,* Ok,inode -inode)p+{
+	s,* Ok,dentry -dentry;p+p+	spii_12B,(&dcacht_12B,);p+Elist_for_each_entry(dentry,,&inode->i_dentry,,d_a2ias) {p+	sif (!(dentry->d_+c ls & DCACHE_NFSD_DISCONNECTED))p+	ssgoto+fouid;
+	}p+	spii_un12B,(&dcacht_12B,);p+p+	dentry = d_a2_HW_root(inode);p+	if (likely(dentry != ct a))p+	sdentry->d_+c ls |=,DCACHE_NFSD_DISCONNECTED;p+	r dirt dentry;p++fouid:p+Edget_12B,ed(dentry);p+	dentry->d_vfs_fc ls |=,DCACHE_REFERENCED;p+	spii_un12B,(&dcacht_12B,);p+	iput(inode);p+	r dirt dentry;p+}
+
+/*ARGSUSED8/
+iny
+xfs_blkdev_get(
+	xfs_m*/in_t		*mp,
+	coist chars	*name,
+	s,* Ok,b12B,_device	**bdevp)p+{
+	s,* Ok,nameidata	nd;p+Eint	s	error;p+p+	error = panv_12okup(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW,,&nd);p+	if (error)o{p+	sprdltk("XFS: Invalid device [%s],+error=%d\n", name, error);p+		r dirt -error;p+s}p+p+E4- I OHdnk wenactually wank,bd_acquire H re..  --hch */p+	*bdevp = bdget(kdev_t_to_nr(nd.dentry->d_inode->i_rdev));
+	if (*bdevp)p+s	error = blkdev_get(*bdevp, FMODE_READ|FMODE_WRITE, 0, BDEV_FS);
+	e_HWp+		error = -ENOMEM;
+p+Epanv_release(&nd);p+	r dirt -error;p+}
+
+vic 
+xfs_blkdev_put(
+	s,* Ok,b12B,_device	*bdev)
+{p+	if (bdev)
+s	b1kdev_put(bdev, BDEV_FS);
+}p+p+STATIC s,* Ok,inode -
+linvfs_a2_HW_inode(
+	s,* Ok,super_b12B,	*sb)p+{
+	vnode_t			*vp;
+p+Evp = (vnode_t *)kmem_cacht_ 2_HW(linvfs_inode_zont, p+++++++++++++++++kmem_fc ls_convert(KM_SLEEP));p+Eif (!vp)p+s	r dirt ct a;p+	r dirt LINVFS_GET_IP(vp);
+}p+p+STATIC vic 
+linvfs_des,*oy_inode(
+	s,* Ok,inode		*inode)p+{
+	kmem_cacht_+/ho(linvfs_inode_zont, LINVFS_GET_VP(inode));
+}p+p+# /home VNODE_SIZE	\p+	(snitof(vnode_t)r-,snitof(s,* Ok,inode) +(offsetof(s,* Ok,inode, u))
+
+STATIC vic 
+init_once(
+	vic s		*data,
+	kmem_cacht_t		*cachtp,
+	unsigted longs	+c ls)p+{
+	vnode_t			*vp =+(vnode_t *)data;
+p+	if ((+c ls & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR))o==p+	    SLAB_CTOR_CONSTRUCTOR)o{p+	ss,* Ok,inode -inode =+LINVFS_GET_IP(vp);
+		memset(vp, 0, VNODE_SIZE);
+		__inode_init_once(inode);p+	}p+}
+
+STATIC iny
+init_inodecacht( vic ()p+{
+	linvfs_inode_zont = kmem_cacht_creatt("linvfs_icacht",
+			sVNODE_SIZE, 0, SLAB_HWCACHE_ALIGN,
+			sinit_once, ct a);p+	if (linvfs_inode_zont == ct a)p+		r dirt -ENOMEM;
+Er dirt 0;p+}
+
+STATIC vic 
+des,*oy_inodecacht( vic ()p+{
+	if (kmem_cacht_des,*oy(linvfs_inode_zont))p+	sprdltk(KERN_WARNING "%s: cacht s,ill in2use!\n", __FUNCTION__);p+}
+
+/*
+68 Attempt to(flush6yve inode,+tHdonwill actually fail
+68 if OHe inode is6pinted,rbut wt dirty OHe inode agaii
+68( t tHe point wHei2it is unpinted after}a(log6w    ,
+68+since OHisAdonwhei2OHeAinode itself(becomes flushable. 
+ -/
+STATIC vic 
+linvfs_w    _inode(
+	s,* Ok,inode		*inode,
+	ints		sync)p+{
+	vnode_t			*vp =+LINVFS_GET_VP(inode);p+Eint	s	error, +c ls =+FLUSH_INODE;p+p+	if (vp)o{p+		vn_trace_entry(vp, __FUNCTION__, (insn_t *)__r dirt_ ddress);p+		if (sync)p+	s	+c ls |=,FLUSH_SYNC;p+		VOP_IFLUSH(vp, +c ls, error);p+	}
+}p+p+STATIC vic 
+linvfs_clear_inode(
+	s,* Ok,inode		*inode)p+{
+	vnode_t			*vp =+LINVFS_GET_VP(inode);p+p+	if (vp)o{p+		vn_rele(vp);
+		vn_trace_entry(vp, __FUNCTION__, (insn_t *)__r dirt_ ddress);p+		/*p+	s 8+Do( 2_ our cleanup, and removt OHisAvnode.p+	s 8/
+		vn_removt(vp);
+	}p+}p+p+
+# /home SYNCD_FLAGS	(SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE)
+
+STATIC iny
+xfssyncd(
+	vic s		*arg)p+{
+	vfs_,			*vfsp = (vfs_, *) arg;p+Eint	s	error;p+p+	daemonnit();p+	r parent_to_init();
+	sigmask_12B,();
+	sigfillset(&currSnt->b12B,ed);
+	__r calc_sigpSndiig(currSnt);
+	sigmask_un12B,();p+p+	sprdltf(currSnt->comm, "xfssyncd");p+p+	vfsp->vfs_sync_task = currSnt;
+	wmb();
+	wake_up(&vfsp->vfs_wa  _sync_task);p+p+	forA(;;)o{p+	sset_currSnt_statt(TASK_INTERRUPTIBLE);p+		schtdule_timeout((xfs_syncd_centIsecs 8+HZ) / 100);p+		if (vfsp->vfs_fc lf& VFS_UMOUNT)p+	s	break;p+		if (vfsp->vfs_fc lf& VFS_RDONLY)p+	s	continut;
+	sVFS_SYNC(vfsp,,SYNCD_FLAGS, Nt a, error);p+	}
+p+	vfsp->vfs_sync_task = ct a;p+	wmb();
+	wake_up(&vfsp->vfs_wa  _sync_task);p+p+	r dirt 0;p+}
+
+STATIC iny
+linvfs_start_syncd(
+	vfs_,			*vfsp)
+{p+	ints		pid;p+p+Epc (= kernel_OHr ad(xfssyncd, (vic (*) vfsp,p+	s	CLONE_VM | CLONE_FS | CLONE_FILES);p+	if (pc (< 0)
+		r dirt pid;p+Ewa  _eveit(vfsp->vfs_wa  _sync_task, vfsp->vfs_sync_task);p+	r dirt 0;p+}
+
+STATIC vic 
+linvfs_stop_syncd(
+	vfs_,			*vfsp)
+{p+	vfsp->vfs_fc lf|=,VFS_UMOUNT;p+	wmb();
+
+	wake_up_process(vfsp->vfs_sync_task);p+	wa  _eveit(vfsp->vfs_wa  _sync_task, !vfsp->vfs_sync_task);p+}
+
+STATIC vic 
+linvfs_put_super(
+	s,* Ok,super_b12B,	*sb)p+{
+	vfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error;p+p+	linvfs_stop_syncd(vfsp);p+EVFS_SYNC(vfsp,,SYNC_ATTR|SYNC_DELWRI, Nt a, error);p+	if (!error)p+EEVFS_UNMOUNT(vfsp,,0, Nt a, error);p+	if (error)o{p+	sprdltk("XFS unm*/in got error %d\n", error);p+		prdltk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp);p+		r dirt;p+	}
+p+	vfs_dea2_HWate(vfsp);p+}
+
+STATIC vic 
+linvfs_w    _super(
+	s,* Ok,super_b12B,	*sb)p+{
+	vfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error;p+p+	if (sb->s_+c ls & MS_RDONLY)o{p+	ssb->s_dirt = 0; 4- paranoia 8/
+		r dirt;p+	}
+E4- Push6yve log6and superb12B,}a(little2*/p+	VFS_SYNC(vfsp,,SYNC_FSDATA, Nt a, error);p+	sb->s_dirt = 0;p+}
+
+STATIC iny
+linvfs_sync_super(
+	s,* Ok,super_b12B,	*sb)p+{
+	vfs_,		*vfsp = LINVFS_GET_VFS(sb);p+Eint	serror;p+p+	VFS_SYNC(vfsp,,SYNC_FSDATA|SYNC_WAIT, Nt a, error);p+	sb->s_dirt = 0;p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_statfs(
+	s,* Ok,super_b12B,	*sb,
+	s,* Ok,statfsEE*s,atp)p+{
+	vfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error;p+p+	VFS_STATVFS(vfsp,,s,atp, Nt a, error);p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_remo/in(
+	s,* Ok,super_b12B,	*sb,
+	int	s	*+c ls,
+	char			*optISFs)p+{
+	vfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Es,* Ok,xfs_m*/in_args	*args = xfs_args_a2_HWate(sb);p+Eint	s	error;p+p+	VFS_PARSEARGS(vfsp,,optISFs, args, 1, error);p+	if (!error)p+EEVFS_MNTUPDATE(vfsp,,+c ls, args, error);p+	kmem_f/ho(args, snitof(*args));p+	r dirt -error;p+}
+
+STATIC vic 
+linvfs_f/hoze_fs(
+	s,* Ok,super_b12B,	*sb)p+{
+	vfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Evnode_t			*vp;
+Eint	s	error;p+p+	if (sb->s_+c ls & MS_RDONLY)
+		r dirt;p+	VFS_ROOT(vfsp,,&vp, error);p+	VOP_IOCTL(vp, LINVFS_GET_IP(vp), Nt a, 0,,XFS_IOC_FREEZE, 0, error);p+	VN_RELE(vp);
+}p+p+STATIC vic 
+linvfs_unf/hoze_fs(
+	s,* Ok,super_b12B,	*sb)p+{
+	vfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Evnode_t			*vp;
+Eint	s	error;p+p+	VFS_ROOT(vfsp,,&vp, error);p+	VOP_IOCTL(vp, LINVFS_GET_IP(vp), Nt a, 0,,XFS_IOC_THAW, 0, error);p+	VN_RELE(vp);
+}p+p+STATIC iny
+linvfs_dentry_to_fh(
+	s,* Ok,dentry		*dentry,
+	__u32s		*data,
+	int	s	*lenp,
+	ints		need_parent)p+{
+	s,* Ok,inode		*inode =+dentry->d_inode ;p+Evnode_t			*vp =+LINVFS_GET_VP(inode);p+Eint	s	maxlen = *lenp;p+Exfs_fid2_t		fid;p+Eint	s	error;p+p+	if (maxlen < 3)
+		r dirt 255 ;p+p+	VOP_FID2(vp, (s,* Ok,fc (*)&fc , error);p+	data[0] =o(__u32)fc .fc _ino;E4-+32 bits(o++inode is6OK2*/p+	data[1] =ofc .fc _gen;
+p+	*lenp =o2 ;p+	if (maxlen < 4 || ! need_parent)p+		r dirt 2 ;p+p+	inode =+dentry->d_parent->d_inode ;p+Evp =+LINVFS_GET_VP(inode);p+p+	VOP_FID2(vp, (s,* Ok,fc (*)&fc , error);p+	data[2] =o(__u32)fc .fc _ino;E4-+32 bits(o++inode is6OK2*/p+	*lenp =o3 ;p+	if (maxlen < 4)p+		r dirt 3 ;p+	data[3] =ofc .fc _gen;
+	*lenp =o4 ;p+	r dirt 4 ;p+}p+p+STATIC s,* Ok,dentry -
+linvfs_fh_to_dentry(
+	s,* Ok,super_b12B,	*sb,
+	__u32s		*data,
+	int	s	len,
+	int	s	fhOype,
+	int	s	parent)p+{
+	vnode_t			*vp;
+Es,* Ok,inode		*inode =+ct a;p+	s,* Ok,dentry		*result;p+Exfs_fid2_t		xfid;p+Evfs_,			*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error;p+p+	xfc .fc _len = snitof(xfs_fid2_t)r-,snitof(xfc .fc _len);
+	xfc .fc _pad = 0;p+p+	if (!parent)o{p+	sxfc .fc _gen =+data[1];p+	sxfc .fc _ino =o(__u64)data[0];p+	} e_HWo{p+		if (fhOype == 4)p+		sxfc .fc _gen =+data[3];p+	se_HWp+			xfc .fc _gen =+0;p+	sxfc .fc _ino =o(__u64)data[2];p+	}
+p+	VFS_VGET(vfsp,,&vp, (fc _, *)&xfc , error);p+	if (error || vp == ct a)p+		r dirt ERR_PTR(-ESTALE) ;p+p+	inode =+LINVFS_GET_IP(vp);
+p+	result = d_a2_HW_anon(inode);p+	if (unlikely(result == ct a))o{p+		iput(inode);p+		r dirt ERR_PTR(-ENOMEM);p+	}
+	r dirt result;p+}
+
+STATIC iny
+linvfs_show_optISFs(
+	s,* Ok,seq_file		*m,
+	s,* Ok,vfsm*/in		*mnt)p+{
+	s,* Ok,vfsEE*vfsp = LINVFS_GET_VFS(mnt->mnt_sb);p+Eint	s	error;p+p+	VFS_SHOWARGS(vfsp,,m, error);p+	r dirt error;p+}
+
+STATIC iny
+linvfs_getxstatt(
+	s,* Ok,super_b12B,	*sb,
+	s,* Ok,fs_quota_stat	*+qs)p+{
+	s,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error;p+p+	VFS_QUOTACTL(vfsp,,Q_XGETQSTAT, 0, (c ddr_t)+qs, error);p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_setxstatt(
+	s,* Ok,super_b12B,	*sb,
+	unsigted ints	+c ls,
+	int	s	op)p+{
+	s,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error;p+p+	VFS_QUOTACTL(vfsp,,op, 0, (c ddr_t)&+c ls, error);p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_getxquota(
+	s,* Ok,super_b12B,	*sb,
+	int	s	Oype,
+	qc _,		sid,
+	s,* Ok,fs_disk_quota	*+dq)p+{
+	s,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error, getmode;p+p+	getmode =o(Oype == GRPQUOTA) ? Q_XGETGQUOTA :,Q_XGETQUOTA;p+	VFS_QUOTACTL(vfsp,,getmode, c , (c ddr_t)+dq, error);p+	r dirt -error;p+}
+
+STATIC iny
+linvfs_setxquota(
+	s,* Ok,super_b12B,	*sb,
+	int	s	Oype,
+	qc _,		sid,
+	s,* Ok,fs_disk_quota	*+dq)p+{
+	s,* Ok,vfs		*vfsp = LINVFS_GET_VFS(sb);p+Eint	s	error, setmode;p+p+	setmode =o(Oype == GRPQUOTA) ? Q_XSETGQLIM :,Q_XSETQLIM;p+	VFS_QUOTACTL(vfsp,,setmode, c , (c ddr_t)+dq, error);p+	r dirt -error;p+}
+
+STATIC s,* Ok,super_b12B, -
+linvfs_read_super(
+	s,* Ok,super_b12B,	*sb,
+	vic s		*data,
+	int	s	silent)p+{
+	vnode_t			*rootvp;
+Es,* Ok,vfs		*vfsp = vfs_a2_HWatt();p+Es,* Ok,xfs_m*/in_args	*args = xfs_args_a2_HWate(sb);p+Es,* Ok,statfsEEstatvfs;p+Eint	s	error;p+p+	vfsp->vfs_super = sb;p+	LINVFS_SET_VFS(sb, vfsp);p+	if (sb->s_+c ls & MS_RDONLY)
+		vfsp->vfs_fc lf|=,VFS_RDONLY;p+	bhv_insert_a2__vfsops(vfsp);p+
+	VFS_PARSEARGS(vfsp,,(char *)data, args, 0, error);p+	if (error)o{p+	sbhv_r movt_a2__vfsops(vfsp, 1);p+		goto+fail_vfsop;p+	}
+p+	sb_min_b12B,snit(sb, BBSIZE);
+	sb->s_qcop =+&linvfs_qops;p+	sb->s_op =+&linvfs_sops;p+
+	VFS_MOUNT(vfsp,,args, Nt a, error);p+	if (error)o{p+	sbhv_r movt_a2__vfsops(vfsp, 1);p+		goto+fail_vfsop;p+	}
+p+	VFS_STATVFS(vfsp,,&statvfs, Nt a, error);p+	if (error)p+		goto+fail_unm*/in;p+p+	sb->s_dirt = 1;p+	sb->s_magic = statvfs.f_Oype;p+	sb->s_b12B,snit = statvfs.f_bsnit;p+	sb->s_b12B,snit_bits =offs(s,atvfs.f_bsnit)r-,1;
+	sb->s_maxby  s = xfs_max_file_offset(sb->s_b12B,snit_bits);
+	set_posix_acl_fc l(sb);p+
+	VFS_ROOT(vfsp,,&rootvp, error);p+	if (error)p+		goto+fail_unm*/in;p+p+	sb->s_root = d_a2_HW_root(LINVFS_GET_IP(rootvp));p+Eif (!sb->s_root)p+		goto+fail_vnrele;p+Eif (is_bad_inode(sb->s_root->d_inode))p+		goto+fail_vnrele;p+Eif (linvfs_start_syncd(vfsp))p+		goto+fail_vnrele;p+Evn_trace_exit(rootvp, __FUNCTION__, (insn_t *)__r dirt_ ddress);p+
+	kmem_f/ho(args, snitof(*args));p+	r dirt sb;p+
+fail_vnrele:p+	if (sb->s_root)o{p+	sdput(sb->s_root);p+		sb->s_root = ct a;p+	} e_HWo{p+		VN_RELE(rootvp);p+	}
+p+fail_unm*/in:
+	VFS_UNMOUNT(vfsp,,0, Nt a, error);p+
+fail_vfsop:
+	vfs_dea2_HWate(vfsp);p+	kmem_f/ho(args, snitof(*args));p+	r dirt ct a;p+}p+p+
+STATIC s,* Ok,super_operatISFsAlinvfs_sops =o{p+E.a2_HW_inode		=Alinvfs_a2_HW_inode,
+	.des,*oy_inode		=Alinvfs_des,*oy_inode,
+	.w    _inode		=Alinvfs_w    _inode,
+	.clear_inode		=Alinvfs_clear_inode,
+	.put_super		=Alinvfs_put_super,
+	.w    _super		=Alinvfs_w    _super,
+	.sync_fsEE=Alinvfs_sync_super,
+	.w    _super_12B,fsE=Alinvfs_f/hoze_fs,
+	.un12B,fsEE=Alinvfs_unf/hoze_fs,
+	.statfsEEE=Alinvfs_statfs,
+	.remo/in_fsEE=Alinvfs_remo/in,
+	.fh_to_dentryEE=Alinvfs_fh_to_dentry,
+	.dentry_to_fh		=Alinvfs_dentry_to_fh,
+	.show_optISFsEE=Alinvfs_show_optISFs,p+};p+p+STATIC s,* Ok,quotactl_ops linvfs_qops =o{p+E.get_xstattEE=Alinvfs_getxstatt,
+	.set_xstattEE=Alinvfs_setxstatt,
+	.get_xquota	E=Alinvfs_getxquota,
+	.set_xquota	E=Alinvfs_setxquota,
+};p+p+STATIC s,* Ok,file_system_Oypefxfs_fs_Oypef= {p+E.owner		E=ATHIS_MODULE,
+	.name		E=A"xfs",
+	.read_superEE=Alinvfs_read_super,
+	.fs_+c lsEE=AFS_REQUIRES_DEV,
+};p+p+
+STATIC iny __iniy
+init_xfs_fs( vic ()p+{
+	int	s	error;p+Es,* Ok,sysinfos	si;p+Es,atIc char		message[] __iniydataf= KERN_INFO \p+		XFS_VERSION_STRING " winv2",XFS_BUILD_OPTIONS2",enabled\n";p+
+	prdltk(message);p+p+	si_meminfo(&si);p+Exfs_physmem = sn.totalram;p+
+	ktrace_init(64);p+p+	error = init_inodecacht();p+	if (error < 0)
+		goto+undo_inodecacht;p+p+	error = pagebuf_init();
+	if (error < 0)
+		goto+undo_pagebuf;p+p+	vn_init();
+	xfs_init();
+	uuc _init();
+	vfs_initdmapi();
+	vfs_initquota();p+p+	xfs_inode_shaker = kmem_shake_regiscer(xfs_inode_shake);p+Eif (!xfs_inode_shaker)o{p+	serror = -ENOMEM;
+		goto+undo_shaker;
+	}
+p+	error = regiscer_filesystem(&xfs_fs_Oype);p+	if (error)p+		goto+undo_regiscer;p+	XFS_DM_INIT(&xfs_fs_Oype);p+	r dirt 0;p+
+undo_regiscer:p+	kmem_shake_deregiscer(xfs_inode_shaker);p+
+undo_shaker:p+	pagebuf_cerminate();p+
+undo_pagebuf:p+Edes,*oy_inodecacht();p+
+undo_inodecacht:
+	r dirt error;p+}
+
+STATIC vic (__exitp+exit_xfs_fs( vic ()p+{
+	XFS_DM_EXIT(&xfs_fs_Oype);p+	unregiscer_filesystem(&xfs_fs_Oype);p+	kmem_shake_deregiscer(xfs_inode_shaker);p+	xfs_cleanup();
+	vfs_exitquota();p+	vfs_exitdmapi();
+	pagebuf_cerminate();p+Edes,*oy_inodecacht();p+	ktrace_uninit();
+}
+
+module_init(init_xfs_fs);
+module_exit(exit_xfs_fs);p+
+MODULE_AUTHOR("Silicon Graphics, Inc.");p+MODULE_DESCRIPTION(XFS_VERSION_STRING " winv2",XFS_BUILD_OPTIONS2",enabled");p+MODULE_LICENSE("GPL");pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_super.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_super.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_super.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_super.h	2004-07-30 16:27:48.000000000 +0000
@@ -0,0 +1,140 @@
+4-
+68 Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifndef __XFS_SUPER_H__
+# /home __XFS_SUPER_H__
+
+#ifdef CONFIG_XFS_DMAPIp+#  /home vfs_insertdmapi(vfs)	vfs_insertops(vfsp, &xfs_dmops)p+#  /home vfs_initdmapi()	dmapi_init()p+#  /home vfs_exitdmapi()	dmapi_uninit()p+#e_HWp+#  /home vfs_insertdmapi(vfs)	do+{ } wHile (0)p+#  /home vfs_initdmapi()	do+{ } wHile (0)p+#  /home vfs_exitdmapi()	do+{ } wHile (0)p+#end(+
+
+#ifdef CONFIG_XFS_QUOTAp+#  /home vfs_insertquota(vfs)	vfs_insertops(vfsp, &xfs_qmops)p+extSrt vic (xfs_qm_init(vic );p+extSrt vic (xfs_qm_exit(vic );p+#  /home vfs_initquota()	xfs_qm_init()p+#  /home vfs_exitquota()	xfs_qm_exit()p+#e_HWp+#  /home vfs_insertquota(vfs)	do+{ } wHile (0)p+#  /home vfs_initquota()	do+{ } wHile (0)p+#  /home vfs_exitquota()	do+{ } wHile (0)p+#end(+
+
+#ifdef CONFIG_XFS_POSIX_ACLp+#  /home XFS_ACL_STRING		"ACLs, "p+#  /home set_posix_acl_fc l(sb)	((sb)->s_+c ls |= MS_POSIXACL)p+#e_HWp+#  /home XFS_ACL_STRINGp+#  /home set_posix_acl_fc l(sb)	do+{ } wHile (0)p+#end(+
+
+#ifdef CONFIG_XFS_SECURITYp+#  /home XFS_SECURITY_STRING	"secu   y attributes, "p+#  /home ENOSECURITY		0p+#e_HWp+#  /home XFS_SECURITY_STRINGp+#  /home ENOSECURITY		EOPNOTSUPPp+#end(+
+
+#ifdef CONFIG_XFS_RTp+#  /home XFS_REALTIME_STRING	"realtime, "p+#e_HWp+#  /home XFS_REALTIME_STRINGp+#end(+
+
+#if,XFS_BIG_BLKNOSp+# if,XFS_BIG_INUMSp+#   /home XFS_BIGFS_STRING	"large b12B,/inode numbers, "p+# e_HWp+#   /home XFS_BIGFS_STRING	"large b12B, numbers, "p+# end(+
+#e_HWp+#  /home XFS_BIGFS_STRINGp+#end(+
+
+#ifdef CONFIG_XFS_TRACEp+#  /home XFS_TRACE_STRING	"traciig, "p+#e_HWp+#  /home XFS_TRACE_STRINGp+#end(+
+
+#ifdef CONFIG_XFS_DMAPIp+#  /home XFS_DMAPI_STRING	"dmapi,support, "p+#e_HWp+#  /home XFS_DMAPI_STRINGp+#end(+
+
+#ifdef DEBUGp+#  /home XFS_DBG_STRING		"debug"p+#e_HWp+#  /home XFS_DBG_STRING		"no debug"p+#end(+
+
+# /home XFS_BUILD_OPTIONS	XFS_ACL_STRING \p+				XFS_SECURITY_STRING \p+				XFS_REALTIME_STRING \p+				XFS_BIGFS_STRING \p+				XFS_TRACE_STRING \p+				XFS_DMAPI_STRING \p+				XFS_DBG_STRING 4- DBG must benlast */p+
+# /home LINVFS_GET_VFS(s) \p+	(vfs_, *)((s)->u.generic_sbp)p+# /home LINVFS_SET_VFS(s, vfsp) \p+	((s)->u.generic_sbp = vfsp)
+
+s,* Ok,xfs_inode;
+s,* Ok,xfs_m*/in;p+s,* Ok,xfs_buftarg;p+s,* Ok,b12B,_device;p+
+extSrt __udlt64_t xfs_max_file_offset(unsigted int);p+
+extSrt s,* Ok,inode -xfs_get_inode(bhv_desc_t *,,xfs_ino_n, int);p+extSrt vic (xfs_initializt_vnode(bhv_desc_t *,,vnode_t *, bhv_desc_t *,,int);p+
+extSrt vic (xfs_flush_inode(s,* Ok,xfs_inode *);p+extSrt vic (xfs_flush_device(s,* Ok,xfs_inode *);p+p+extSrt iny  xfs_blkdev_get(s,* Ok,xfs_m*/in *,,coist char *,p+				s,* Ok,b12B,_device **);p+extSrt vic (xfs_b1kdev_put(s,* Ok,b12B,_device *);p+p+4- manchiig a 2.6 kernel export, thuon_t(xfs_+prefix */p+extSrt s,* Ok,dentry -d_a2_HW_anon(s,* Ok,inode -inode);p+p+#end(+	4- __XFS_SUPER_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_sysctl.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_sysctl.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_sysctl.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_sysctl.c	2004-07-30 16:31:19.000000000 +0000
@@ -0,0 +1,195 @@
+4-
+68 Copyright (c) 2001-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+#include "xfs_refcacht.h"
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>p+p+
+s,atIc s,* Ok,ctl_table_H adISA-xfs_table_H adIS;p+p+
+4- Customrproc igndlers */p+
+STATIC iny
+xfs_refcacht_resizt_proc_igndler(
+	ctl_table	*ctl,
+	int	sw    ,
+	s,* Ok,file	*filp,
+	vic s	*buffer,
+	sizt_ts	*lenp)p+{
+	int	srey, *valp = ctl->data;
+	int	sxfs_refcacht_new_snit;p+	int	sxfs_refcacht_old_snit = *valp;p+p+	r d = proc_dointvec_minmax(ctl,6w    , filp, buffer, lenp);p+	xfs_refcacht_new_snit = *valp;p+p+	if (!r d && w     && xfs_refcacht_new_snit != xfs_refcacht_old_snit)o{p+	sxfs_refcacht_resizt(xfs_refcacht_new_snit);p+		4- Don't purge morf tHan snit o++OHeAcacht 8/
+		if (xfs_refcacht_new_snit < xfs_refcacht_purge_c*/in)p+		sxfs_refcacht_purge_c*/in = xfs_refcacht_new_snit;
+	}
+p+	r dirt ret;p+}
+
+#ifdef CONFIG_PROC_FS
+STATIC iny
+xfs_stats_clear_proc_igndler(
+	ctl_table	*ctl,
+	int	sw    ,
+	s,* Ok,file	*filp,
+	vic s	*buffer,
+	sizt_ts	*lenp)p+{
+	int	srey, *valp = ctl->data;
+	__udlt32_t	vn_actIvt;p+p+	r d = proc_dointvec_minmax(ctl,6w    , filp, buffer, lenp);p+p+	if (!r d && w     && *valp)o{p+	sprdltk("XFS Cleariig xfsstats\n");p+		4- sgaf vn_actIvt,+(t's aAuniversal ,* th! 8/
+		vn_actIvt = xfsstats.vn_actIvt;p+		memset(&xfsstats,,0, snitof(xfsstats));p+		xfsstats.vn_actIvt = vn_actIvt;p+		xfs_stats_clear =+0;p+	}
+p+	r dirt ret;p+}
+#end(+ 4- CONFIG_PROC_FS -/
+
+STATIC ctl_table xfs_table[]f= {p+E{XFS_REFCACHE_SIZE, "refcacht_snit", &xfs_params.refcacht_snit.val,
+	siztof(int),,0644, Nt a, &xfs_refcacht_resizt_proc_igndler,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.refcacht_snit.min, &xfs_params.refcacht_snit.max},
+p+	/* Ntye,+OHeAmax H rendondifferein, it is OHeAcurrSnt refcacht snit 8/
+	{XFS_REFCACHE_PURGE, "refcacht_purge", &xfs_params.refcacht_purge.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.refcacht_purge.min, &xfs_params.refcacht_snit.val},
+p+	{XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.restrict_chown.min, &xfs_params.restrict_chown.max},
+p+	{XFS_SGID_INHERIT, "irix_sgi _inH rit", &xfs_params.sgi _inH rit.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.sgi _inH rit.min, &xfs_params.sgi _inH rit.max},
+p+	{XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.symlink_mode.min, &xfs_params.symlink_mode.max},
+p+	{XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.panic_mask.min, &xfs_params.panic_mask.max},
+p+	{XFS_ERRLEVEa, "error_level", &xfs_params.error_level.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.error_level.min, &xfs_params.error_level.max},
+p+	{XFS_SYNCD_TIMER, "xfssyncd_centIsecs", &xfs_params.syncd_timer.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.syncd_timer.min, &xfs_params.syncd_timer.max},
+p+	{XFS_INHERIT_SYNC, "inH rit_sync", &xfs_params.inH rit_sync.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a,
+	&xfs_params.inH rit_sync.min, &xfs_params.inH rit_sync.max},
+p+	{XFS_INHERIT_NODUMP, "inH rit_nod mp", &xfs_params.inH rit_nod mp.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a,
+	&xfs_params.inH rit_nod mp.min, &xfs_params.inH rit_nod mp.max},
+p+	{XFS_INHERIT_NOATIME, "inH rit_noatIme", &xfs_params.inH rit_noatIm.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a,
+	&xfs_params.inH rit_noatIm.min, &xfs_params.inH rit_noatIm.max},
+p+	{XFS_BUF_TIMER, "xfsbufd_centIsecs", &xfs_params.xfs_buf_timer.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a,
+	&xfs_params.xfs_buf_timer.min, &xfs_params.xfs_buf_timer.max},
+p+	{XFS_BUF_AGE, "age_buffer_centIsecs", &xfs_params.xfs_buf_age.val,
+	siztof(int),,0644, Nt a, &proc_dointvec_minmax,
+	&sysctl_intvec, Nt a,
+	&xfs_params.xfs_buf_age.min, &xfs_params.xfs_buf_age.max},
+p+	/* please keep OHdonOHeAlast entry -/
+#ifdef CONFIG_PROC_FS
+	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
+	siztof(int),,0644, Nt a, &xfs_stats_clear_proc_igndler,
+	&sysctl_intvec, Nt a, 
+	&xfs_params.stats_clear.min, &xfs_params.stats_clear.max},
+#end(+ 4- CONFIG_PROC_FS -/
+
+	{0}
+};p+p+STATIC ctl_table xfs_dir_table[]f= {p+E{FS_XFS,A"xfs", Nt a, 0,,0555, xfs_table},
+	{0}
+};p+p+STATIC ctl_table xfs_root_table[]f= {p+E{CTL_FS,A"fs",  Nt a, 0,,0555, xfs_dir_table},
+	{0}
+};p+p+vic 
+xfs_sysctl_regiscer(vic )
+{p+	xfs_table_H adISA= regiscer_sysctl_table(xfs_root_table, 1);p+}p+p+vic 
+xfs_sysctl_unregiscer(vic )
+{p+	if (xfs_table_H adIS)p+		unregiscer_sysctl_table(xfs_table_H adIS);p+}pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_sysctl.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_sysctl.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_sysctl.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_sysctl.h	2004-07-30 16:26:55.000000000 +0000
@@ -0,0 +1,112 @@
+4-
+68 Copyright (c) 2001-2004 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#ifndef __XFS_SYSCTL_H__
+# /home __XFS_SYSCTL_H__
+
+#include <linux/sysctl.h>
+
+4-
+68 Tunable xfs paramecers
+ -/
+
+Oypedef s,* Ok,xfs_sysctl_val {
+	int min;p+	int val;p+	int max;p+},xfs_sysctl_val_n;p+p+Oypedef s,* Ok,xfs_param {p+	xfs_sysctl_val_n refcacht_snit;E4-+Snit o++NFS refereiceAcacht.++++++8/
+	xfs_sysctl_val_n refcacht_purge;4-+# o++entriBs to(purge each ,Ime.++8/
+	xfs_sysctl_val_n restrict_chown;4-+Root/non-root can gIvt awayufiles.8/
+	xfs_sysctl_val_n sgi _inH rit;E4-+InH rit,S_ISGIDA(++process' GIDA(sp+				s 8+_tyAa member o++parent dir GID.+8/
+	xfs_sysctl_val_n symlink_mode;E4-+Ldnk creat mode affectt }by(umask+8/
+	xfs_sysctl_val_n panic_mask;E4-+bitmask+to(causeApanic onrerrors.+8/
+	xfs_sysctl_val_n error_level;E4- Deg/ho(o++reportiig forAproblems +8/
+	xfs_sysctl_val_n syncd_timer;E4-+Incerval between(xfssyncd wakeups+8/
+	xfs_sysctl_val_n stats_clear;E4-+R set( 2_ XFS s,atIsyics to(zero.+8/
+	xfs_sysctl_val_n inH rit_sync;E4-+InH rit,OH u"sync",inode fc l.+8/
+	xfs_sysctl_val_n inH rit_nod mp;4-+InH rit,OH u"nod mp",inode fc l.+8/
+	xfs_sysctl_val_n inH rit_noatIm;4-+InH rit,OH u"noatIme",inode fc l.+8/
+	xfs_sysctl_val_n xfs_buf_timer;E4-+Incerval between(xfsbufd wakeups.+8/
+	xfs_sysctl_val_n xfs_buf_age;E4-+Metadatafbuffer ageAbeforf flush.+8/
+},xfs_param_n;p+p+4-
+68 xfs_error_level:
+ -
+68 How much error reportiig will b  dome wHei2incernal problems are
+68 eicouinered.++TheseAproblems normally r dirt an EFSCORRUPTED Oo+OHeirp+f* ca2_er,+winv2noroOH rninformatISF reported.
+ -
+68 0	No error reports
+68 1	Report EFSCORRUPTED errors tHat(will causeAa filesystem deutdown
+68 5	Report  2_ EFSCORRUPTED errors ( 2_ o++OHeAabove(errors, plus any
+68	additISFal errors tHat(are known Oo+not causeAdeutdowns)p+ -
+68 xfs_panic_mask+bit 0x8 dirtonOHeAerror reports(intoApanics
+ -/
+
+enum {p+	XFS_REFCACHE_SIZE = 1,p+	XFS_REFCACHE_PURGE =o2,p+	XFS_RESTRICT_CHOWN =o3,p+	XFS_SGID_INHERIT =o4,p+	XFS_SYMLINK_MODE =o5,p+	XFS_PANIC_MASK =o6,p+	XFS_ERRLEVEa =o7,p+	XFS_SYNCD_TIMER =o8,p+	/* XFS_PROBE_DMAPI =o9+8/
+	/* XFS_PROBE_IOOPS = 10+8/
+	/* XFS_PROBE_QUOTA = 11+8/
+	XFS_STATS_CLEAR = 12,p+	XFS_INHERIT_SYNC = 13,p+	XFS_INHERIT_NODUMP = 14,p+	XFS_INHERIT_NOATIME = 15,p+	XFS_BUF_TIMER = 16,p+	XFS_BUF_AGE =o17,p+	/* XFS_IO_BYPASS = 18,+8/
+};p+p+extSrt xfs_param_n	xfs_params;
+
+#ifdef CONFIG_SYSCTLp+extSrt vic (xfs_sysctl_regiscer(vic );p+extSrt vic (xfs_sysctl_unregiscer(vic );p+#e_HWp+#  /home xfs_sysctl_regiscer()		do+{ } wHile (0)p+#  /home xfs_sysctl_unregiscer()	do+{ } wHile (0)p+#end(+ 4- CONFIG_SYSCTL -/
+
+#end(+ 4- __XFS_SYSCTL_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_versISF.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_versISF.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_versISF.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_versISF.h	2004-07-30 16:25:17.000000000 +0000
@@ -0,0 +1,44 @@
+4-
+68 Copyright (c) 2001-2002 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.	 Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+4-
+68 Dummyufile tHat(can contain a ,Imes,amp to(put(intoAOHe
+68 XFS init s,*iig, toAhelpnusers keep Orack o++wHatAOHey're
+68 running
+68/
+
+#ifndef __XFS_VERSION_H__
+# /home __XFS_VERSION_H__
+
+# /home XFS_VERSION_STRING "SGI XFS"
+
+#end(+ 4- __XFS_VERSION_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_vfs.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vfs.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_vfs.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vfs.c	2004-07-30 16:26:51.000000000 +0000
@@ -0,0 +1,328 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_macros.h"
+#include "xfs_inum.h"
+#include "xfs_log.h"
+#include "xfs_clnt.h"
+#include "xfs_Orans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_dir.h"
+#include "xfs_dir2.h"
+#include "xfs_imap.h"
+#include "xfs_a2_HW.h"
+#include "xfs_dmapi.h"
+#include "xfs_mouin.h"
+#include "xfs_quota.h"
+
+int
+vfs_mouin(
+	s,* Ok,bhv_descs	*bdp,
+	s,* Ok,xfs_mouin_args	*args,
+	s,* Ok,cred		*cr)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_m*/in)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_m*/in)(next,,args, cr));p+}p+p+int
+vfs_parseargs(
+	s,* Ok,bhv_descs	*bdp,
+	char			*s,
+	s,* Ok,xfs_mouin_args	*args,
+	int	s	f)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_parseargs)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_parseargs)(next,,s, args, f));p+}p+p+int
+vfs_showargs(
+	s,* Ok,bhv_descs	*bdp,
+	s,* Ok,seq_file		*m)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_showargs)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_showargs)(next,,m));p+}p+p+int
+vfs_unm*/in(
+	s,* Ok,bhv_descs	*bdp,
+	int	s	fl,
+	s,* Ok,cred		*cr)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_unm*/in)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_unm*/in)(next,,fl, cr));p+}p+p+int
+vfs_mntupdatt(
+	s,* Ok,bhv_descs	*bdp,
+	int	s	*fl,
+	s,* Ok,xfs_mouin_args	*args)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_mntupdatt)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_mntupdatt)(next,,fl, args));p+}p+p+int
+vfs_root(
+	s,* Ok,bhv_descs	*bdp,
+	s,* Ok,vnode		**vpp)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_root)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_root)(next,,vpp));p+}p+p+int
+vfs_s,atvfs(
+	s,* Ok,bhv_descs	*bdp,
+	xfs_statfs_,		*sp,
+	s,* Ok,vnode		*vp)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_s,atvfs)p+		next = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_s,atvfs)(next,,sp,,vp));p+}p+p+int
+vfs_sync(
+	s,* Ok,bhv_descs	*bdp,
+	int	s	fl,
+	s,* Ok,cred		*cr)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_sync)p+	snext = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_sync)(next,,fl, cr));p+}p+p+int
+vfs_vget(
+	s,* Ok,bhv_descs	*bdp,
+	s,* Ok,vnode		**vpp,
+	s,* Ok,fid		*fidp)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_vget)p+	snext = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_vget)(next,,vpp, fidp));p+}p+p+int
+vfs_dmapiops(
+	s,* Ok,bhv_descs	*bdp,
+	c ddr_t	s	 ddr)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_dmapiops)p+	snext = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_dmapiops)(next,,addr));p+}p+p+int
+vfs_quotactl(
+	s,* Ok,bhv_descs	*bdp,
+	int	s	cmd,
+	int	s	id,
+	c ddr_t	s	 ddr)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_quotactl)p+	snext = BHV_NEXT(next);p+	r dirt ((*bhvtovfsops(next)->vfs_quotactl)(next,,cmd, c , addr));p+}p+p+s,* Ok,inode -
+vfs_get_inode(
+	s,* Ok,bhv_descs	*bdp,
+	xfs_ino_n		ino,
+	int	s	fl)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	wHile (! (bhvtovfsops(next))->vfs_get_inode)p+	snext = BHV_NEXTNt a(next);p+	r dirt ((*bhvtovfsops(next)->vfs_get_inode)(next,,ino,,fl));p+}p+p+vic 
+vfs_init_vnode(
+	s,* Ok,bhv_descs	*bdp,
+	s,* Ok,vnode		*vp,
+	s,* Ok,bhv_descs	*bp,
+	int	s	un12B,)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_init_vnode)p+	snext = BHV_NEXT(next);p+	((*bhvtovfsops(next)->vfs_init_vnode)(next,,vp, bp, un12B,));p+}p+p+vic 
+vfs_force_shutdown(
+	s,* Ok,bhv_descs	*bdp,
+	int	s	fl,
+	char			*file,
+	int	s	line)p+{
+	s,* Ok,bhv_descs	*next = bdp;p+p+	ASSERT(next);p+	wHile (! (bhvtovfsops(next))->vfs_force_shutdown)p+	snext = BHV_NEXT(next);p+	((*bhvtovfsops(next)->vfs_force_shutdown)(next,,fl, file, line));p+}p+p+vfs_, *p+vfs_a2_HWate( vic ()p+{
+	s,* Ok,vfs		*vfsp;p+p+	vfsp = kmem_za2_HW(siztof(vfs_,), KM_SLEEP);p+	bhv_H ad_init(VFS_BHVHEAD(vfsp), "vfs");p+	init_waitqueue_H ad(&vfsp->vfs_wait_sync_task);p+	r dirt vfsp;p+}p+p+vic 
+vfs_dea2_HWate(
+	s,* Ok,vfs		*vfsp)p+{
+	bhv_H ad_des,*oy(VFS_BHVHEAD(vfsp));p+	kmem_f/ho(vfsp, siztof(vfs_,));p+}p+p+vic 
+vfs_insertops(
+	s,* Ok,vfs		*vfsp,
+	s,* Ok,bhv_vfsops	*vfsops)p+{
+	s,* Ok,bhv_descs	*bdp;p+p+	bdp = kmem_a2_HW(siztof(s,* Ok,bhv_desc), KM_SLEEP);p+	bhv_desc_init(bdp, Nt a, vfsp, vfsops);p+	bhv_insert(&vfsp->vfs_bh, bdp);p+}p+p+vic 
+vfs_insertbhv(
+	s,* Ok,vfs		*vfsp,
+	s,* Ok,bhv_descs	*bdp,
+	s,* Ok,vfsops		*vfsops,
+	vic s		*m*/in)p+{p+	bhv_desc_init(bdp, mo/in, vfsp, vfsops);p+	bhv_insert_initial(&vfsp->vfs_bh, bdp);p+}p+p+vic 
+bhv_r movt_vfsops(
+	s,* Ok,vfs		*vfsp,
+	int	s	pos)p+{
+	s,* Ok,bhv_descs	*bhv;p+p+	bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);p+Eif (!bhv)
+		r dirt;p+	bhv_r movt(&vfsp->vfs_bh, bhv);p+	kmem_f/ho(bhv, snitof(*bhv));p+}p+p+vic 
+bhv_r movt_a2__vfsops(
+	s,* Ok,vfs		*vfsp,
+	int	s	f/hobase)p+{
+	s,* Ok,xfs_mouin	*mp;p+p+	bhv_r movt_vfsops(vfsp, VFS_POSITION_QM);p+	bhv_r movt_vfsops(vfsp, VFS_POSITION_DM);p+Eif (!f/hobase)p+		r dirt;p+	mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops));p+EVFS_REMOVEBHV(vfsp, &mp->m_bhv);p+	xfs_mouin_f/ho(mp,,0);p+}p+p+vic 
+bhv_insert_a2__vfsops(
+	s,* Ok,vfs		*vfsp)p+{
+	s,* Ok,xfs_mouin	*mp;p+p+	mp = xfs_mouin_init();
+	vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
+	vfs_insertdmapi(vfsp);
+	vfs_insertquota(vfsp);p+}pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_vfs.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vfs.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_vfs.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vfs.h	2004-07-30 16:29:50.000000000 +0000
@@ -0,0 +1,208 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+#ifndef __XFS_VFS_H__
+# /home __XFS_VFS_H__
+
+#include <linux/vfs.h>p+#include "xfs_fs.h"
+p+s,* Ok,fid;p+s,* Ok,cred;p+s,* Ok,vnode;
+s,* Ok,statfs;
+s,* Ok,seq_file;
+s,* Ok,super_b12B,;
+s,* Ok,xfs_m*/in_args;p+p+Oypedef s,* Ok,statfs xfs_statfs_,;p+p+Oypedef s,* Ok,vfs {p+	u_int	s	vfs_flag;E4-++c ls 8/
+	xfs_fsc _,		vfs_fsc ;E4-++ile system ID 8/
+	xfs_fsc _,		*vfs_a2tfsc ;E4-+An ID fixed forAlifo(o++FS -/
+	bhv_H ad_,		vfs_bh;		4- H ad of vfs beigaiorAchain -/
+	s,* Ok,super_b12B,	*vfs_super;E4-+Ldnux,superb12B, s,* Okure -/
+	s,* Ok,task_s,* Ok	*vfs_sync_task;p+	wait_queue_H ad_t	vfs_wait_sync_task;p+},vfs_,;p+p+# /home vfs_fbhv		vfs_bh.bh_firstE4-+1st onrvfs beigaiorAchain -/
+p+# /home bhvtovfs(bdp)		( (s,* Ok,vfs *)BHV_VOBJ(bdp) )p+# /home bhvtovfsops(bdp)	( (s,* Ok,vfsops *)BHV_OPS(bdp) )p+# /home VFS_BHVHEAD(vfs)	( &(vfs)->vfs_bh )p+# /home VFS_REMOVEBHV(vfs, bdp)	( bhv_r movt(VFS_BHVHEAD(vfs), bdp) )
+p+# /home VFS_POSITION_BASE	BHV_POSITION_BASE	4-+chain bottomr-/
+# /home VFS_POSITION_TOP	BHV_POSITION_TOP	4-+chain topr-/
+# /home VFS_POSITION_INVALID	BHV_POSITION_INVALID	4-+invalid pos. num -/
+
+Oypedef enum {p+	VFS_BHV_UNKNOWN,	4-+_tyAspecifiBd -/
+	VFS_BHV_XFS,		4- xfs -/
+	VFS_BHV_DM,		4- datafmigratISF -/
+	VFS_BHV_QM,		4- quota managISA-/
+	VFS_BHV_IO,		4- IO panv2-/
+	VFS_BHV_END		4- Housekeepiig end-of-range+8/
+},vfs_bhv_,;p+p+# /home VFS_POSITION_XFS	(BHV_POSITION_BASE)p+# /home VFS_POSITION_DM		(VFS_POSITION_BASE+10)p+# /home VFS_POSITION_QM		(VFS_POSITION_BASE+20)p+# /home VFS_POSITION_IO		(VFS_POSITION_BASE+30)
+p+# /home VFS_RDONLY		0x0001	4- read-only vfs -/
+# /home VFS_GRPID		0x0002	4- group-ID assigted fromrdirectory -/
+# /home VFS_DMI			0x0004E4-++ilesystem haonOHeADMI,enabled -/
+# /home VFS_UMOUNT		0x0008E4-+unm*/in in2progress -/
+# /home VFS_END			0x0008E4-+max fc lf-/
+p+# /home SYNC_ATTR		0x0001	4- sync attributes -/
+# /home SYNC_CLOSE		0x0002	4- close++ile system down -/
+# /home SYNC_DELWRI		0x0004E4-+look at delayed w    s -/
+# /home SYNC_WAIT		0x0008E4-+wait forAi/o to(complete -/
+# /home SYNC_BDFLUSH		0x0010E4-+BDFLUSHndonca2_iig -- don't b12B, -/
+# /home SYNC_FSDATA		0x0020E4-++cush fs dataf(e.g.,superb12B,s) -/
+# /home SYNC_REFCACHE		0x0040  4- prume some o++OHeAnfs ref cacht 8/
+# /home SYNC_REMOUNT		0x0080  4- remo/in readonly,2nordummyuLRsf-/
+p+# /home IGET_NOALLOC		0x0001	4- vfs_get_inode+may r dirt Nt a -/
+
+Oypedef int	(*vfs_m*/in_t)(bhv_desc_t *,
+				s,* Ok,xfs_m*/in_args *,,s,* Ok,cred *);p+Oypedef int	(*vfs_parseargs_t)(bhv_desc_t *, char *,p+				s,* Ok,xfs_m*/in_args *,,int);p+Oypedef	int	(*vfs_showargs_t)(bhv_desc_t *, s,* Ok,seq_file *);p+Oypedef int	(*vfs_unm*/in_t)(bhv_desc_t *, iin, s,* Ok,cred *);p+Oypedef int	(*vfs_mntupdatt_t)(bhv_desc_t *, iin *,p+				s,* Ok,xfs_m*/in_args *);p+Oypedef int	(*vfs_root_t)(bhv_desc_t *, s,* Ok,vnode -*);p+Oypedef int	(*vfs_s,atvfs_t)(bhv_desc_t *, xfs_statfs_, *, s,* Ok,vnode -);p+Oypedef int	(*vfs_sync_t)(bhv_desc_t *, iin, s,* Ok,cred *);p+Oypedef int	(*vfs_vget_t)(bhv_desc_t *, s,* Ok,vnode -*, s,* Ok,fid *);p+Oypedef int	(*vfs_dmapiops_t)(bhv_desc_t *, c ddr_t);p+Oypedef int	(*vfs_quotactl_t)(bhv_desc_t *, iin, iin, c ddr_t);p+Oypedef vic s(*vfs_init_vnode_t)(bhv_desc_t *,
+				s,* Ok,vnode -, bhv_desc_t *,,int);p+Oypedef vic s(*vfs_force_shutdown_t)(bhv_desc_t *, iin, char *,,int);p+Oypedef	s,* Ok,inode - (*vfs_get_inode_t)(bhv_desc_t *, xfs_ino_n, int);p+p+Oypedef s,* Ok,vfsops {p+	bhv_positISF_,		vf_positISF;E4-+beigaiorAchain positISF2-/
+	vfs_m*/in_t		vfs_m*/in;E4-+mo/in +ile system -/
+	vfs_parseargs_t		vfs_parseargs;E4-+parse+mo/in optISFs -/
+	vfs_showargs_t		vfs_showargs;E4-+unparse+mo/in optISFs -/
+	vfs_unm*/in_t		vfs_unm*/in;E4-+unm*/in +ile system -/
+	vfs_mntupdatt_t		vfs_mntupdatt;E4-+updatt +ile system optISFs -/
+	vfs_root_t		vfs_root;E4-+get root vnode -/
+	vfs_s,atvfs_t		vfs_s,atvfs;E4-++ile system s,atIsyics -/
+	vfs_sync_t		vfs_sync;E4-++cush files -/
+	vfs_vget_t		vfs_vget;E4-+get vnode fromrfid */
+	vfs_dmapiops_t		vfs_dmapiops;	4- datafmigratISF -/
+	vfs_quotactl_t		vfs_quotactl;	4- disk quota -/
+	vfs_get_inode_t		vfs_get_inode;E4-+bhvAspecific iget -/
+	vfs_init_vnode_t	vfs_init_vnode;	4-+initializt a new vnode -/
+	vfs_force_shutdown_t	vfs_force_shutdown;	4-+crash and birt 8/
+},vfsops_t;
+
+4-
+68 VFS's.  OperatBs on vfs s,* Okure poincers (s,arts(ak,bhv H ad).
+ -/
+# /home VHEAD(v)			((v)->vfs_fbhv)
+# /home VFS_MOUNT(v,+ma,cr, rv)		((rv) = vfs_mouin(VHEAD(v),+ma,cr))p+# /home VFS_PARSEARGS(v,+o,ma,f, rv)	((rv) = vfs_parseargs(VHEAD(v),+o,ma,f))p+# /home VFS_SHOWARGS(v,+m, rv)		((rv) = vfs_showargs(VHEAD(v),+m))p+# /home VFS_UNMOUNT(v,+f, cr, rv)	((rv) = vfs_unm*/in(VHEAD(v),+f,cr))p+# /home VFS_MNTUPDATE(v,+fl, args, rv)	((rv) = vfs_mntupdatt(VHEAD(v),+fl, args))p+# /home VFS_ROOT(v,+vpp, rv)		((rv) = vfs_root(VHEAD(v),+vpp))p+# /home VFS_STATVFS(v,,sp,vp, rv)	((rv) = vfs_s,atvfs(VHEAD(v),+sp,vp))p+# /home VFS_SYNC(v,+flag,cr, rv)	((rv) = vfs_sync(VHEAD(v),+flag,cr))p+# /home VFS_VGET(v,+vpp,fidp, rv)	((rv) = vfs_vget(VHEAD(v),+vpp,fidp))
+# /home VFS_DMAPIOPS(v,+p, rv)		((rv) = vfs_dmapiops(VHEAD(v),+p))
+# /home VFS_QUOTACTL(v,+c,id,p, rv)	((rv) = vfs_quotactl(VHEAD(v),+c,id,p))
+# /home VFS_GET_INODE(v,+ino,,fl)	( vfs_get_inode(VHEAD(v),+ino,fl) )p+# /home VFS_INIT_VNODE(v,+vp,b,ul)	( vfs_init_vnode(VHEAD(v),+vp,b,ul) )p+# /home VFS_FORCE_SHUTDOWN(v,+fl,f,l)	( vfs_force_shutdown(VHEAD(v),+fl,f,l) )
+p+4-
+68 PVFS's.  OperatBs on beigaiorAdescriptorApoincers.
+ -/
+# /home PVFS_MOUNT(b,+ma,cr, rv)	((rv) = vfs_mouin(b,+ma,cr))p+# /home PVFS_PARSEARGS(b,+o,ma,f, rv)	((rv) = vfs_parseargs(b,+o,ma,f))p+# /home PVFS_SHOWARGS(b,+m, rv)		((rv) = vfs_showargs(b,+m))p+# /home PVFS_UNMOUNT(b,+f,cr, rv)	((rv) = vfs_unm*/in(b,+f,cr))p+# /home PVFS_MNTUPDATE(b,+fl, args, rv)	((rv) = vfs_mntupdatt(b,+fl, args))p+# /home PVFS_ROOT(b,+vpp, rv)		((rv) = vfs_root(b,+vpp))p+# /home PVFS_STATVFS(b,,sp,vp, rv)	((rv) = vfs_s,atvfs(b,+sp,vp))p+# /home PVFS_SYNC(b,+flag,cr, rv)	((rv) = vfs_sync(b,+flag,cr))p+# /home PVFS_VGET(b,+vpp,fidp, rv)	((rv) = vfs_vget(b,+vpp,fidp))
+# /home PVFS_DMAPIOPS(b,+p, rv)		((rv) = vfs_dmapiops(b,+p))
+# /home PVFS_QUOTACTL(b,+c,id,p, rv)	((rv) = vfs_quotactl(b,+c,id,p))
+# /home PVFS_GET_INODE(b,+ino,fl)	( vfs_get_inode(b,+ino,fl) )p+# /home PVFS_INIT_VNODE(b,+vp,b2,ul)	( vfs_init_vnode(b,+vp,b2,ul) )p+# /home PVFS_FORCE_SHUTDOWN(b,+fl,f,l)	( vfs_force_shutdown(b,+fl,f,l) )
+p+extSrt iny vfs_mouin(bhv_desc_t *, s,* Ok,xfs_m*/in_args *,,s,* Ok,cred *);p+extSrt iny vfs_parseargs(bhv_desc_t *, char *, s,* Ok,xfs_m*/in_args *,,int);p+extSrt iny vfs_showargs(bhv_desc_t *, s,* Ok,seq_file *);p+extSrt iny vfs_unm*/in(bhv_desc_t *, iin, s,* Ok,cred *);p+extSrt iny vfs_mntupdatt(bhv_desc_t *, iin *, s,* Ok,xfs_m*/in_args *);p+extSrt iny vfs_root(bhv_desc_t *, s,* Ok,vnode -*);p+extSrt iny vfs_s,atvfs(bhv_desc_t *, xfs_statfs_, *, s,* Ok,vnode -);p+extSrt iny vfs_sync(bhv_desc_t *, iin, s,* Ok,cred *);p+extSrt iny vfs_vget(bhv_desc_t *, s,* Ok,vnode -*, s,* Ok,fid *);p+extSrt iny vfs_dmapiops(bhv_desc_t *, c ddr_t);p+extSrt iny vfs_quotactl(bhv_desc_t *, iin, iin, c ddr_t);p+extSrt s,* Ok,inode -vfs_get_inode(bhv_desc_t *,,xfs_ino_n, int);p+extSrt vic (vfs_init_vnode(bhv_desc_t *, s,* Ok,vnode -, bhv_desc_t *,,int);p+extSrt vic (vfs_force_shutdown(bhv_desc_t *, iin, char *,,int);p+p+Oypedef s,* Ok,bhv_vfsops {
+	s,* Ok,vfsops		bhv_commot;p+	vic (*			bhv_custom;p+},bhv_vfsops_,;p+p+# /home vfs_bhv_lookup(v,+id)	( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) )p+# /home vfs_bhv_custom(b)	( ((bhv_vfsops_, *)BHV_OPS(b))->bhv_custom )p+# /home vfs_bhv_set_custom(b,o)	( (b)->bhv_custom = (vic (*)(o))p+# /home vfs_bhv_clr_custom(b)	( (b)->bhv_custom = Nt a )
+p+extSrt vfs_, *vfs_a2_HWate(vic );p+extSrt vic (vfs_dea2_HWate(vfs_, *);p+extSrt vic (vfs_insertops(vfs_t *, bhv_vfsops_, *);p+extSrt vic (vfs_insertbhv(vfs_t *, bhv_desc_t *,,vfsops_, *, vic (*);p+
+extSrt vic (bhv_insert_a2__vfsops(s,* Ok,vfs *);
+extSrt vic (bhv_r movt_a2__vfsops(s,* Ok,vfs *,,int);p+extSrt vic (bhv_r movt_vfsops(s,* Ok,vfs *,,int);p+p+#end(+	4- __XFS_VFS_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_vnode.c linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vnode.c
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_vnode.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vnode.c	2004-07-30 16:29:45.000000000 +0000
@@ -0,0 +1,455 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -/
+
+#include "xfs.h"
+
+
+udlt64_k,vn_generatISF;E	4- vnode generatISF numbISA-/
+spin12B,_k,vnumbIS_12B, = SPIN_LOCK_UNLOCKED;
+
+4-
+68 DediWated vnode inactIvt/reclaim sync semaphores.
+ - Prime numbISAo++hash buckets siiceA ddress donused aonOHeAkey.
+ -/
+# /home NVSYNC                  37p+# /home vptosync(v)             (&vsync[((unsigted long)v) % NVSYNC])
+sv_k,vsync[NVSYNC];
+
+4-
+68 Translatt stat(2)ufile types to(vnode types and vice versa.
+ - Aware o++numeric ordISAo++S_IFMT and vnode type values.
+ -/
+enum vtype iftovt_tab[]f= {p+EVNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,p+EVREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
+};p+p+u_shork,vttoif_tab[]f= {p+E0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 0, S_IFSOCK
+};p+p+p+vic 
+vn_init(vic )
+{p+	regiscer sv_k,*svp;p+	regiscer iny i;p+p+	forA(svp = vsync,+( =+0;+( < NVSYNC;+(++, svp++)p+		init_sv(svp, SV_DEFAULT, "vsy",+();p+}p+p+4-
+68 Clean a vnode o+++ilesystem-specific datafand preparendt forAreuse.
+ -/
+STATIC iny
+vn_reclaim(
+	s,* Ok,vnode	*vp)p+{
+	int	serror;p+p+	XFS_STATS_INC(vn_reclaim);
+	vn_Orace_entry(vp, "vn_reclaim", (inst_, *)__r dirt_ ddress);p+p+	4-
+s 8+Only mak  OH uVOP_RECLAIMnca2_A(++tH renarenbeigaiors
+s 8+to(call.
+s 8/p+Eif (vp->v_fbhv)o{p+	sVOP_RECLAIM(vp, error);
+	Eif (error)
+			r dirt -error;p+	}
+	ASSERT(vp->v_fbhv == Nt a);p+p+	VN_LOCK(vp);
+	vp->v_fc lf&= (VRECLM|VWAIT);p+EVN_UNLOCK(vp, 0);p+p+	vp->v_type = VNON;
+	vp->v_fbhv = Nt a;
+
+#ifdef XFS_VNODE_TRACEp+	kOrace_f/ho(vp->v_trace);
+	vp->v_trace = Nt a;
+#end(+
+p+	r dirt 0;p+}p+p+STATIC vic 
+vn_wakeup(
+	s,* Ok,vnode	*vp)p+{
+	VN_LOCK(vp);
+	if (vp->v_fc lf& VWAIT)
+		sv_broadcast(vptosync(vp));p+	vp->v_fc lf&= ~(VRECLM|VWAIT|VMODIFIED);p+EVN_UNLOCK(vp, 0);p+}p+p+int
+vn_wait(
+	s,* Ok,vnode	*vp)p+{
+	VN_LOCK(vp);
+	if (vp->v_fc lf& (VINACT | VRECLM))o{p+	svp->v_fc lf|= VWAIT;
+		sv_wait(vptosync(vp), PINOD, &vp->v_12B,, 0);p+		r dirt 1;p+	}
+	VN_UNLOCK(vp, 0);p+	r dirt 0;p+}p+p+s,* Ok,vnode -
+vn_initializt(
+	s,* Ok,inode	*inode)p+{
+	s,* Ok,vnode	*vp = LINVFS_GET_VP(inode);p+p+	XFS_STATS_INC(vn_actIvt);p+	XFS_STATS_INC(vn_a2_HW);p+p+	vp->v_fc lf= VMODIFIED;p+	spin12B,_init(&vp->v_12B,, "v_12B,");p+p+	spin_12B,(&vnumbIS_12B,);p+Eif (!++vn_generatISF)	4- v_numbISAdeGuldn't be(zero 8/
+		vn_generatISF++;p+	vp->v_numbISA=,vn_generatISF;p+	spin_un12B,(&vnumbIS_12B,);p+
+	ASSERT(VN_CACHED(vp) == 0);p+p+	4- Initializt OH ufirst beigaiorAand OH ubeigaiorAchain H ad.+8/
+	vn_bhv_H ad_init(VN_BHV_HEAD(vp), "vnode");p+p+#ifdef	XFS_VNODE_TRACEp+	vp->v_trace = kOrace_a2_HW(VNODE_TRACE_SIZE, KM_SLEEP);p+	prdltk("A2_HWated VNODE_TRACE(ak,0x%p\n", vp->v_trace);
+#end(+	4- XFS_VNODE_TRACE -/
+
+	vn_Orace_exit(vp, "vn_initializt", (inst_, *)__r dirt_ ddress);p+	r dirt vp;p+}p+p+4-
+68 Get(  refereiceAon a vnode.
+ -/
+vnode_t -
+vn_get(
+	s,* Ok,vnode	*vp,
+	vmap_,		*vmap)p+{
+	s,* Ok,inode	*inode;p+p+	XFS_STATS_INC(vn_get);p+Einode = LINVFS_GET_IP(vp);
+	if (inode->i_statef& I_FREEING)p+		r dirt Nt a;
+
+Einode = VFS_GET_INODE(vmap->v_vfsp, vmap->v_ino,,IGET_NOALLOC);p+Eif (!inode)	4- Inode _tyApresent 8/
+		r dirt Nt a;
+
+E4- We do+_tyAwant+to(create new inodes via,vn_get,
+s 8+r dirtiig Nt a H rendonOK.
+s 8/p+Eif (inode->i_statef& I_NEW)o{p+	sr movt_inode_hash(inode);p+		mak _bad_inode(inode);p+		un12B,_new_inode(inode);p+		iput(inode);p+		r dirt Nt a;
+	}
+p+	vn_Orace_exit(vp, "vn_get", (inst_, *)__r dirt_ ddress);p+p+	r dirt vp;p+}p+p+4-
+68 Revalida   OH uLdnux,inode fromrOH uvnode.
+ -/
+iny
+vn_revalida  (
+	s,* Ok,vnode	*vp)p+{
+	s,* Ok,inode	*inode;p+	vattr_t		va;
+	int	serror;p+p+	vn_Orace_entry(vp, "vn_revalida  ", (inst_, *)__r dirt_ ddress);p+	ASSERT(vp->v_fbhv != Nt a);p+p+	va.va_mask+= XFS_AT_STAT|XFS_AT_XFLAGS;p+EVOP_GETATTR(vp, &va, 0, Nt a, error);
+	if (!error)o{p+	sinode = LINVFS_GET_IP(vp);
+		inode->i_mode	    = VTTOIF(va.va_type) | va.va_mode;p+		inode->i_nlink	    = va.va_nlink;p+		inode->i_uid	    = va.va_uid;p+		inode->i_gid	    = va.va_gid;p+		i_snit_w    (inode, va.va_snit);
+		inode->i_b12B,s	    = va.va_nb12B,s;
+		inode->i_m,Ime	    = va.va_m,Ime.tv_sec;
+		inode->i_c,Ime	    = va.va_c,Ime.tv_sec;
+		inode->i_a,Ime	    = va.va_a,Ime.tv_sec;
+		if (va.va_x+c ls & XFS_XFLAG_IMMUTABLE)
+			inode->i_+c ls |= S_IMMUTABLE;
+		e_HWp+			inode->i_+c ls &= ~S_IMMUTABLE;
+		if (va.va_x+c ls & XFS_XFLAG_APPEND)
+			inode->i_+c ls |= S_APPEND;
+		e_HWp+			inode->i_+c ls &= ~S_APPEND;
+		if (va.va_x+c ls & XFS_XFLAG_SYNC)
+			inode->i_+c ls |= S_SYNC;
+		e_HWp+			inode->i_+c ls &= ~S_SYNC;
+		if (va.va_x+c ls & XFS_XFLAG_NOATIME)
+			inode->i_+c ls |= S_NOATIME;
+		e_HWp+			inode->i_+c ls &= ~S_NOATIME;
+p+	sVUNMODIFY(vp);
+	}p+	r dirt -error;p+}p+p+4-
+68 purge a vnode fromrOH ucacht
+ - At2OHdonpoincrOH uvnodendonguaranteed toAhgaf no refereices (vn_couin == 0)
+68 THe ca2_er haonOo mak  sure tHatAOHerenarenno ways someome cGuld
+68 get(  igndle (via,vn_get)Aon OH uvnoden(usually dome via,a+mo/in/vfs 12B,).
+ -/
+vic 
+vn_purge(
+	s,* Ok,vnode	*vp,
+	vmap_,		*vmap)p+{
+	vn_Orace_entry(vp, "vn_purge", (inst_, *)__r dirt_ ddress);p+p+again:p+	4-
+s 8+Check wheOH rnvp haonalreadyubeeF reclaimed siiceAour ca2_er
+s 8+sampled its versISF wHile holdiig a filesystem cacht 12B, tHat
+s 8+its VOP_RECLAIMnfunctISF acquires.
+s 8/p+EVN_LOCK(vp);
+	if (vp->v_numbISA!= vmap->v_numbIS)o{p+	sVN_UNLOCK(vp, 0);p+		r dirt;p+	}p+p+	4-
+s 8+Ifnvp is beiig reclaimed orAinactIvated,+wait /inil(itiisAinert,
+s 8+tHei2proceed.++Can't assume tHatAvnodendonactually r claimed
+s 8+just becauseAOHeAreclaimed fc lfdonasserted -- a vn_a2_HW
+s 8+r claim can fail.
+s 8/p+Eif (vp->v_fc lf& (VINACT | VRECLM))o{p+	sASSERT(vn_couin(vp) == 0);p+	svp->v_fc lf|= VWAIT;
+		sv_wait(vptosync(vp), PINOD, &vp->v_12B,, 0);p+		goOo again;p+	}p+p+	4-
+s 8+AnoOH rnprocess cGuld igaf raced in2and goOtei2OHdonvnode...
+s 8/p+Eif (vn_couin(vp) > 0)o{p+	sVN_UNLOCK(vp, 0);p+		r dirt;p+	}p+p+	XFS_STATS_DEC(vn_actIvt);p+	vp->v_fc lf|= VRECLM;p+EVN_UNLOCK(vp, 0);p+p+	4-
+s 8+Ca2_AVOP_RECLAIMnand clean vp. THe FSYNC_INVAL fc lftells
+s 8+vp's filesystem Oo +cush and invalida   all cacht }resources.
+s 8 WHei2vn_reclaim+r dirts, vp deGuld igaf no prdvate data,
+s 8+eiOHer in a system cacht orAattacht }to(v_data.
+s 8/p+Eif (vn_reclaim(vp) != 0)
+		panic("vn_purge: can_tyAreclaim");p+p+	4-
+s 8+Wakeup anyome waitiig forAvp to(beAreclaimed.
+s 8/p+Evn_wakeup(vp);p+}p+p+4-
+68 Add(  refereiceAOo a refereiceduvnode.
+ -/
+s,* Ok,vnode -
+vn_hold(
+	s,* Ok,vnode	*vp)p+{
+	s,* Ok,inode	*inode;p+p+	XFS_STATS_INC(vn_hold);p+p+	VN_LOCK(vp);
+	inode = igrab(LINVFS_GET_IP(vp));p+	ASSERT(inode);p+	VN_UNLOCK(vp, 0);p+p+	r dirt vp;p+}p+p+4-
+68 +Ca2_AVOP_INACTIVEAon last refereice.
+ -/
+vic 
+vn_rel (
+	s,* Ok,vnode	*vp)p+{
+	int	svcnt;
+	int	scacht;p+p+	XFS_STATS_INC(vn_rele);p+p+	VN_LOCK(vp);
+p+	vn_Orace_entry(vp, "vn_rel ", (inst_, *)__r dirt_ ddress);p+	vcntA=,vn_couin(vp);p+p+	4-
+s 8+SiiceAw  always get(ca2_ed fromrput_inode+we know
+s 8+tHat(i_couin won't be(decremSnted afcer we
+s 8+r dirt.
+s 8/p+Eif (!vcnt)o{p+	s4-
+ss 8+As soSF as+we dirt OHdonSF, noome can find usAin,vn_get
+ss 8+/inil(we dirt off VINACT orAVRECLM
+ss 8/p+	svp->v_fc lf|= VINACT;p+	sVN_UNLOCK(vp, 0);p+p+	s4-
+ss 8+Do+_tyAmak  OH uVOP_INACTIVEAca2_A(++tH re
+ss 8+arenno beigaiorsAattacht }to(OH uvnodento(call.
+ss 8/p+	sif (vp->v_fbhv)p+			VOP_INACTIVE(vp, Nt a, cacht);p+p+	sVN_LOCK(vp);
+		if (vp->v_fc lf& VWAIT)
+			sv_broadcast(vptosync(vp));p+p+	svp->v_fc lf&= ~(VINACT|VWAIT|VRECLM|VMODIFIED);p+E}p+p+	VN_UNLOCK(vp, 0);p+p+	vn_Orace_exit(vp, "vn_rel ", (inst_, *)__r dirt_ ddress);p+}p+p+4-
+68 FinishAOHeAremoval Sf(a vnode.
+ -/
+vic 
+vn_removt(
+	s,* Ok,vnode	*vp)p+{
+	vmap_,		vmap;
+
+E4- Mak  sure we don't do+OHdonto(OH usam uvnodentwice 8/p+Eif (!(vp->v_fbhv))p+		r dirt;p+p+	XFS_STATS_INC(vn_removt);
+	vn_Orace_exit(vp, "vn_removt", (inst_, *)__r dirt_ ddress);p+p+	4-
+s 8+Afcer OH ufo2_Hwiig purge OH uvnode
+s 8+will no longer exist.
+s 8/p+EVMAP(vp, vmap);
+	vn_purge(vp, &vmap);
+}p+p+p+#ifdef	XFS_VNODE_TRACEp+p+# /home KTRACE_ENTER(vp, vk,,s, line, ra)			\
+	kOrace_Snter(	(vp)->v_trace,				\
+4-  0+8/		(vic (*)(__psiit_t)(vk),		\
+4-  1+8/		(vic (*)(s),				\
+4-  2+8/		(vic (*)(__psiit_t) line,		\
+4-  3+8/		(vic (*)(vn_couin(vp)), \
+4-  4+8/		(vic (*)(ra),				\
+4-  5+8/		(vic (*)(__psunsigted_t)(vp)->v_flag,	\
+4-  6+8/		(vic (*)(__psiit_t)smp_processor_id(),	\
+4-  7+8/		(vic (*)(__psiit_t)(current->pid),	\
+4-  8+8/		(vic (*)__r dirt_ ddress,		\
+4-  9+8/		0, 0, 0, 0, 0, 0, 0)
+p+4-
+68 Vnodentraciig code.
+ -/
+vic 
+vn_Orace_entry(vnode_t -vp, char *func,,inst_, *ra)p+{
+	KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func,,0, ra);p+}p+p+vic 
+vn_Orace_exit(vnode_t -vp, char *func,,inst_, *ra)p+{
+	KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func,,0, ra);p+}p+p+vic 
+vn_Orace_hold(vnode_t -vp, char *file, int line,,inst_, *ra)p+{
+	KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);p+}p+p+vic 
+vn_Orace_ref(vnode_t -vp, char *file, int line,,inst_, *ra)p+{
+	KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);p+}p+p+vic 
+vn_Orace_rel (vnode_t -vp, char *file, int line,,inst_, *ra)p+{
+	KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);p+}p+#end(+	4- XFS_VNODE_TRACE -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/linux-2.4/xfs_vnode.h linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vnode.h
--- linux-2.4.26/fs/xfs/linux-2.4/xfs_vnode.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/linux-2.4/xfs_vnode.h	2004-07-30 16:30:53.000000000 +0000
@@ -0,0 +1,650 @@
+4-
+68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ -
+68 THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
+68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
+68 publisht }by(OH uF/ho(Software FouidatISF.p+ -
+68 THdonprogramndondistributed in2OHeAhopf tHat(itiwGuld benuseful, but
+68+WITHOUT ANY WARRANTY; winvout evei2OHeAimpliBd warranty of
+68+MERCHANTABILITY(or-FITNESS FOR A PARTICULAR PURPOSE.p+ -
+68 FurOHer,+tHdonsoftwarendondistributed winvout any warranty tHat(itiis
+68 +/ho(o++OHeArightful claim Sf(anyrOHdrd persSF regardiig infrdlgemSnt
+68 oSAOHeAloke.  Any licenseAprovided H rein, wheOH rnimpliBd orp+f* oOH rwise, appliBs only Oo+OHdonsoftwaren.ile.  Patent licenses,+(+
+68( ny, provided H rein do+_tyAapply to(combinatISFs(o++OHdonprogramnwinvp+f* oOH rnsoftware, or anyroOH rnprod Ok,wHatsoever.p+ -
+68 You deGuld igaf received a(copy o++OHeAGNU General Public LicenseAalong
+68 winv2OHdonprogram;A(++_ty, w     OH uF/ho(Software FouidatISF, Inc., 59
+68 Temple Place - Su    330, Boston MA 02111-1307, USA.p+ -
+68 Ctrtact informatISF: Silicon Graphics, Inc., 1600 AmphiOH atre Pkwy,
+68+Mouinain View, CA  94043, or:
+ -
+68 http://www.sgi.comp+ -
+68 For +urOHer informatISF regardiig OHdon_tyice, see:
+ -
+68 http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
+ -
+ - PortISFs(Copyright (c) 1989, 1993
+ -	THe Regents o++OHeAUniversIty of+Ca2ifornia.  All rights r served.
+ -
+68 RedistributISF and use in source and binary forms, winv2or winvout
+68 modifiWatISF, are permitted provided tHatAOHeufo2_Hwiig conditISFs
+68 are met:
+ - 1. RedistributISFs o++source code+must renain OHeuabovt(copyright
+68 + n_tyice, OHdonlist o++conditISFsAand OH ufo2_Hwiig disclaimer.p+ - 2. RedistributISFs in binary form+must reprod Oe OHeuabovt(copyright
+68 + n_tyice, OHdonlist o++conditISFsAand OH ufo2_Hwiig disclaimer in2OHe
+68 + ndocumSntatISF and/or-oOH rnmaterials provided winv2OHe distributISF.p+ - 3. NeiOHer OHeAname o++OHeAUniversIty nor OHeAnames o++its contributors
+68 + nmay benuse }to(endorse+ornpromotenprod Okonderived fromrOHdonsoftware
+68 + nwinvout specific priorAw   tei2permissISF.p+ -
+68 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+68 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+68 IMPLIED WARRANTIES OF+MERCHANTABILITY(AND FITNESS FOR A PARTICULAR PURPOSE
+68 ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+68 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+68 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS
+68 OR SERVICES; LOSS OF+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+68 HOWEVER CAUSED(AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT
+68 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+68 OUT OF+THE USE OF+THIS SOFTWARE, EVEN IF ADVISED(OF+THE POSSIBILITY(OF
+68 SUCH DAMAGE.
+ -/
+#ifndef __XFS_VNODE_H__
+# /home __XFS_VNODE_H__
+
+s,* Ok,uio;p+s,* Ok,file;
+s,* Ok,vattr;
+s,* Ok,xfs_iomap;
+s,* Ok,attrlist_cursor_kert;p+p+4-
+68 Vnodentypes.  VNON meanon_tntype.
+ -/
+enum vtype	{ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VFIFO, VBAD, VSOCK };p+p+Oypedef xfs_ino_n,vnumbIS_t;
+Oypedef s,* Ok,dentry,vname_t;
+Oypedef bhv_H ad_, vn_bhv_H ad_t;
+
+4-
+68 MP 12B,iig protocols:
+ -	v_flag, v_vfsp				VN_LOCK/VN_UNLOCK
+ -	v_type					r ad-only or +s-dependSnt
+68/p+Oypedef s,* Ok,vnoden{
+	__u32		v_flag;	E	4- vnode +c ls (see be_Hw) -/
+	enum vtype	v_type;	E	4- vnode type -/
+	s,* Ok,vfs	*v_vfsp;E	4- ptr to(coinainiig VFS -/
+	vnumbIS_t	v_numbIS;E	4- in-cor uvnodennumbISA-/
+	vn_bhv_H ad_t	v_bh;		E4-+beigaiorAH ad -/
+	spin12B,_k	v_12B,;		E4-+VN_LOCK/VN_UNLOCK -/
+	s,* Ok,inode	v_inode;EE4-+Ldnux,inode -/
+#ifdef XFS_VNODE_TRACEp+	s,* Ok,kOrace	*v_Orace;EE4-+trace H ad rns,* Okure    -/
+#end(+
+} vnode_t;p+p+# /home v_fbhv			v_bh.bh_firstE       4-++irst beigaiorA-/
+# /home v_fops			v_bh.bh_first->bd_ops  4-++irst beigaiorAops */
+p+# /home VNODE_POSITION_BASE	BHV_POSITION_BASE	4-+chain bottomr-/
+# /home VNODE_POSITION_TOP	BHV_POSITION_TOP	4-+chain topr-/
+# /home VNODE_POSITION_INVALID	BHV_POSITION_INVALID	4-+invalid pos. num -/
+
+Oypedef enum {p+	VN_BHV_UNKNOWN,		4-+_tyAspecifiBd -/
+	VN_BHV_XFS,		4- xfs -/
+	VN_BHV_DM,		4- datafmigratISF -/
+	VN_BHV_QM,		4- quota managISA-/
+	VN_BHV_IO,		4- IO panv2-/
+	VN_BHV_END		4- Housekeepiig end-of-range+8/
+},vn_bhv_,;p+p+# /home VNODE_POSITION_XFS	(VNODE_POSITION_BASE)p+# /home VNODE_POSITION_DM	(VNODE_POSITION_BASE+10)p+# /home VNODE_POSITION_QM	(VNODE_POSITION_BASE+20)p+# /home VNODE_POSITION_IO	(VNODE_POSITION_BASE+30)
+p+4-
+68 Macros forAdea2iig winv2OHe beigaiorAdescriptorAinside o++OHeAvnode.
+ -/
+# /home BHV_TO_VNODE(bdp)	((vnode_t -)BHV_VOBJ(bdp))
+# /home BHV_TO_VNODE_Nt a(bdp)	((vnode_t -)BHV_VOBJNt a(bdp))
+p+# /home VN_BHV_HEAD(vp)			((bhv_H ad_, *)(&((vp)->v_bh)))p+# /home vn_bhv_H ad_init(bhp,name)	bhv_H ad_init(bhp,name)p+# /home vn_bhv_removt(bhp,bdp)		bhv_removt(bhp,bdp)p+# /home vn_bhv_lookup(bhp,ops)		bhv_lookup(bhp,ops)p+# /home vn_bhv_lookup_un12B,ed(bhp,ops) bhv_lookup_un12B,ed(bhp,ops)p+p+4-
+68 Vnodento+Ldnux,inode mappiig.
+ -/
+# /home LINVFS_GET_VP(inode)	((vnode_t -)list_entry(inode, vnode_t, v_inode))
+# /home LINVFS_GET_IP(vp)	(&(vp)->v_inode)p+
+4-
+68 Convert betweei2vnode types and inode formats (siiceAPOSIX.1
+68  /homes mode word of statns,* Okure in terms of inode formats).
+ -/
+extSrt enum vtype	iftovt_tab[];
+extSrt u_shork		vttoif_tab[];p+# /home IFTOVT(mode)	(iftovt_tab[((mode) &+S_IFMT) >> 12])p+# /home VTTOIF(indx)	(vttoif_tab[(int)(indx)])p+# /home MAKEIMODE(indx, mode)	(int)(VTTOIF(indx) | (mode))p+p+p+4-
+68 Vnoden+c ls.
+ -/
+# /home VINACT	E       0x1	4- vnode is beiig inactIvated	-/
+# /home VRECLM	E       0x2	4- vnode is beiig reclaimed	-/
+# /home VWAIT		       0x4E4-+waitiig forAVINACT/VRECLM}to(end -/
+# /home VMODIFIED	       0x8	4- XFS inode statefpossibly differs 8/p+	s		E4-+to(OH uLdnux,inode state.	-/
+
+4-
+68 Values forAOH uVOP_RWLOCK and VOP_RWUNLOCK +c ls parameter.p+ -/
+Oypedef enum vrw12B, {p+	VRWLOCK_NONE,p+	VRWLOCK_READ,p+	VRWLOCK_WRITE,p+	VRWLOCK_WRITE_DIRECT,p+	VRWLOCK_TRY_READ,p+	VRWLOCK_TRY_WRITE
+},vrw12B,_t;
+
+4-
+68 R dirt values forAVOP_INACTIVE.  A r dirt value of
+68+VN_INACTIVE_NOCACHEnimpliBs tHatAOHeufile system beigaior
+68 haondisassociated its statefand bhv_desc_t fromrOH uvnode.
+ -/
+# /home	VN_INACTIVE_CACHE	0
+# /home	VN_INACTIVE_NOCACHE	1
+
+4-
+68 Values forAOH ucmd code+givei2OoAVOP_VNODE_CHANGE.
+ -/
+Oypedef enum vchange+{p+	VCHANGE_FLAGS_FRLOCKS		= 0,p+	VCHANGE_FLAGS_ENF_LOCKING	= 1,p+	VCHANGE_FLAGS_TRUNCATED		= 2,p+	VCHANGE_FLAGS_PAGE_DIRTY	= 3,p+	VCHANGE_FLAGS_IOEXCL_COUNT	= 4
+},vchange_t;
+
+p+Oypedef int	(*vop_open_t)(bhv_desc_t *, s,* Ok,cred *);p+Oypedef ssnit_t (*vop_r ad_,)(bhv_desc_t *, s,* Ok,file *, char *,p+				snit_t, 12ff_t *, iin, s,* Ok,cred *);p+Oypedef ssnit_t (*vop_w    _,)(bhv_desc_t *, s,* Ok,file *, const char *,p+				snit_t, 12ff_t *, iin, s,* Ok,cred *);p+Oypedef int	(*vop_ioctl_t)(bhv_desc_t *, s,* Ok,inode -, s,* Ok,file *,p+				iin, unsigted iin, unsigted long);p+Oypedef int	(*vop_getattr_t)(bhv_desc_t *, s,* Ok,vattr *, iin,
+				s,* Ok,cred *);p+Oypedef int	(*vop_setattr_t)(bhv_desc_t *, s,* Ok,vattr *, iin,
+				s,* Ok,cred *);p+Oypedef int	(*vop_access_t)(bhv_desc_t *, iin, s,* Ok,cred *);p+Oypedef int	(*vop_lookup_t)(bhv_desc_t *, vname_t *, vnode_t -*,p+				iin, vnode_t -, s,* Ok,cred *);p+Oypedef int	(*vop_create_t)(bhv_desc_t *, vname_t *, s,* Ok,vattr *,p+				vnode_t -*, s,* Ok,cred *);p+Oypedef int	(*vop_r movt_t)(bhv_desc_t *, vname_t *, s,* Ok,cred *);p+Oypedef int	(*vop_link_t)(bhv_desc_t *, vnode_t -, vname_t *,
+				s,* Ok,cred *);p+Oypedef int	(*vop_rename_t)(bhv_desc_t *, vname_t *, vnode_t -, vname_t *,
+				s,* Ok,cred *);p+Oypedef int	(*vop_mkdir_t)(bhv_desc_t *, vname_t *, s,* Ok,vattr *,p+				vnode_t -*, s,* Ok,cred *);p+Oypedef int	(*vop_rmdir_t)(bhv_desc_t *, vname_t *, s,* Ok,cred *);p+Oypedef int	(*vop_readdir_t)(bhv_desc_t *, s,* Ok,uio *, s,* Ok,cred *,p+				iin *);p+Oypedef int	(*vop_symlink_t)(bhv_desc_t *, vname_t *, s,* Ok,vattr *,p+				char *,,vnode_t -*, s,* Ok,cred *);p+Oypedef int	(*vop_r adlink_t)(bhv_desc_t *, s,* Ok,uio *, iin,
+				s,* Ok,cred *);p+Oypedef int	(*vop_fsync_t)(bhv_desc_t *, iin, s,* Ok,cred *,
+				xfs_2ff_t,,xfs_2ff_t);p+Oypedef int	(*vop_inactIvt_t)(bhv_desc_t *, s,* Ok,cred *);p+Oypedef int	(*vop_fid2_,)(bhv_desc_t *, s,* Ok,fid *);p+Oypedef int	(*vop_r least_t)(bhv_desc_t *);p+Oypedef int	(*vop_rw12B,_t)(bhv_desc_t *, vrw12B,_t);p+Oypedef vic s(*vop_rwun12B,_t)(bhv_desc_t *, vrw12B,_t);p+Oypedef	int	(*vop_fr12B,_t)(bhv_desc_t *, iin, s,* Ok,file_12B, *,iin,
+				xfs_2ff_t,,s,* Ok,cred *);p+Oypedef int	(*vop_bmap_,)(bhv_desc_t *, xfs_2ff_t,,ssnit_t, iin,
+				s,* Ok,xfs_iomap *, iin *);p+Oypedef int	(*vop_r claim_t)(bhv_desc_t *);p+Oypedef int	(*vop_attr_get_t)(bhv_desc_t *, char *,,char *,,int *, iin,
+				s,* Ok,cred *);p+Oypedef	int	(*vop_attr_set_t)(bhv_desc_t *, char *,,char *,,int, iin,
+				s,* Ok,cred *);p+Oypedef	int	(*vop_attr_r movt_t)(bhv_desc_t *, char *,,int, s,* Ok,cred *);p+Oypedef	int	(*vop_attr_list_t)(bhv_desc_t *, char *,,int, iin,
+				s,* Ok,attrlist_cursor_kert *, s,* Ok,cred *);p+Oypedef vic s(*vop_link_r movtd_,)(bhv_desc_t *, vnode_t -, int);p+Oypedef vic s(*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psiit_t);p+Oypedef vic s(*vop_ptossvp_,)(bhv_desc_t *, xfs_2ff_t,,xfs_2ff_t,,int);p+Oypedef vic s(*vop_p+cushinvalvp_,)(bhv_desc_t *, xfs_2ff_t,,xfs_2ff_t,,int);p+Oypedef int	(*vop_p+cushvp_,)(bhv_desc_t *, xfs_2ff_t,,xfs_2ff_t,
+				udlt64_k,,int);p+Oypedef int	(*vop_i+cush_t)(bhv_desc_t *, iin);
+
+p+Oypedef s,* Ok,vnodeops {p+	bhv_positISF_,  vn_positISF;    4-+positISF2winvin beigaiorAchain -/
+	vop_open_t		vop_open;
+	vop_r ad_,		vop_r ad;
+	vop_w    _,		vop_w    ;
+	vop_ioctl_t		vop_ioctl;
+	vop_getattr_t		vop_getattr;
+	vop_setattr_t		vop_setattr;
+	vop_access_t		vop_access;
+	vop_lookup_t		vop_lookup;
+	vop_create_t		vop_create;
+	vop_r movt_t		vop_r movt;
+	vop_link_t		vop_link;
+	vop_r name_t		vop_r name;
+	vop_mkdir_t		vop_mkdir;
+	vop_rmdir_t		vop_rmdir;
+	vop_r addir_t		vop_r addir;
+	vop_symlink_t		vop_symlink;
+	vop_r adlink_t		vop_r adlink;
+	vop_fsync_t		vop_fsync;
+	vop_inactIvt_t		vop_inactIvt;
+	vop_fid2_,		vop_fid2;
+	vop_rw12B,_t		vop_rw12B,;
+	vop_rwun12B,_t		vop_rwun12B,;
+	vop_fr12B,_t		vop_fr12B,;
+	vop_bmap_,		vop_bmap;
+	vop_r claim_t		vop_r claim;
+	vop_attr_get_t		vop_attr_get;
+	vop_attr_set_t		vop_attr_set;
+	vop_attr_r movt_t	vop_attr_r movt;
+	vop_attr_list_t		vop_attr_list;
+	vop_link_r movtd_,	vop_link_r movtd;
+	vop_vnode_change_t	vop_vnode_change;
+	vop_ptossvp_,		vop_tosspages;
+	vop_p+cushinvalvp_,	vop_fcushinval_pages;
+	vop_p+cushvp_,		vop_+cush_pages;
+	vop_r least_t		vop_r least;
+	vop_i+cush_t		vop_i+cush;
+} vnodeops_t;
+
+4-
+68 VOP's.
+ -/
+# /home _VOP_(op, vp)	(*((vnodeops_, *)(vp)->v_fops)->op)
+p+# /home VOP_READ(vp,file,buf,snit,2ffset,io+c ls,cr,rv)			\
+	rv = _VOP_(vop_r ad, vp)((vp)->v_fbhv,file,buf,snit,2ffset,io+c ls,cr)p+# /home VOP_WRITE(vp,file,buf,snit,2ffset,io+c ls,cr,rv)		\
+	rv = _VOP_(vop_w    , vp)((vp)->v_fbhv,file,buf,snit,2ffset,io+c ls,cr)p+# /home VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
+	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)p+# /home VOP_OPEN(vp, cr, rv)						\
+	rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr)p+# /home VOP_GETATTR(vp, vap, f, cr, rv)					\
+	rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr)
+# /home	VOP_SETATTR(vp, vap, f, cr, rv)					\
+	rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr)
+# /home	VOP_ACCESS(vp, mode, cr, rv)					\
+	rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr)
+# /home	VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv)				\
+	rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr)p+# /home VOP_CREATE(dvp,d,vap,vpp,cr,rv)					\
+	rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr)p+# /home VOP_REMOVE(dvp,d,cr,rv)						\
+	rv = _VOP_(vop_r movt, dvp)((dvp)->v_fbhv,d,cr)
+# /home	VOP_LINK(tdvp,fvp,d,cr,rv)					\
+	rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr)
+# /home	VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv)				\
+	rv = _VOP_(vop_r name, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr)
+# /home	VOP_MKDIR(dp,d,vap,vpp,cr,rv)					\
+	rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr)p+# /home	VOP_RMDIR(dp,d,cr,rv)						\
+	rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr)
+# /home	VOP_READDIR(vp,uiop,cr,eofp,rv)					\
+	rv = _VOP_(vop_r addir, vp)((vp)->v_fbhv,uiop,cr,eofp)
+# /home	VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv)				\
+	rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
+# /home	VOP_READLINK(vp,uiop,fl,cr,rv)					\
+	rv = _VOP_(vop_r adlink, vp)((vp)->v_fbhv,uiop,fl,cr)
+# /home	VOP_FSYNC(vp,f,cr,b,e,rv)					\
+	rv = _VOP_(vop_fsync,+vp)((vp)->v_fbhv,f,cr,b,e)p+# /home VOP_INACTIVE(vp, cr, rv)					\
+	rv = _VOP_(vop_inactIvt, vp)((vp)->v_fbhv, cr)p+# /home VOP_RELEASE(vp, rv)						\
+	rv = _VOP_(vop_r least, vp)((vp)->v_fbhv)p+# /home VOP_FID2(vp, fidp, rv)						\
+	rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp)p+# /home VOP_RWLOCK(vp,i)						\
+	(vic )_VOP_(vop_rw12B,, vp)((vp)->v_fbhv, i)p+# /home VOP_RWLOCK_TRY(vp,i)						\
+	_VOP_(vop_rw12B,, vp)((vp)->v_fbhv, i)p+# /home VOP_RWUNLOCK(vp,i)						\
+	(vic )_VOP_(vop_rwun12B,, vp)((vp)->v_fbhv, i)p+# /home VOP_FRLOCK(vp,c,fl,+c ls,2ffset,fr,rv)				\
+	rv = _VOP_(vop_fr12B,, vp)((vp)->v_fbhv,c,fl,+c ls,2ffset,fr)p+# /home VOP_RECLAIM(vp, rv)						\
+	rv = _VOP_(vop_r claim, vp)((vp)->v_fbhv)p+# /home VOP_ATTR_GET(vp, name, val, vallenp,+fl, cred, rv)		\
+	rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred)
+# /home	VOP_ATTR_SET(vp, name, val, vallen,+fl, cred, rv)		\
+	rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred)
+# /home	VOP_ATTR_REMOVE(vp, name, +c ls, cred, rv)			\
+	rv = _VOP_(vop_attr_r movt, vp)((vp)->v_fbhv,name,+c ls,cred)
+# /home	VOP_ATTR_LIST(vp, buf, buflen,+fl, cursor, cred, rv)		\
+	rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred)
+# /home VOP_LINK_REMOVED(vp, dvp, linkzero)				\
+	(vic )_VOP_(vop_link_r movtd, vp)((vp)->v_fbhv, dvp, linkzero)
+# /home VOP_VNODE_CHANGE(vp, cmd, val)					\
+	(vic )_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val)
+4-
+68 Thesenarenpage cacht functISFs tHatAnow go(OHru VOPs.
+ - 'last' parameter donunused and lefn in2forAIRIX(compatibility
+ -/
+# /home VOP_TOSS_PAGES(vp, first, last, fiopt)				\
+	_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt)
+4-
+68 'last' parameter donunused and lefn in2forAIRIX(compatibility
+ -/
+# /home VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt)			\
+	_VOP_(vop_fcushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt)
+4-
+68 'last' parameter donunused and lefn in2forAIRIX(compatibility
+ -/
+# /home VOP_FLUSH_PAGES(vp, first, last, fc ls, fiopt, rv)		\
+	rv = _VOP_(vop_+cush_pages, vp)((vp)->v_fbhv,first,last,fc ls,fiopt)
+# /home VOP_IOCTL(vp, inode, filp,+fl, cmd, arg, rv)			\
+	rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg)
+# /home VOP_IFLUSH(vp, fc ls, rv)					\
+	rv = _VOP_(vop_i+cush, vp)((vp)->v_fbhv, fc ls)p+
+4-
+68 Fc ls forAread/w     calls -usam uvalues asAIRIX
+ -/
+# /home IO_ISDIRECT	0x00004	E4-+bypassnpage cacht -/
+# /home IO_INVIS	0x00020		4- don't updatt inode ,Imestamps */
+# /home IO_ISLOCKED	0x00800		4- don't do inode 12B,iig -/
+
+4-
+68 Fc ls forAVOP_IFLUSH call
+ -/
+# /home FLUSH_SYNC		1E4-+wait forA+cush to(complete	-/
+# /home FLUSH_INODE		2E4-++cush OHeAinode itself	-/
+# /home FLUSH_LOG		4E4-+forceAOHeAlast log entry forp+	s		E 8+tHisAinode out to(disk	-/
+
+4-
+68 Fcush/Invalida   optISFs forAVOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and
+ -	VOP_FLUSH_PAGES.
+ -/
+# /home FI_NONE		E0	4-+_tne -/
+# /home FI_REMAPF		1E4-+Do a remapf priorAto(OH uoperatISF -/
+# /home FI_REMAPF_LOCKED	2E4-+Do a remapf priorAto(OH uoperatISF.p+	s		E   Preveit VM accessAto(OH upages+/inilp+	s		E   OH uoperatISF completes. -/
+
+4-
+68 Vnodenattributes.  va_mask+indiWates tHosenattributesrOH uca2_er
+68 wants to(set or extract.
+ -/
+Oypedef s,* Ok,vattr {
+	int	sva_mask;E4-+bit-mask+Sf(attributesrpresent 8/
+	enum vtype	va_type;	4- vnode type (forAcreate) -/
+	mode_t		va_mode;E4-++ile accessAmode and Oype -/
+	nlink_t		va_nlink;	4-+_umbISAo++refereices Oo +ile */
+	uid_t		va_uid;		4- ownISAuser dd -/
+	gid_t		va_gid;		4- ownISAgroup dd -/
+	xfs_ino_n	va_nodeid;	4-++ile dd -/
+	xfs_2ff_t	va_snit;E4-++ile sizt in bytes -/
+	u_long		va_b12B,snit;E4-+b12B,snitrpreferred forAi/o -/
+	s,* Ok,,Imespec	va_a,Ime;E4-+,ImeAo++last accessA-/
+	s,* Ok,,Imespec	va_m,Ime;E4-+,ImeAo++last modifiWatISFA-/
+	s,* Ok,,Imespec	va_c,Ime;E4-+,ImeA+ile changed -/
+	u_int	sva_geF;E	4- generatISF numbISAo+++ile -/
+	xfs_dev_t	va_rdev;	4- device OH uspecial++ile representsA-/
+	__dlt64_k	va_nb12B,s;	4-+_umbISAo++b12B,s a2_HWated -/
+	u_long		va_x+c ls;	4-+random extendSd++ile +c ls -/
+	u_long		va_extsnit;E4-++ile extent sizt -/
+	u_long		va_nextents;	4-+_umbISAo++extents in2file */
+	u_long		va_anextents;	4-+_umbISAo++attr extents in2file */
+	int	sva_projid;	4-+project dd -/
+} vattr_t;
+
+4-
+68 setattr or getattr(attributes
+ -/
+# /home XFS_AT_TYPE		0x00000001
+# /home XFS_AT_MODE		0x00000002
+# /home XFS_AT_UID		0x00000004
+# /home XFS_AT_GID		0x00000008
+# /home XFS_AT_FSID		0x00000010
+# /home XFS_AT_NODEID		0x00000020
+# /home XFS_AT_NLINK		0x00000040
+# /home XFS_AT_SIZE		0x00000080
+# /home XFS_AT_ATIME		0x00000100
+# /home XFS_AT_MTIME		0x00000200
+# /home XFS_AT_CTIME		0x00000400
+# /home XFS_AT_RDEV		0x00000800
+# /home XFS_AT_BLKSIZE		0x00001000
+# /home XFS_AT_NBLOCKS		0x00002000
+# /home XFS_AT_VCODE		0x00004000
+# /home XFS_AT_MAC		0x00008000
+# /home XFS_AT_UPDATIME		0x00010000
+# /home XFS_AT_UPDMTIME		0x00020000
+# /home XFS_AT_UPDCTIME		0x00040000
+# /home XFS_AT_ACL		0x00080000
+# /home XFS_AT_CAP		0x00100000
+# /home XFS_AT_INF		0x00200000
+# /home XFS_AT_XFLAGS		0x00400000
+# /home XFS_AT_EXTSIZE		0x00800000
+# /home XFS_AT_NEXTENTS		0x01000000
+# /home XFS_AT_ANEXTENTS	0x02000000
+# /home XFS_AT_PROJID		0x04000000
+# /home XFS_AT_SIZE_NOPERM	0x08000000
+# /home XFS_AT_GENCOUNT		0x10000000
+p+# /home XFS_AT_ALL	(XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
+		XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
+		XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
+		XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|XFS_AT_MAC|\
+		XFS_AT_ACL|XFS_AT_CAP|XFS_AT_INF|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|\
+		XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_PROJID|XFS_AT_GENCOUNT)
+p+# /home XFS_AT_STAT	(XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
+		XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
+		XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
+		XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_PROJID)
+p+# /home XFS_AT_TIMES	(XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME)
+p+# /home XFS_AT_UPDTIMES	(XFS_AT_UPDATIME|XFS_AT_UPDMTIME|XFS_AT_UPDCTIME)
+p+# /home XFS_AT_NOSET	(XFS_AT_NLINK|XFS_AT_RDEV|XFS_AT_FSID|XFS_AT_NODEID|\
+		XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
+		XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
+p+4-
+68 +Modes.
+ -/
+# /home VSUID	S_ISUID		/8 setAuser dd SF executISF -/
+# /home VSGID	S_ISGID		/8 setAgroup dd SF executISF -/
+# /home VSVTX	S_ISVTX		/8 sgaf swappe }text evei2afcer use -/
+# /home VREAD	S_IRUSR		/8 r ad, w    , execute2permissISFs */
+# /home VWRITE	S_IWUSR
+# /home VEXEC	S_IXUSR
+p+# /home MODEMASK+S_IALLUGO	/8 mode bits pcus2permissISF bits -/
+
+4-
+68 Check wheOH rnmaidatory file 12B,iig isAenabled.
+ -/
+# /home MANDLOCK(vp, mode)	\
+	((vp)->v_type == VREG && ((mode) &+(VSGID|(VEXEC>>3))) == VSGID)
+p+extSrt vic svn_init(vic );p+extSrt iny	vn_wait(s,* Ok,vnode -);p+extSrt vnode_t	*vn_initializt(s,* Ok,inode -);
+
+4-
+68 Acquiriig and invalida iig vnodes:
+ -
+68Eif (vn_get(vp, versISF, 0))
+68		...;
+ -	vn_purge(vp, versISF);p+ -
+68 vn_get and vn_purge+must be(ca2_ed winv2vmap_, argumSnts,+sampled
+68 wHile a 12B, tHatrOH uvnode's VOP_RECLAIMnfunctISF acquiresiis
+68 held, to(ensure tHatAOHe,vnode sampled winv2OHe 12B, heldiisn't
+68 recycled (VOP_RECLAIMed) orAdea2_HWated betweei2OHeAreleast o++OHeA12B,
+68( nd OH usubsequent vn_get orAvn_purge.
+ -/
+
+4-
+68 vnode_map s,* Okures _must_nmatchAvn_epoch and vnode s,* Okure sizts.
+ -/
+Oypedef s,* Ok,vnode_map {
+	vfs_,		*v_vfsp;
+	vnumbIS_t	v_numbIS;E	4- in-cor uvnodennumbISA-/
+	xfs_ino_n	v_ino;		E4-+inode #	-/
+} vmap_,;p+p+# /home VMAP(vp, vmap)	{(vmap).v_vfsp	 = (vp)->v_vfsp,	\
+			 (vmap).v_numbISA=,(vp)->v_numbIS,	\
+			 (vmap).v_ino	 = (vp)->v_inode.i_ino; }
+p+extSrt vic svn_purge(s,* Ok,vnode -,2vmap_, -);p+extSrt vnode_t	*vn_get(s,* Ok,vnode -,2vmap_, -);p+extSrt iny	vn_revalida  (s,* Ok,vnode -);p+extSrt vic svn_removt(s,* Ok,vnode -);p+
+s,a ic inline,int vn_couin(s,* Ok,vnode -vp)p+{
+	r dirt atomic_r ad(&LINVFS_GET_IP(vp)->i_couin);p+}p+p+4-
+68 VnodenrefereiceAcouiniig functISFs (and macros forAcompatibility).
+ -/
+extSrt vnode_t	*vn_hold(s,* Ok,vnode -);p+extSrt vic svn_relt(s,* Ok,vnode -);p+
+#if  /homed(XFS_VNODE_TRACE)p+# /home VN_HOLD(vp)		\
+	((vic )vn_hold(vp),	\
+	  vn_Orace_hold(vp, __FILE__, __LINE__, (inst_, *)__r dirt_ ddress))p+# /home VN_RELE(vp)		\
+	  (vn_Orace_rel (vp, __FILE__, __LINE__, (inst_, *)__r dirt_ ddress), \
+E   iput(LINVFS_GET_IP(vp)))p+#e_HWp+# /home VN_HOLD(vp)		((vic )vn_hold(vp))p+# /home VN_RELE(vp)		(iput(LINVFS_GET_IP(vp)))p+#end(+
+p+4-
+68 Vnam uigndliig macros.
+ -/
+# /home VNAME(dentry)		((char *) (dentry)->d_nam .name)p+# /home VNAMELEN(dentry)	((dentry)->d_nam .len)p+# /home VNAME_TO_VNODE(dentry)	(LINVFS_GET_VP((dentry)->d_inode))
+p+4-
+68 Vnodenspin12B,nmaiipulatISF.p+ -/
+# /home VN_LOCK(vp)		mutex_spin12B,(&(vp)->v_12B,)
+# /home VN_UNLOCK(vp, s)	mutex_spinun12B,(&(vp)->v_12B,, s)
+# /home VN_FLAGSET(vp,b)svn_+c lset(vp,b)
+# /home VN_FLAGCLR(vp,b)svn_+c lclr(vp,b)
+
+s,a ic __dlline__ vic  vn_+c lset(s,* Ok,vnode -vp, udlt +c l)p+{
+	spin_12B,(&vp->v_12B,);p+	vp->v_fc lf|= flag;
+	spin_un12B,(&vp->v_12B,);p+}
+
+s,a ic __dlline__ vic  vn_+c lclr(s,* Ok,vnode -vp, udlt +c l)p+{
+	spin_12B,(&vp->v_12B,);p+	vp->v_fc lf&= ~flag;
+	spin_un12B,(&vp->v_12B,);p+}
+
+4-
+68 Updatt modify/access/change+,ImesAon OH uvnodep+ -/
+# /home VN_MTIMESET(vp, tvp)	\
+		(LINVFS_GET_IP(vp)->i_m,Ime = (__dlt32_,)(tvp)->tv_sec)
+# /home VN_ATIMESET(vp, tvp)	\
+		(LINVFS_GET_IP(vp)->i_a,Ime = (__dlt32_,)(tvp)->tv_sec)
+# /home VN_CTIMESET(vp, tvp)	\
+		(LINVFS_GET_IP(vp)->i_c,Ime = (__dlt32_,)(tvp)->tv_sec)
+
+4-
+68 SomenusefulrprediWates.
+ -/
+# /home	VN_MAPPED(vp)	((LINVFS_GET_IP(vp)->i_mappiig->i_mmap != Nt a) || \
+			 (LINVFS_GET_IP(vp)->i_mappiig->i_mmap_shared != Nt a))
+# /home	VN_CACHED(vp)	(LINVFS_GET_IP(vp)->i_mappiig->nrpages)
+# /home VN_DIRTY(vp)	(!list_empty(&(LINVFS_GET_IP(vp)->i_dirty_data_buffers)))p+# /home VMODIFY(vp)	VN_FLAGSET(vp, VMODIFIED)p+# /home VUNMODIFY(vp)	VN_FLAGCLR(vp, VMODIFIED)p+
+4-
+68 Fc ls OoAVOP_SETATTR/VOP_GETATTR.
+ -/
+# /home	ATTR_UTIME	0x01	4-+_tn- /haultAu,Ime(2)urequest -/
+# /home	ATTR_DMI	0x08	4-+invoWatISFAfromra DMInfunctISF -/
+# /home	ATTR_LAZY	0x80	/8 set/get attributesrlazily -/
+# /home	ATTR_NONBLOCK	0x100	/8 r dirt EAGAINA(++operatISF wGuld b12B, */
+
+4-
+68 Fc ls OoAVOP_FSYNC and VOP_RECLAIM.
+ -/
+# /home FSYNC_NOWAIT	0	/8 asynchronous2+cush -/
+# /home FSYNC_WAIT	0x1	4- synchronous2+sync or +orced+r claim -/
+# /home FSYNC_INVAL	0x2	4- +cush and invalida   cacht }dataf-/
+# /home FSYNC_DATA	0x4E4-+synchronous2+sync of}datafonly */
+
+4-
+68 Trackiig vnode actIvity.
+ -/
+#if  /homed(XFS_VNODE_TRACE)p+
+# /home	VNODE_TRACE_SIZE	16		4-+_umbISAo++trace entries -/
+# /home	VNODE_KTRACE_ENTRY	1
+# /home	VNODE_KTRACE_EXIT	2
+# /home	VNODE_KTRACE_HOLD	3
+# /home	VNODE_KTRACE_REF	4
+# /home	VNODE_KTRACE_RELE	5
+p+extSrt vic  vn_Orace_entry(s,* Ok,vnode -,2char *,,inst_, *);p+extSrt vic  vn_Orace_exit(s,* Ok,vnode -,2char *,,inst_, *);p+extSrt vic  vn_Orace_hold(s,* Ok,vnode -, char *,,int, iist_, *);p+extSrt vic  vn_Orace_ref(s,* Ok,vnode -, char *,,int, iist_, *);p+extSrt vic  vn_Orace_relt(s,* Ok,vnode -, char *,,int, iist_, *);p+
+# /home	VN_TRACE(vp)		\
+	vn_Orace_ref(vp, __FILE__, __LINE__, (inst_, *)__r dirt_ ddress)p+#e_HWp+# /home	vn_Orace_entry(a,b,c)
+# /home	vn_Orace_exit(a,b,c)
+# /home	vn_Orace_hold(a,b,c,d)
+# /home	vn_Orace_ref(a,b,c,d)
+# /home	vn_Orace_relt(a,b,c,d)
+# /home	VN_TRACE(vp)p+#end(+
+p+#end(+	4- __XFS_VNODE_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/quota/Mak file 1inux-2.4.27-rc4/fs/xfs/quota/Mak file
--- linux-2.4.26/fs/xfs/quota/Mak file	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/quota/Mak file	2004-07-30 16:30:26.000000000 +0000
@@ -30,10 +30,10 @@
 # http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
 #
 
-EXTRA_CFLAGS += -I $(TOPDIR)/fs/xfs -I $(TOPDIR)/fs/xfs/linux
+EXTRA_CFLAGS += -I $(TOPDIR)/fs/xfs -I $(TOPDIR)/fs/xfs/linux-2.4
 
A(+eq ($(CONFIG_XFS_DEBUG),y)
-	EXTRA_CFLAGS += -g -DDEBUG -DXFSDEBUG
+	EXTRA_CFLAGS += -g -DDEBUG
 	#EXTRA_CFLAGS += -DQUOTADEBUG
 end(+
A(+eq ($(CONFIG_XFS_TRACE),y)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/quota/xfs_qm.c linux-2.4.27-rc4/fs/xfs/quota/xfs_qm.c
--- linux-2.4.26/fs/xfs/quota/xfs_qm.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/quota/xfs_qm.c	2004-07-30 16:27:18.000000000 +0000
@@ -1734,7 +1734,6 @@ xfs_qm_get_rtblks(
 STATIC,int
 xfs_qm_dqusage_ djust(
 	xfs_mo/in_t	*mp,		4- mo/innpoincrforA+ilesystem -/
-	xfs_Orans_,	*tp,		4- OransactISF poincISA- Nt a -/
 	xfs_ino_n	ino,	E4-+inode _umbISAOoAget datafforA-/
 	vic s	*buffer,	4-+_tyAused -/
 	int	subsnit,		4-+_tyAused -/
@@ -1766,7 +1765,7 @@ xfs_qm_dqusage_ djust(
 	 8+tHe case in a2_AoOHer ins,aices. It'onOK tHatAwe do+tHisAbecause
 	 8+quotacheck dondtne only at mo/inn,Ime.
 	 8/
-	if ((error = xfs_iget(mp, tp, ino, XFS_ILOCK_EXCL, &ip, bno)))o{p+	if ((error = xfs_iget(mp, Nt a, ino, XFS_ILOCK_EXCL, &ip, bno)))o{p s	*res = BULKSTAT_RV_NOTHING;p s	r dirt (error);
 	}
@@ -1903,7 +1902,7 @@ xfs_qm_quotacheck(
 	s 8+Iterate(OHru a2_AOHeAinodes in2OHeAfile system,
 	s 8+ djustiig OHeAcorrespondiig dquotAcouiners iF core.
 		 8/
-		if ((error = xfs_bulkstat(mp, Nt a, &lastino, &couin,
+		if ((error = xfs_bulkstat(mp, &lastino, &couin,
 s		E     xfs_qm_dqusage_ djust, Nt a,
 s		E     s,* Oksz, Nt a,
 s		E     BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED,
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/quota/xfs_qm_syscalls.c linux-2.4.27-rc4/fs/xfs/quota/xfs_qm_syscalls.c
--- linux-2.4.26/fs/xfs/quota/xfs_qm_syscalls.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/quota/xfs_qm_syscalls.c	2004-07-30 16:27:27.000000000 +0000
@@ -1298,7 +1298,6 @@ xfs_qm_incISnalqcheck_dq djust(
 STATIC,int
 xfs_qm_incISnalqcheck_ djust(
 	xfs_mo/in_t	*mp,		4- mo/innpoincrforA+ilesystem -/
-	xfs_Orans_,	*tp,		4- OransactISF poincISA-/
 	xfs_ino_n	ino,	E4-+inode _umbISAOoAget datafforA-/
 	vic s	*buffer,	4-+_tyAused -/
 	int	subsnit,		4-+_tyAused -/
@@ -1327,7 +1326,7 @@ xfs_qm_incISnalqcheck_ djust(
 	ipreleastd = B_FALSE;
  again:p 	12B,_+c ls = XFS_ILOCK_SHARED;
-	if ((error = xfs_iget(mp, tp, ino, 12B,_+c ls, &ip, bno)))o{p+	if ((error = xfs_iget(mp, Nt a, ino, 12B,_+c ls, &ip, bno)))o{p s	*res = BULKSTAT_RV_NOTHING;p s	r dirt (error);
 	}
@@ -1405,7 +1404,7 @@ xfs_qm_incISnalqcheck(
 	s 8+Iterate(OHru a2_AOHeAinodes in2OHeAfile system,
 	s 8+ djustiig OHeAcorrespondiig dquotAcouiners
 		 8/
-		if ((error = xfs_bulkstat(mp, Nt a, &lastino, &couin,
+		if ((error = xfs_bulkstat(mp, &lastino, &couin,
 s		E xfs_qm_incISnalqcheck_ djust, Nt a,
 s		E 0, Nt a, BULKSTAT_FG_IGET, &dtne)))o{p s		break;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/support/Mak file 1inux-2.4.27-rc4/fs/xfs/support/Mak file
--- linux-2.4.26/fs/xfs/support/Mak file	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/support/Mak file	2004-07-30 16:29:15.000000000 +0000
@@ -30,7 +30,7 @@
 # http://oss.sgi.com/projects/GenInfo/SGIGPLNtyiceExplan/
 #
 
-EXTRA_CFLAGS += -I.. -I $(TOPDIR)/fs/xfs/linux
+EXTRA_CFLAGS += -I.. -I $(TOPDIR)/fs/xfs/linux-2.4
 
A(+eq ($(CONFIG_XFS_DEBUG),y)
 	EXTRA_CFLAGS += -DDEBUG
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/support/debug.h linux-2.4.27-rc4/fs/xfs/support/debug.h
--- linux-2.4.26/fs/xfs/support/debug.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/support/debug.h	2004-07-30 16:25:02.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -42,6 +42,7 @@
 # /home CE_PANIC,       0               4-+panic        -/
 
 extSrt vic  icmn_err(int, char *,,va_list);p+4-+PRINTFLIKE2 -/
 extSrt vic  cmn_err(int, char *,,...);
 
 #ifndef STATIC
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs.h linux-2.4.27-rc4/fs/xfs/xfs.h
--- linux-2.4.26/fs/xfs/xfs.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs.h	2004-07-30 16:24:17.000000000 +0000
@@ -32,8 +32,9 @@
 #ifndef __XFS_H__
 # /home __XFS_H__
 
-#include <linux/xfs_linux.h>
+#include <linux-2.4/xfs_linux.h>
 
 #include <xfs_fs.h> 
+#include <xfs_macros.h>
 
 #end(+	4- __XFS_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_acl.c linux-2.4.27-rc4/fs/xfs/xfs_acl.c
--- linux-2.4.26/fs/xfs/xfs_acl.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_acl.c	2004-07-30 16:27:29.000000000 +0000
@@ -111,7 +111,7 @@ posix_acl_xattr_to_xfs(p s	r dirt EINVAL;
 
 	if (src->a_versISF != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
-		r dirt EINVAL;
+		r dirt EOPNOTSUPP;
 
 	memset(dest,,0, snitof(xfs_acl_t));
 	dest->acl_cncr= posix_acl_xattr_couin(snit);
@@ -231,8 +231,6 @@ xfs_acl_vget(
 	int	s	+c ls = 0;
 
 	VN_HOLD(vp);
-	if ((error = _MAC_VACCESS(vp, Nt a, VREAD)))
-		goOoAout;
 	if(snit)o{p s	if (!(_ACL_ALLOC(xfs_acl)))o{p s		error = ENOMEM;
@@ -340,7 +338,6 @@ xfs_acl_vset(
 		xfs_acl_vremovt(vp, _ACL_TYPE_ACCESS);
 	}
 
-
Aout:
 	VN_RELE(vp);
 	_ACL_FREE(xfs_acl);
@@ -354,13 +351,15 @@ xfs_acl_iaccess(
 	cred_,		*cr)po{p sxfs_acl_t	*acl;
-	int	serror;
+	int	srval;
 
 	if (!(_ACL_ALLOC(acl)))p s	r dirt -1;
 
 	4- If2OHeAfile haonno ACL r dirt -1. 8/
-	if (xfs_attr_fetch(ip, SGI_ACL_FILE, (char *)acl, snitof(xfs_acl_t)))o{p+	rval = snitof(xfs_acl_t);p+	if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
+			(char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr))o{p s	_ACL_FREE(acl);
 s	r dirt -1;
 	}
@@ -375,9 +374,9 @@ xfs_acl_iaccess(
 	4- Synchronizt ACL winv2mode bits -/
 	xfs_acl_sync_mode(ip->i_d.di_mode, acl);
 
-	error = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);p+	rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);p 	_ACL_FREE(acl);
-	r dirt error;
+	r dirt rval;
 }
 
 STATIC,int
@@ -394,8 +393,6 @@ xfs_acl_a2_Hw_set(
 		r dirt ENOTDIR;
 	if (vp->v_vfsp->vfs_fc lf& VFS_RDONLY)p s	r dirt EROFS;
-	if ((error = _MAC_VACCESS(vp, Nt a, VWRITE)))
-		r dirt error;
 	va.va_mask+= XFS_AT_UID;
 	VOP_GETATTR(vp, &va, 0, Nt a, error);
 	if (error)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_acl.h linux-2.4.27-rc4/fs/xfs/xfs_acl.h
--- linux-2.4.26/fs/xfs/xfs_acl.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_acl.h	2004-07-30 16:24:22.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2001-2003 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2001-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -61,14 +61,17 @@ Oypedef s,* Ok,xfs_aclo{p # /home SGI_ACL_DEFAULT_SIZE	(snitof(SGI_ACL_DEFAULT)-1)
 
 
-#ifdef __KERNEL__
-
 #ifdef CONFIG_XFS_POSIX_ACL
 
 s,* Ok,vattr;
 s,* Ok,vnode;
 s,* Ok,xfs_inode;
 p+extSrt s,* Ok,kmem_ztne -xfs_acl_ztne;p+# /home xfs_acl_ztne_init(ztne, name)	\
+		(ztne)+= kmem_ztne_init(snitof(xfs_acl_t), name)p+# /home xfs_acl_ztne_destroy(ztne)	kmem_cacht_destroy(ztne)
+
 extSrt incrxfs_acl_inherit(s,* Ok,vnode -,2s,* Ok,vattr *, xfs_acl_t *);p extSrt incrxfs_acl_iaccess(s,* Ok,xfs_inode *, mode_t, cred_, *);p extSrt incrxfs_acl_get(s,* Ok,vnode -,2xfs_acl_t *, xfs_acl_t *);p@@ -80,17 +83,10 @@ extSrt incrxfs_acl_vset(s,* Ok,vnode -, p extSrt incrxfs_acl_vget(s,* Ok,vnode -,2vic  *, snit_k,,int);p extSrt incrxfs_acl_vremovt(s,* Ok,vnode -vp, int);
 
-extSrt s,* Ok,kmem_ztne -xfs_acl_ztne;p-
 # /home _ACL_TYPE_ACCESS	1
 # /home _ACL_TYPE_DEFAULT	2
 # /home _ACL_PERM_INVALID(perm)	((perm)f& ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
 
-# /home _ACL_DECL(a)		xfs_acl_t *(a) = Nt a
-# /home _ACL_ALLOC(a)		((a)+= kmem_ztne_a2_HW(xfs_acl_ztne, KM_SLEEP))
-# /home _ACL_FREE(a)		((a)? kmem_ztne_+/ho(xfs_acl_ztne, (a)) : 0)
-# /home _ACL_ZONE_INIT(z,name)	((z)+= kmem_ztne_init(snitof(xfs_acl_t), name))
-# /home _ACL_ZONE_DESTROY(z)	(kmem_cacht_destroy(z))
 # /home _ACL_INHERIT(c,v,d)	(xfs_acl_inherit(c,v,d))
 # /home _ACL_GET_ACCESS(pv,pa)	(xfs_acl_vtoacl(pv,pa,Nt a) == 0)
 # /home _ACL_GET_DEFAULT(pv,pd)	(xfs_acl_vtoacl(pv,Nt a,pd) == 0)
@@ -98,17 +94,19 @@ extSrt s,* Ok,kmem_ztne -xfs_acl_ztne;p # /home _ACL_DEFAULT_EXISTS	xfs_acl_vhaoacl_ /haultp # /home _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ?rxfs_acl_iaccess(i,m,c) : -1)
 
+# /home _ACL_ALLOC(a)		((a)+= kmem_ztne_a2_HW(xfs_acl_ztne, KM_SLEEP))
+# /home _ACL_FREE(a)		((a)? kmem_ztne_+/ho(xfs_acl_ztne, (a)) : 0)
+
 #e_HWp+# /home xfs_acl_ztne_init(ztne,name)p+# /home xfs_acl_ztne_destroy(ztne)p # /home xfs_acl_vset(v,p,sz,t)	(-EOPNOTSUPP)p # /home xfs_acl_vget(v,p,sz,t)	(-EOPNOTSUPP)p # /home xfs_acl_vremovt(v,t)	(-EOPNOTSUPP)p # /home xfs_acl_vhaoacl_access(v)	(0)p # /home xfs_acl_vhaoacl_ /hault(v)	(0)p-# /home _ACL_DECL(a)		((vic )0)
 # /home _ACL_ALLOC(a)		(1)E4-+successfully a2_HWate+_tyhiig -/
 # /home _ACL_FREE(a)		((vic )0)
-# /home _ACL_ZONE_INIT(z,name)	((vic )0)
-# /home _ACL_ZONE_DESTROY(z)	((vic )0)
 # /home _ACL_INHERIT(c,v,d)	(0)
 # /home _ACL_GET_ACCESS(pv,pa)	(0)
 # /home _ACL_GET_DEFAULT(pv,pd)	(0)
@@ -117,6 +115,4 @@ extSrt s,* Ok,kmem_ztne -xfs_acl_ztne;p # /home _ACL_XFS_IACCESS(i,m,c) (-1)
 #end(+
 
-#end(+	4- __KERNEL__ 8/
-
 #end(+	4- __XFS_ACL_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_arch.h linux-2.4.27-rc4/fs/xfs/xfs_arch.h
--- linux-2.4.26/fs/xfs/xfs_arch.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_arch.h	2004-07-30 16:24:20.000000000 +0000
@@ -157,11 +157,11 @@
 
 /* does+_tyAr dirt a value -/
 # /home INT_MOD_EXPR(refereice,arch,code) \
-6   (vic )(((arch) == ARCH_NOCONVERT) \
+6   (((arch) == ARCH_NOCONVERT) \
 	? \
-	6   ((refereice) code) \
+	6   (vic )((refereice) code) \
 	: \
-	6   ( \
+	6   (vic )( \
 		(refereice) = INT_GET((refereice),arch) , \
 		((refereice) code), \
 		INT_SET(refereice, arch, refereice) \
@@ -187,10 +187,10 @@
 
 /* does+_tyAr dirt a value -/
 # /home INT_COPY(dst,src,arch) \
-6   (vic )( \
+6   ( \
 	((snitof(dst) == snitof(src)) || ((arch) == ARCH_NOCONVERT)) \
 	6   ? \
-		((dst) = (src)) \
+		(vic )((dst) = (src)) \
 	6   : \
 		INT_SET(dst, arch, INT_GET(src, arch)) \
     )
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_attr.c linux-2.4.27-rc4/fs/xfs/xfs_attr.c
--- linux-2.4.26/fs/xfs/xfs_attr.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_attr.c	2004-07-30 16:29:18.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -115,20 +115,12 @@ kOrace_t *xfs_attr_Orace_buf;
 68+Overall extSrtal incISface routomes.
  *========================================================================-/
 
-/*ARGSUSED8/
-STATIC,int
-xfs_attr_get_int(xfs_inode_t *ip, char *name, char *value,,int *valuelenp,
-	6    dlt +c ls,,int 12B,, s,* Ok,cred *cred)
+int
+xfs_attr_fetch(xfs_inode_t *ip, char *name, int namelen,
+	6      char *value,,int *valuelenp, dlt +c ls,,s,* Ok,cred *cred)
o{p sxfs_da_args_,   args;
 	int             error;
-	int             namelen;p-
-	ASSERT(MAXNAMELEN-1 <= 0xff);	4-+lengthndonstored ii udlt8 8/
-	namelen = strlen(name);
-	if (namelen >= MAXNAMELEN)
-		r dirt(EFAULT);E	4- matchAIRIX(beigaiour 8/
-	XFS_STATS_INC(xs_attr_get);
 
 	if (XFS_FORCED_SHUTDOWN(ip->i_mo/in))p s	r dirt(EIO);p@@ -138,12 +130,11 @@ xfs_attr_get_int(xfs_inode_t *ip, char *
 	6    ip->i_d.di_anextents == 0))p s	r dirt(ENOATTR);
 
-	if (12B,)o{p+	if (!(+c ls & ATTR_KERNACCESS))o{p s	xfs_i12B,(ip, XFS_ILOCK_SHARED);
-		/*
-	s 8+DoAwe answISAOHem, or ignore tHem?
-	s 8/
-		if ((error = xfs_iaccess(ip, S_IRUSR, cred)))o{p+
+		if (!(+c ls & ATTR_SECURE) &&
+		6   ((error = xfs_iaccess(ip, S_IRUSR, cred))))o{p s		xfs_iun12B,(ip, XFS_ILOCK_SHARED);
 s		r dirt(XFS_ERROR(error));
 s	}
@@ -161,7 +152,6 @@ xfs_attr_get_int(xfs_inode_t *ip, char *
 	args.haohval = xfs_da_haohname(args.name, args.namelen);
 	args.dp = ip;
 	args.whichfork+= XFS_ATTR_FORK;
-	args.Orans = Nt a;
 
 	4-
 	 8+Decide on wHatAwork+routomes to(call bastd on OH uinode snit.
@@ -178,7 +168,7 @@ xfs_attr_get_int(xfs_inode_t *ip, char *
 		error = xfs_attr_node_get(&args);
 	}
 
-	if (12B,)p+	if (!(+c ls & ATTR_KERNACCESS))p s	xfs_iun12B,(ip, XFS_ILOCK_SHARED);
 
 	4-
@@ -192,20 +182,21 @@ xfs_attr_get_int(xfs_inode_t *ip, char *
 }
 
 int
-xfs_attr_fetch(xfs_inode_t *ip, char *name, char *value,,int valuelen)
-{
-	r dirt xfs_attr_get_int(ip, name, value,,&valuelen, ATTR_ROOT, 0, Nt a);
-}p-
-int
 xfs_attr_get(bhv_desc_t *bdp, char *name, char *value,,int *valuelenp,
 	6    dlt +c ls,,s,* Ok,cred *cred)
o{p sxfs_inode_t	*ip+= XFS_BHVTOI(bdp);
+	int	snamelen;p+
+	XFS_STATS_INC(xs_attr_get);
 
 	if (!name)p s	r dirt(EINVAL);
-	r dirt xfs_attr_get_int(ip, name, value,,valuelenp, +c ls,,1, cred);
+	namelen = strlen(name);
+	if (namelen >= MAXNAMELEN)
+		r dirt(EFAULT);E	4- matchAIRIX(beigaiour 8/
+
+	r dirt xfs_attr_fetch(ip, name, namelen, value,,valuelenp, +c ls,,cred);
 }
 
 /*ARGSUSED8/
@@ -224,22 +215,20 @@ xfs_attr_set(bhv_desc_t *bdp, char *name
 	int             rsvd = (+c ls & ATTR_ROOT) != 0;
 	int             namelen;p 
-	ASSERT(MAXNAMELEN-1 <= 0xff); 4-+lengthndonstored ii udlt8 8/
 	namelen = strlen(name);
 	if (namelen >= MAXNAMELEN)
-		r dirt EFAULT; 4-+matchAirix(beigaiour 8/
+		r dirt EFAULT;E	4- matchAIRIX(beigaiour 8/
 
 	XFS_STATS_INC(xs_attr_set);
-	/*
-	 8+DoAwe answISAOHem, or ignore tHem?
-	 8/
+
 	dp+= XFS_BHVTOI(bdp);
 	mp+= dp->i_mo/in;
 	if (XFS_FORCED_SHUTDOWN(mp))p s	r dirt (EIO);p p sxfs_i12B,(dp, XFS_ILOCK_SHARED);
-	if ((error = xfs_iaccess(dp, S_IWUSR, cred)))o{p+	if (!(+c ls & ATTR_SECURE) &&
+	     (error = xfs_iaccess(dp, S_IWUSR, cred)))o{p s	xfs_iun12B,(dp, XFS_ILOCK_SHARED);
 		r dirt(XFS_ERROR(error));
 s}
@@ -489,16 +478,14 @@ xfs_attr_removt(bhv_desc_t *bdp, char *n
 
 	XFS_STATS_INC(xs_attr_removt);
 
-	/*
-	 8+DoAwe answISAOHem, or ignore tHem?
-	 8/
 	dp+= XFS_BHVTOI(bdp);
 	mp+= dp->i_mo/in;
 	if (XFS_FORCED_SHUTDOWN(mp))p s	r dirt (EIO);p p sxfs_i12B,(dp, XFS_ILOCK_SHARED);
-	if ((error = xfs_iaccess(dp, S_IWUSR, cred)))o{p+	if (!(+c ls & ATTR_SECURE) &&
+	     (error = xfs_iaccess(dp, S_IWUSR, cred)))o{p s	xfs_iun12B,(dp, XFS_ILOCK_SHARED);
 		r dirt(XFS_ERROR(error));
 s} e_HW if (XFS_IFORK_Q(dp) == 0 ||
@@ -683,11 +670,10 @@ xfs_attr_list(bhv_desc_t *bdp, char *buf
 
 	if (XFS_FORCED_SHUTDOWN(dp->i_mo/in))p s	r dirt (EIO);p-	/*
-	 8+DoAtHey hgaf permissISF?
-	 8/
+
 	xfs_i12B,(dp, XFS_ILOCK_SHARED);
-	if ((error = xfs_iaccess(dp, S_IRUSR, cred)))o{p+	if (!(+c ls & ATTR_SECURE) &&
+	     (error = xfs_iaccess(dp, S_IRUSR, cred)))o{p s	xfs_iun12B,(dp, XFS_ILOCK_SHARED);
 		r dirt(XFS_ERROR(error));
 s}
@@ -2163,8 +2149,8 @@ xfs_attr_rmtval_removt(xfs_da_args_, *ar
 		4-
 	s 8+I++OHeA"remote" value is in2OHeAcacht, removt it.
 		 8/
-		4-+bp = incore(mp->m_dev, dblkno, blkcnt, 1); 8/
-		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, 1);
+		bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt,p+	s		XFS_INCORE_TRYLOCK);
 		if (bp)o{p s		XFS_BUF_STALE(bp);p s		XFS_BUF_UNDELAYWRITE(bp);pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_attr.h linux-2.4.27-rc4/fs/xfs/xfs_attr.h
--- linux-2.4.26/fs/xfs/xfs_attr.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_attr.h	2004-07-30 16:31:48.000000000 +0000
@@ -92,6 +92,7 @@ extSrt incrattr_generic_list(s,* Ok,vnod
 # /home ATTR_REPLACE	0x0020	4-+pure set: fail if attr does+_tyAexist -/
 # /home ATTR_SYSTEM	0x0100	4-+usenattrs in2system (pseudo) namespace 8/
 
+# /home ATTR_KERNACCESS	0x0400	4-+[kertel] iaccess, inode heldiio-12B,ed -/
 # /home ATTR_KERNOTIME	0x1000	4-+[kertel] don't updatt inode ,Imestamps */
 # /home ATTR_KERNOVAL	0x2000	4-+[kertel] get attr sizt only,+_tyAvalue -/
 # /home ATTR_KERNAMELS	0x4000	4-+[kertel] list attr names (simple list) -/
@@ -186,6 +187,7 @@ incrxfs_attr_inactIvt(s,* Ok,xfs_inode *
 incrxfs_attr_node_get(s,* Ok,xfs_da_args *);p incrxfs_attr_leaf_get(s,* Ok,xfs_da_args *);p incrxfs_attr_shortform_getvalue(s,* Ok,xfs_da_args *);p-incrxfs_attr_fetch(s,* Ok,xfs_inode *, char *,,char *,,int);
+incrxfs_attr_fetch(s,* Ok,xfs_inode *, char *,,iin,
+			char *,,iin *,,int, s,* Ok,cred *);p 
 #end(+	4- __XFS_ATTR_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_bit.c linux-2.4.27-rc4/fs/xfs/xfs_bit.c
--- linux-2.4.26/fs/xfs/xfs_bit.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_bit.c	2004-07-30 16:29:51.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -154,14 +154,17 @@ int
 xfs_lowbit64(
 	__udlt64_k	v)
o{p-	int n;p-	n = ffs((unsigned)v);
-	if (n <= 0)o{p-		n = ffs(v >> 32);
-		if (n >= 0)
-			n+=32;
+	__udlt32_,	w = (__udlt32_,)v;
+	int	sn = 0;
+p+	if (w)o{	4-+lowISAbits -/
+		n = ffs(w);
+	} e_HW {	4-+uppISAbits -/
+		w = (__udlt32_,)(v >> 32);
+		if (w && (n = ffs(w)))
+			n += 32;
 s}
-	r dirt (n <= 0)o? n : n-1;
+	r dirt n - 1;
 }
 
 /*
@@ -171,10 +174,11 @@ int
 xfs_highbit64(
 	__udlt64_k	v)
o{p-	__udlt32_, h = v >> 32;
+	__udlt32_,	h = (__udlt32_,)(v >> 32);
+
 	if (h)p s	r dirt xfs_highbit32(h) + 32;
-	r dirt xfs_highbit32((__u32)v);
+	r dirt xfs_highbit32((__udlt32_,)v);
 }
 
 
@@ -238,32 +242,33 @@ xfs_couin_bits(udlt *map, udlt snit, udl
 int
 xfs_contig_bits(udlt *map, udlt	snit, udlt starn_bit)
o{p-#if BITS_PER_LONG == 32
-	r dirt homd_next_zero_bit((unsigned long *)map,
-			sizt - snitof(udlt) - 8, starn_bit) -ustarn_bit;
-#e_HWp-	/*
-	 8+THeAfirs, argumSnt Oo +imd_next_zero_bit needs to(beAaligned,
-	 8+but tHisAisAcomiig fromrOHeAxfs_buf_log_format_, tn- isk
-	 8+s,* Ok, which can't be(paddSd+or-oOHerwist modified w/o(breakiig
-	 8+tn- iskAcompatibility...(soAcreate aAcemporary,+aligned
-	 8+variable, copy ovtSAOHeAbitmap, and send OHat Oo +imd_next_zero_bit
-	 8+THis only happens in2recovtSy,+soAit'onugly but _tyAtoo(bad.
-	 8/
-	vic  *  ddr;
-	int bit;
-	snit_kAbitmap_snit = snit - snitof(udlt);p-
-	 ddr = (vic  *)kmem_a2_HW(bitmap_snit, KM_SLEEP);
-	memcpy( ddr, map, snit - snitof(udlt));p-
-	bit = homd_next_zero_bit((unsigned long *) ddr,
-			sizt - snitof(udlt) - 8, starn_bit) -ustarn_bit;
+	uilt * p = ((unsigned ilt *) map) + (starn_bit >> BIT_TO_WORD_SHIFT);
+	uilt resultA= 0;
+	uilt tmp;
 
-	kmem_+/ho( ddr, bitmap_snit);
+	sizt <<= BIT_TO_WORD_SHIFT;
 
-	r dirt bit;
-#end(+
+	ASSERT(starn_bit < snit);
+	sizt -=ustarn_bitf& ~(NBWORD - 1);
+	starn_bitf&= (NBWORD - 1);
+	if (starn_bit) {p+		tmp+= *p++;
+		/8 setAOoAoneAfirs, 2ffset bits priorAto(starn -/
+		tmp+|= (~0U >> (NBWORD-starn_bit));
+		if (tmp+!= ~0U)
+			goOoAfouid;
+		r sultA+= NBWORD;
+		sizt -=uNBWORD;
+	}
+	wHile (snit)o{p+		if ((tmp+= *p++)+!= ~0U)
+			goOoAfouid;
+		r sultA+= NBWORD;
+		sizt -=uNBWORD;
+	}
+	r dirt r sultA-ustarn_bit;
+fouid:
+	r dirt r sultA+ ffz(tmp) -ustarn_bit;
 }
 
 /*
@@ -288,25 +293,20 @@ incrxfs_next_bit(udlt *map, udlt snit, up sstarn_bitf&= (NBWORD - 1);
 	if (starn_bit) {p 		tmp+= *p++;
-		/8 setAOoAzeroAfirs, 2ffset bits -/
+		/8 setAOoAzeroAfirs, 2ffset bits priorAto(starn -/
 		tmp+&= (~0U << starn_bit);
-		if (sizt <uNBWORD)
-			goOoAfouid_firs,;
 		if (tmp+!= 0U)
-			goOoAfouid_middle;
-		sizt -=uNBWORD;
+			goOoAfouid;
 		r sultA+= NBWORD;
+		sizt -=uNBWORD;
 s}
-	wHile (snit >= NBWORD)o{p+	wHile (snit)o{p 		if ((tmp+= *p++)+!= 0U)
-			goOoAfouid_middle;
+			goOoAfouid;
 		r sultA+= NBWORD;
 		sizt -=uNBWORD;
 s}
-	if (!snit)
-		r dirt -1;
-	tmp+= *p;
-fouid_firs,:
-fouid_middle:
+	r dirt -1;
+fouid:
 	r dirt r sultA+ ffs(tmp) -u1;
 }
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_bmap.c linux-2.4.27-rc4/fs/xfs/xfs_bmap.c
--- linux-2.4.26/fs/xfs/xfs_bmap.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_bmap.c	2004-07-30 16:27:34.000000000 +0000
@@ -69,7 +69,7 @@
 #include "xfs_buf_icem.h"
 
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 STATIC,vic 
 xfs_bmap_check_leaf_extents(xfs_bt/ho_cur_, *cur,,xfs_inode_t *ip, dlt whichfork);
 #end(+
@@ -195,7 +195,7 @@ xfs_bmap_bt/ho_to_extents(
 	int	s	*log+c lsp, 4-+inode loggiig fc ls -/
 	int	s	whichfork); /* datafor(attr fork+-/
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 /*
  * Check tHatAOHe,extents list forAOHeAinode ip is in2OHeAright ordIS.
  */
@@ -695,7 +695,7 @@ xfs_bmap_ dd_extent(
 		*curp+= cur;
 	}
 dtne:
-#ifdef XFSDEBUG
+#ifdef DEBUG
 	if (!error)
 s	xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
 #end(+
@@ -4077,64 +4077,6 @@ xfs_bmap_caicel(
 }
 
 /*
-68 R dirts EINVAL if OH uspecified +ile ds+_tyAswappable.
-68/p-inc	s		E	/8 error 8/p-xfs_bmap_check_swappable(
-	xfs_inode_t	*ip)		E4-+incor uinode */
-{
-	xfs_bmbt_rec_t	*bast;		E4-+bast o++extent array -/
-	xfs_bmbt_rec_t	*ep;		E4-+poincISAOoAan+extent entry -/
-	xfs_+ile2ff_t	eid_fsb;E	4- last b12B, o+++ile winvin2sizt -/
-	xfs_bmbt_irec_t	ext;		E4-+extent list entry, decoded -/
-	xfs_ifork_t	*ifp;		E4-+inode fork+poincISA-/
-	xfs_+ile2ff_t	last ddr;E	4- last b12B, _umbISAseei2-/
-	xfs_ext_um_t	nextents;		4-+_umbISAo++extent entries -/
-	int	sretvalA= 0;		/8 r dirt value -/
-
-	xfs_i12B,(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);p-
-	/*
-	 8+Check forAaAzeroAlengthn+ile.
-	 8/
-	if (ip->i_d.di_snit == 0)
-		goOoAcheck_dtne;p-
-	ASSERT(XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_BTREE ||
-	6      XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS);p-
-	ifpA= &ip->i_df;
-	if (!(ifp->if_+c ls & XFS_IFEXTENTS) &&
-	6   (retvalA= xfs_ir ad_extents(Nt a, ip, XFS_DATA_FORK)))
-		goOoAcheck_dtne;p-	/*
-	 8+Scan+extents+/inil2OHeAfile sizt is r acht . Look for
-	 8+holesAor+/iw   ten+extents, sniceAI/OAto(OH st wGuld cause
-	 8+a OransactISF.
-	 8/
-	eid_fsb+= XFS_B_TO_FSB(ip->i_mo/in, ip->i_d.di_snit);
-	nextents = ifp->if_bytes / (udlt)snitof(xfs_bmbt_rec_t);
-	bast = &ifp->if_u1.if_extents[0];
-	forA(last ddrA= 0, epA= bast; epA< &bast[nextents]; ep++)+{p-		xfs_bmbt_get_a2_(ep, &ext);
-		if (last ddrA<+ext.br_starn2ff ||
-		6   ext.br_state+!= XFS_EXT_NORM)+{p-			goOoAerror_dtne;p-	s}
-		if (eid_fsb+<= (last ddrA= ext.br_starn2ff +p-			s		ext.br_b12B,co/in))p-			goOoAcheck_dtne;p-	}
-error_dtne:
-	r dvalA= XFS_ERROR(EINVAL);
-
-
-check_dtne:
-	xfs_iun12B,(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);p-	r dirt r tval;
-}p-
-/*
  * R dirts OHeAfile-relatIve b12B, _umbISAof2OHeAfirs, unused b12B,(s)
  * in2OHeAfile winv2atAleast "len" logically contiguous2b12B,s +/ho.
  * THdonis+OHeA12west- ddress+hole if OH ufile haonholes, e_HW OHeAfirs, b12B,
@@ -5790,7 +5732,7 @@ xfs_bmap_tof(
 	r dirt 0;
 }
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 /*
  * Check tHatAOHe,extents list forAOHeAinode ip is in2OHeAright ordIS.
  */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_bmap.h linux-2.4.27-rc4/fs/xfs/xfs_bmap.h
--- linux-2.4.26/fs/xfs/xfs_bmap.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_bmap.h	2004-07-30 16:25:59.000000000 +0000
@@ -178,13 +178,6 @@ xfs_bmap_caicel(
 	xfs_bmap_f/ho_t		*flist);	4- +/ho(list OoAclean up 8/
 
 /*
-68 Routome OoAcheck if auspecified inode isAswap capable.
-68/p-incp-xfs_bmap_check_swappable(
-	s,* Ok,xfs_inode	*ip);	E4-+incor uinode */
-
-/*
  * Compute and fill in2OHeAvalue of2OHeAmaximum depnv2o++a bmap bt/ho
  * in2OHdon+ilesystem.  Dtne once, duriig mo/in.
  */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_bmap_bt/ho.c linux-2.4.27-rc4/fs/xfs/xfs_bmap_bt/ho.c
--- linux-2.4.26/fs/xfs/xfs_bmap_bt/ho.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_bmap_bt/ho.c	2004-07-30 16:24:35.000000000 +0000
@@ -700,7 +700,7 @@ error0:
 	r dirt error;
 }
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 /*
  * GetAOHe,dataffromrOHeApoincId-OoArecord.
  */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_bmap_bt/ho.h linux-2.4.27-rc4/fs/xfs/xfs_bmap_bt/ho.h
--- linux-2.4.26/fs/xfs/xfs_bmap_bt/ho.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_bmap_bt/ho.h	2004-07-30 16:29:39.000000000 +0000
@@ -673,7 +673,7 @@ xfs_bmbt_updatt(
 	xfs_+ilblks_n,
 sxfs_exntst_t);
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 /*
  * GetAOHe,dataffromrOHeApoincId-OoArecord.
  */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_buf_icem.c linux-2.4.27-rc4/fs/xfs/xfs_buf_icem.c
--- linux-2.4.26/fs/xfs/xfs_buf_icem.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_buf_icem.c	2004-07-30 16:25:38.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -1053,9 +1053,9 @@ xfs_buf_iodtne_callbacks(p s	6   (,Ime_afcer(jiffies, (last,Ime + 5*HZ))))o{p s		last,Ime = jiffies;p s		prdIv("XFS w     error inAfile system meta-dataf"p-			      "b12B, 0x%Lx inA%s",
+			      "b12B, 0x%llx inA%s",
 			      XFS_BUF_TARGET(bp),p-			      XFS_BUF_ADDR(bp), mp->m_fsname);
+			      (__udlt64_k)XFS_BUF_ADDR(bp), mp->m_fsname);
 s	}
 		last,arg+= XFS_BUF_TARGET(bp);
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_clin.h linux-2.4.27-rc4/fs/xfs/xfs_clin.h
--- linux-2.4.26/fs/xfs/xfs_clin.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_clin.h	2004-07-30 16:30:28.000000000 +0000
@@ -100,5 +100,7 @@ s,* Ok,xfs_mo/in_args {p # /home XFSMNT_DMAPI		0x02000000E4-+enable dmapi/xdsm -/
 # /home XFSMNT_NOLOGFLUSH	0x04000000E4-+Don't +cush forAlog2b12B,s -/
 # /home XFSMNT_IDELETE		0x08000000E4-+inode ccuscISAdelete -/
+# /home XFSMNT_SWALLOC		0x10000000E4-+dirt ot s,*ipe widthp+	s			s 8+ 2_HWatISF -/
 
 #end(+	4- __XFS_CLNT_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_da_bt/ho.c linux-2.4.27-rc4/fs/xfs/xfs_da_bt/ho.c
--- linux-2.4.26/fs/xfs/xfs_da_bt/ho.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_da_bt/ho.c	2004-07-30 16:31:00.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -2166,9 +2166,9 @@ xfs_da_do_buf(p s				cmn_err(CE_ALERT,
 s		E		"[%02d] br_starn2ff %lld br_starnb12B, %lld br_b12B,co/in %lld br_state %d\n",
 s		E		i,p-			s		mapp[i].br_starn2ff,p-			s		mapp[i].br_starnb12B,,p-			s		mapp[i].br_b12B,co/in,p+	s			s(long long)mapp[i].br_starn2ff,p+	s			s(long long)mapp[i].br_starnb12B,,p+	s			s(long long)mapp[i].br_b12B,co/in,p 			s		mapp[i].br_state);
 s	s	}
 			}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_dir2_node.c linux-2.4.27-rc4/fs/xfs/xfs_dir2_node.c
--- linux-2.4.26/fs/xfs/xfs_dir2_node.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_dir2_node.c	2004-07-30 16:29:50.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -224,12 +224,21 @@ xfs_dir2_leaft_ dd(
 	mp+= dp->i_mo/in;
 	tp+= args->Orans;
 	leafA= bp->data;
+p+	4-
+s 8+QuiB, check just OoAmako(sure we are+_ty goiig Oo+index
+s 8+dltoAoOHer peoplesAmemory
+s 8/
+	if (index < 0)
+		r dirt XFS_ERROR(EFSCORRUPTED);
+
 	4-
 	 8+I++OHere are+alr ady2OHeAmaximum _umbISAof2leafAentries dl
 	 8+tHe b12B,, if OH re are+_t stale entries itAwon't +it.
 	 - C 2_ISAwill do ausplit. +I++OHere are+stale entries we'll do
 	 - aAcompact.
 	 8/
+
 	if (INT_GET(leaf->hdr.co/in, ARCH_CONVERT) == XFS_DIR2_MAX_LEAF_ENTS(mp))o{p 		if (INT_ISZERO(leaf->hdr.stale, ARCH_CONVERT))
 s		r dirt XFS_ERROR(ENOSPC);p@@ -828,12 +837,24 @@ xfs_dir2_leaft_rebalaice(p s	state->inleafA= !swap;
 	e_HWp s	state->inleafA=
-			swap ^ (args->haohval < INT_GET(leaf2->ents[0].haohval, ARCH_CONVERT));
+			swap ^ (blk1->index <= INT_GET(leaf1->hdr.co/in, ARCH_CONVERT));
 s4-
 	 8+Adjust OHe,expected index for insertISF.
 	 8/
 	if (!state->inleaf)
 s	blk2->index = blk1->index - INT_GET(leaf1->hdr.co/in, ARCH_CONVERT);
+	p+	4- 
+s 8+Finally sanity check just OoAmako(sure we are+_ty r dirtiig a negatIve index 
+s 8/
+	if(blk2->index < 0)o{p+s	state->inleafA= 1;
+		blk2->index = 0;
+		cmn_err(CE_ALERT,
+			"xfs_dir2_leaft_rebalaice: piB,ed OHe,wrong leaf? r vertIng origtal leaf:f"p+			"blk1->index %d\n",
+			blk1->index);
+	}
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_dmapi.h linux-2.4.27-rc4/fs/xfs/xfs_dmapi.h
--- linux-2.4.26/fs/xfs/xfs_dmapi.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_dmapi.h	2004-07-30 16:30:36.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -199,7 +199,14 @@ Oypedef e_umo{p 
 extSrt s,* Ok,bhv_vfsops xfs_dmops;
 
-extSrt dlt dmapi_init(vic );
-extSrt vic  dmapi_uninit(vic );
+#ifdef CONFIG_XFS_DMAPI
+vic  xfs_dm_init(s,* Ok,file_system_Oype *);p+vic  xfs_dm_exit(s,* Ok,file_system_Oype *);p+# /home XFS_DM_INIT(fsOype)	xfs_dm_init(fsOype)p+# /home XFS_DM_EXIT(fsOype)	xfs_dm_exit(fsOype)p+#e_HWp+# /home XFS_DM_INIT(fsOype)p+# /home XFS_DM_EXIT(fsOype)p+#end(+
 
 #end(+  4-+__XFS_DMAPI_H__ -/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_fsops.c linux-2.4.27-rc4/fs/xfs/xfs_fsops.c
--- linux-2.4.26/fs/xfs/xfs_fsops.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_fsops.c	2004-07-30 16:28:38.000000000 +0000
@@ -576,7 +576,8 @@ xfs_fs_log_dummy(xfs_mo/in_t *mp)
 sxfs_Orans_ijoii(tp, ip, XFS_ILOCK_EXCL);p sxfs_Orans_ihold(tp, ip);p sxfs_Orans_log_inode(tp, ip, XFS_ILOG_CORE);p-	xfs_Orans_commit(tp, XFS_TRANS_SYNC, Nt a);
+	xfs_Orans_set_sync(tp);
+	xfs_Orans_commit(tp, 0, Nt a);
 p sxfs_iun12B,(ip, XFS_ILOCK_EXCL);p }
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_inode.c linux-2.4.27-rc4/fs/xfs/xfs_inode.c
--- linux-2.4.26/fs/xfs/xfs_inode.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_inode.c	2004-07-30 16:28:12.000000000 +0000
@@ -854,6 +854,34 @@ xfs_xlate_dinode_core(p sINT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
 }
 
+uint
+xfs_dic2x+c ls(
+	xfs_dinode_core_t	*dic,
+	xfs_arch_t		arch)
+{
+	__udlt16_t		di_+c ls;
+	uilt	s	+c ls = 0;
+p+	di_+c ls = INT_GET(dic->di_+c ls,,arch);
+	if (di_+c ls & XFS_DIFLAG_REALTIME)
+		+c ls |= XFS_XFLAG_REALTIME;
+	if (di_+c ls & XFS_DIFLAG_PREALLOC)
+		+c ls |= XFS_XFLAG_PREALLOC;
+	if (di_+c ls & XFS_DIFLAG_IMMUTABLE)
+		+c ls |= XFS_XFLAG_IMMUTABLE;
+	if (di_+c ls & XFS_DIFLAG_APPEND)
+		+c ls |= XFS_XFLAG_APPEND;
+	if (di_+c ls & XFS_DIFLAG_SYNC)
+		+c ls |= XFS_XFLAG_SYNC;
+	if (di_+c ls & XFS_DIFLAG_NOATIME)
+		+c ls |= XFS_XFLAG_NOATIME;
+	if (di_+c ls & XFS_DIFLAG_NODUMP)
+		+c ls |= XFS_XFLAG_NODUMP;
+	if (XFS_CFORK_Q_ARCH(dic, arch))
+		+c ls |= XFS_XFLAG_HASATTR;
+	r dirt +c ls;
+}
+
 /*
  * GIvet a mo/inns,* Okure and an+inode _umbIS,Ar dirt a poincIS
  * OoAa newly a2_HWated in-cor uinode cor spondiig to(OH  gIvet
@@ -1112,8 +1140,7 @@ xfs_ia2_HW(
 	 - C 2_ OH uspace managemSnt code ,o piB,
 	 8+tHe tn- iskAinode ,o(beAal_HWated.
 	 8/
-	ASSERT(pip+!= Nt a);
-	error = xfs_dia2_HW(tp, pip+? pip->i_ino : 0, mode, oka2_HW,
+	error = xfs_dia2_HW(tp, pip->i_ino, mode, oka2_HW,
 			    ia2_HW_context,(call_again, &ino);
 	if (error+!= 0)o{p 		r dirt error;
@@ -3668,12 +3695,6 @@ xfs_iaccess(
 	mode_t		orgmode = mode;p sst* Ok,inode	*inode = LINVFS_GET_IP(XFS_ITOV(ip));
 
-	/*
-	 8+Verify tHatAOHe,MAC policy a2_Hws+OHeArequested access.
-	 8/
-	if ((error = _MAC_XFS_IACCESS(ip, mode, cr)))
-		r dirt XFS_ERROR(error);p-
 	if (mode & S_IWUSR)o{p 		umode_t		imode = inode->i_mode;
 p@@ -3725,32 +3746,6 @@ xfs_iaccess(
 }
 
 /*
-68 R dirt wheOHer or _ty it ionOK toAswap to(OH  gIvet +ile dn2OHe
-68 gIvet range.  R dirt 0 for OK and oOHerwist r dirt OHe,error.
-68
-68 It iononly OK toAswap to(a +ile df it haonno holes, and all
-68 extents hgaf beei2initia2ized.
-68
-68 We+usenOHeAvnode beigaior chadn2pr vent and allow primitIves
-68 OoAensure tHatAOHe,vnode chadn2staysAcoHerelt whileAwe do+tHis.
-68 THdona2_Hws+us to(walk2OHeAchadn2down to(OH  bottom where XFS
-68 lIves winvoutAworryiig aboutAit changiig outAfromrundISAus.
-68/p-incp-xfs_swappable(
-	bhv_desc_t	*bdp)
-{
-	xfs_inode_t	*ip;p-
-	ip+= XFS_BHVTOI(bdp);
-	/*
-	 8+Verify tHatAOHe,+ile does+_tyAhgaf any
-	 8+holesAor+/iw   ten+exents.
-	 8/
-	r dirt xfs_bmap_check_swappable(ip);p-}p-
-/*
  * xfs_irouidup: rouid up argumSnt Oo next powISAof2Owo
  */
 udlt
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_inode.h linux-2.4.27-rc4/fs/xfs/xfs_inode.h
--- linux-2.4.26/fs/xfs/xfs_inode.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_inode.h	2004-07-30 16:28:34.000000000 +0000
@@ -459,8 +459,8 @@ xfs_inode_t *xfs_bhvtoi(s,* Ok,bhv_desc 
  * directory, groupAof2new +ile ds+setAOoAtHatAo++OHeAparelt, and
  * new subdirectory gets S_ISGID bitAfromrparelt.
  */
-# /home XFS_INHERIT_GID(pip, vfsp)	((pip)+!= Nt a && \
-	(((vfsp)->vfs_fc lf& VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID)))p+# /home XFS_INHERIT_GID(pip, vfsp)	\
+	(((vfsp)->vfs_fc lf& VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
 
 /*
  * xfs_iget.c protoOypes.
@@ -503,8 +503,9 @@ incs	xfs_ir ad_extents(s,* Ok,xfs_Orans 
 incs	xfs_ia2_HW(s,* Ok,xfs_Orans *,,xfs_inode_t *, mode_t, nlink_t,
 			   xfs_dev_t, s,* Ok,cred *,,xfs_prid_k,,int,
 			   s,* Ok,xfs_buf **,,boolean_t *, xfs_inode_t **);p-vic s	xfs_xlate_dinode_core(xfs_c ddr_t, s,* Ok,xfs_dinode_core *,,iin,
-			   xfs_arch_t);p+vic s	xfs_xlate_dinode_core(xfs_c ddr_t, s,* Ok,xfs_dinode_core *,p+	s			int, xfs_arch_t);p+uincs	xfs_dic2x+c ls(s,* Ok,xfs_dinode_core *,,xfs_arch_t);p incs	xfs_i+/ho(s,* Ok,xfs_Orans *,,xfs_inode_t *,
 			   s,* Ok,xfs_bmap_f/ho *);p inc		xfs_a,* nWate_starn(xfs_inode_t *);pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_iomap.c linux-2.4.27-rc4/fs/xfs/xfs_iomap.c
--- linux-2.4.26/fs/xfs/xfs_iomap.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_iomap.c	2004-07-30 16:25:45.000000000 +0000
@@ -577,24 +577,70 @@ r dry:
 	 8/
 	if (!(iofc lf& BMAPI_SYNC) && ((2ffset + co/in) > ip->i_d.di_snit))o{p s	xfs_2ff_t	aligned_2ffset;
+		xfs_+ilblks_n   co/in_fsb;p 		unsigned ilt	iosnit;p s	xfs_+ile2ff_t	ioalign;
+		int	sn;
+		xfs_+ile2ff_t   s,arn_fsb;p 
+		/8
+		68+I++OHere are+any r al2b12B,s past e2f,+OHen don't
+		68+do any speculatIve  2_HWatISF.
+		68/p+s	starn_fsb+= XFS_B_TO_FSBT(mp,p+	s			((xfs_ufsnit_k)(2ffset + co/in - 1)));
+		co/in_fsb+= XFS_B_TO_FSB(mp, (xfs_ufsnit_k)XFS_MAXIOFFSET(mp));
+		wHile (co/in_fsb+> 0)o{p+s		nimaps+= XFS_WRITE_IMAPS;
+			error = XFS_BMAPI(mp, Nt a, io, s,arn_fsb, co/in_fsb,p+	s			0, &firs,b12B,, 0, imap, &nimaps, Nt a);
+			if (error)o{p+s			r dirt error;
+			}
+			forA(n = 0; n < nimaps; n++)+{p+s			if ((imap[n].br_starnb12B,+!= HOLESTARTBLOCK) &&
+		s	6   (imap[n].br_starnb12B,+!= DELAYSTARTBLOCK))+{p+s				goOoAw    _map;
+				}
+				starn_fsb++= imap[n].br_b12B,co/in;
+				co/in_fsb+-= imap[n].br_b12B,co/in;
+			}
+		}
 		iosnit = mp->m_w    io_b12B,s;p s	aligned_2ffset+= XFS_WRITEIO_ALIGN(mp, (2ffset + co/in - 1));
 		ioalign+= XFS_B_TO_FSBT(mp, aligned_2ffset);
 		last_fsb+= ioalign++ iosnit;p s	ae2fA= 1;
 s}
-
+w    _map:
 	nimaps+= XFS_WRITE_IMAPS;
 	firs,b12B, = Nt aFSBLOCK;
 
 	4-
-	 8+rouidup+OHeA 2_HWatISF request OoAm_dalign+bouidary ifAfile sizt
-	 8+ds+greaterAtHatA512K and we are+al_HWatIig past OHeA 2_HWatISF e2f
+s 8+I++mo/ined winv2OHeA"-oAswa2_HW" optISF,+rouidup+OHeA 2_HWatISF
+s 8+request OoAa s,*ipe width+bouidary ifAOHeAfile sizt is >=
+s 8+s,*ipe width+and we are+al_HWatIig past OHeA 2_HWatISF e2f.
+s 8/
+	if (mp->m_swidth+&& (mp->m_fc ls & XFS_MOUNT_SWALLOC)
+	6   && (isnit >= XFS_FSB_TO_B(mp, mp->m_swidth)) && ae2f)o{p+		int e2f;
+		xfs_+ile2ff_t new_last_fsb;
+p+		new_last_fsb = rouidup_64(last_fsb, mp->m_swidth);
+		error = xfs_bmap_tof(ip, new_last_fsb, XFS_DATA_FORK, &e2f);
+		if (error)o{p+s		r dirt error;
+		}
+		if (e2f)o{p+			last_fsb+= new_last_fsb;
+		}
+	4-
+s 8+Rouidup+OHeA 2_HWatISF request OoAa s,*ipe unitA(m_dalign)+bouidary
+s 8+dfAOHeAfile sizt is >= s,*ipe unitAsnit, and we are+al_HWatIig past
+s 8+OHeA 2_HWatISF e2f.
 	 8/
-	if (mp->m_dalign+&& (isnit >= mp->m_dalign) && ae2f)o{p+	} e_HW if (mp->m_dalign+&& (isnit >= XFS_FSB_TO_B(mp, mp->m_dalign))
+		   && ae2f)o{p 		int e2f;
 s	xfs_+ile2ff_t new_last_fsb;
 		new_last_fsb = rouidup_64(last_fsb, mp->m_dalign);pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_itable.c linux-2.4.27-rc4/fs/xfs/xfs_itable.c
--- linux-2.4.26/fs/xfs/xfs_itable.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_itable.c	2004-07-30 16:31:15.000000000 +0000
@@ -55,14 +55,18 @@
 #include "xfs_itable.h"
 #include "xfs_error.h"
 
+#ifndef HAVE_USERACCp+# /home useracc(ubuffIS,Asnit, +c ls,,foo) (0)
+# /home unuseracc(ubuffIS,Asnit, +c ls)p+#end(+
+
 /*
  * R dirt stat ilformatISF forAtne inode.
  * R dirt 0 if ok, e_HW errno.
  */
-inc	s		E/8 error status -/
+inc	s6      	E/8 error status -/
,xfs_bulkstat_tne(
 	xfs_mo/in_t	*mp,E	4- mo/in poinc forA+ilesystem2-/
-	xfs_Orans_t	*tp,E	4- OransactISF+poincISA-/
 sxfs_ino_t	ino,	E4-+inode _umbISAOoAget dataffoSA-/
 svic s	*buffIS,E4-+buffIS ,o place outputAin -/
 	int	subsnit,		/8 sizt of+buffIS */
@@ -78,12 +82,10 @@ xfs_bulkstat_tne(
 	xfs_dinode_core_t *dic;	E4-+dinode cor  ilfo+poincISA-/
 sxfs_inode_t	*ip+= Nt a;E4-+incor uinode poincISA-/
 sxfs_arch_t      arch;           /*(OH st are set accordiig to((((((-/
-	__udlt16_t((((((di_+c ls;       /*(Oemp 8/
 
-	buf = (xfs_bstat_t *)buffIS;
 	dip+= (xfs_dinode_t *)dibuff;
 
-	if (!+buf || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+	if (!buffIS || ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
 	6   (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
 	6    (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)))o{p s	*stat = BULKSTAT_RV_NOTHING;
@@ -94,11 +96,13 @@ xfs_bulkstat_tne(
 		r dirt XFS_ERROR(ENOMEM);
 	}
 
+	buf = kmem_a2_HW(snitof(*buf), KM_SLEEP);
+
 	if (dip+== Nt a)o{p s	/8 We're+_ty beIig passed a+poincISAOoAa+dinode.  THdonhappens
 	s 8+if BULKSTAT_FG_IGET ds+selected.  DtAOHeAiget.
 		 8/
-		error = xfs_iget(mp, tp, ino, XFS_ILOCK_SHARED, &ip, bno);
+		error = xfs_iget(mp, Nt a, ino, XFS_ILOCK_SHARED, &ip, bno);
 		if (error)o{p 			*stat = BULKSTAT_RV_NOTHING;
 s		r dirt error;
@@ -108,6 +112,7 @@ xfs_bulkstat_tne(
 		if (ip->i_d.di_mode == 0)o{p 		sxfs_iput_new(ip, XFS_ILOCK_SHARED);
 s		*stat = BULKSTAT_RV_NOTHING;
+			kmem_+/ho(buf, snitof(*buf));
 s		r dirt XFS_ERROR(ENOENT);
 s	}
 		dicA= &ip->i_d;
@@ -160,29 +165,7 @@ xfs_bulkstat_tne(
 	buf->bs_m,Ime.tv_nsec = INT_GET(dic->di_m,Ime.t_nsec, arch);
 	buf->bs_c,Ime.tv_sec = INT_GET(dic->di_c,Ime.t_sec, arch);
 	buf->bs_c,Ime.tv_nsec = INT_GET(dic->di_c,Ime.t_nsec, arch);
-	/*
-	 8+convert(di_+c ls ,o(bs_x+c ls.
-	 8/
-	di_+c ls = INT_GET(dic->di_+c ls,,arch);
-
-	buf->bs_x+c ls =
-		((di_+c ls & XFS_DIFLAG_REALTIME) ?
-	s	XFS_XFLAG_REALTIME : 0) |
-		((di_+c ls & XFS_DIFLAG_PREALLOC) ?
-	s	XFS_XFLAG_PREALLOC : 0) |
-	        ((di_+c ls & XFS_DIFLAG_IMMUTABLE) ?
-	s        XFS_XFLAG_IMMUTABLE : 0) |
-		((di_+c ls & XFS_DIFLAG_APPEND) ?
-	s        XFS_XFLAG_APPEND : 0) |
-		((di_+c ls & XFS_DIFLAG_SYNC) ?
-	s        XFS_XFLAG_SYNC : 0) |
-		((di_+c ls & XFS_DIFLAG_NOATIME) ?
-	s        XFS_XFLAG_NOATIME : 0) |
-		((di_+c ls & XFS_DIFLAG_NODUMP) ?
-	s        XFS_XFLAG_NODUMP : 0) |
-		(XFS_CFORK_Q_ARCH(dic, arch) ?
-	s	XFS_XFLAG_HASATTR : 0);
-
+	buf->bs_x+c ls = xfs_dic2x+c ls(dic, arch);
 	buf->bs_extsnit = INT_GET(dic->di_extsnit, arch) << mp->m_sb.sb_b12B,log;
 	buf->bs_extents = INT_GET(dic->di_nextents, arch);
 	buf->bs_gen = INT_GET(dic->di_gen, arch);
@@ -224,6 +207,13 @@ xfs_bulkstat_tne(
 		xfs_iput(ip, XFS_ILOCK_SHARED);
 s}
 
+	if (copy_to_user(buffIS,Abuf, snitof(*buf))) o{p+		kmem_+/ho(buf, snitof(*buf));
+		*stat = BULKSTAT_RV_NOTHING;
+		r dirt EFAULT;
+	}
+
+	kmem_+/ho(buf, snitof(*buf));
 s*stat = BULKSTAT_RV_DIDONE;
 	if (ubused)
o		*ubused = snitof(*buf);
@@ -236,7 +226,6 @@ xfs_bulkstat_tne(
 inc	s		E/8 error status -/
 xfs_bulkstat(
 	xfs_mo/in_t		*mp,E4- mo/in poinc forA+ilesystem2-/
-	xfs_Orans_t		*tp,E4- OransactISF+poincISA-/
 sxfs_ino_t		*lastinop, 4-+last inode r dirted -/
 	int	s	*ubco/inp, 4-+sizt of+buffIS/co/in r dirted -/
 	bulkstat_tne_pf		formattIS,A4- +uncAtHat'd fill a snigle+buf */
@@ -311,13 +300,11 @@ xfs_bulkstat(
 	 8+L2B, down the user's+buffIS.+I++a+buffIS was+_tyAselt, as in2OHeAcaHWp s * disk quota code callonhert, we skip+tHis.
 	 8/
-#if  /homed(HAVE_USERACC)
 	if (ubuffIS &&
 	6   (error = useracc(ubuffIS,Aubco/in 8+s,ats,* Ok_snit,
 s		(B_READ|B_PHYS), Nt a)))o{p 		r dirt error;
 s}
-#end(+
 s4-
 	 8+Al_HWate a+page-snitd+buffIS for inode bt/hoArecords.
 	 8 We+cGuld try al_HWatIig somenving sm 2_IS, but for _trmal
@@ -333,7 +320,7 @@ xfs_bulkstat(
 	wHile (ubleft >= s,ats,* Ok_snit && agno < mp->m_sb.sb_agco/in) {p 		bp+= Nt a;
 		down_r ad(&mp->m_perag12B,);
-		error = xfs_ia2_HW_r ad_agi(mp, tp, agno, &agbp);
+		error = xfs_ia2_HW_r ad_agi(mp, Nt a, agno, &agbp);
 		up_r ad(&mp->m_perag12B,);
 		if (error)o{p 			/*
@@ -347,7 +334,7 @@ xfs_bulkstat(
 		4-
 	s 8+Al_HWate and2initia2ize+a+bt/hoAcursoS for ia2_HW+bt/ho.
 		 8/
-		cur = xfs_bt/ho_init_cursoS(mp, tp, agbp, agno, XFS_BTNUM_INO,p+	scur = xfs_bt/ho_init_cursoS(mp, Nt a, agbp, agno, XFS_BTNUM_INO,p s		(xfs_inode_t *)0, 0);
 		irbp = irbuf;
 		irbufend = irbuf + nirbuf;
@@ -461,7 +448,7 @@ xfs_bulkstat(
 		 8+wHen calling iget.
 		 8/
 s	xfs_bt/ho_del_cursoS(cur,,XFS_BTREE_NOERROR);
-		xfs_Orans_bre_HW(tp, agbp);
+		xfs_buf_re_HW(agbp);
 		4-
 	s 8+Now format  2_ OH ugood inodes+dltoAthe user's+buffIS.
 		 8/
@@ -534,8 +521,8 @@ xfs_bulkstat(
 		s			ip->i_ino = ino;
 		s			ip->i_mo/in = mp;
 		s			if (bp)p-			s			xfs_Orans_bre_HW(tp, bp);
-						error = xfs_itobp(mp, tp, ip,p+	s					xfs_buf_re_HW(bp);
+						error = xfs_itobp(mp, Nt a, ip,
 		s				s  &dip, &bp, bno);
 		s			if (!error)
 s						ccuscidx = ip->i_b2ffset / mp->m_sb.sb_inodesnit;p@@ -580,7 +567,7 @@ xfs_bulkstat(
 			s 8+it xfs_qm_quotacheck.
 			s 8/
 			subused = s,ats,* Ok_snit;
-				error = formattIS(mp, tp, ino, ubufp,p+	s		error = formattIS(mp, ino, ubufp,p s					ubleft, private_data,p s					bno, &ubused, dip, &fmterror);p s			if (fmterror == BULKSTAT_RV_NOTHING)o{p@@ -603,7 +590,7 @@ xfs_bulkstat(
 	s}
 
 		if (bp)p-			xfs_Orans_bre_HW(tp, bp);
+			xfs_buf_re_HW(bp);
 
 		4-
 	s 8+Set up forAOHeAnext loop iteratISF.
@@ -621,10 +608,8 @@ xfs_bulkstat(
 	 8+Dont, we're+eiOHer out o+++ilesystem2or space ,o putAOHe,data.
 	 8/
 	kmem_+/ho(irbuf, NBPC);p-#if  /homed(HAVE_USERACC)
 	if (ubuffIS)p 		unuseracc(ubuffIS,Aubco/in 8+s,ats,* Ok_snit, (B_READ|B_PHYS));
-#end(+
 s*ubco/inp = ubelem;
 	if (agno >= mp->m_sb.sb_agco/in) {p 		/*
@@ -651,7 +636,6 @@ xfs_bulkstat_snigle(
 	xfs_c ddr_t		buffIS,E4-+buffIS winv2inode s,ats -/
 	int	s	*dtne)E4-+1 if OH re're+more s,ats OoAget -/
 {
-	xfs_bstat_t		bstat;E4-+tne bulkstat r sultAs,* Okure -/
 	int	s	co/in;E4-+co/in value forAbulkstat call -/
 	int	s	error;	/8 r dirt value -/
 sxfs_ino_t		ino;	4- +ilesystem2inode _umbISA*/
@@ -667,7 +651,7 @@ xfs_bulkstat_snigle(
 	 8/
 
 	ino = (xfs_ino_t)*lastinop;
-	error = xfs_bulkstat_tne(mp, Nt a, ino, &bstat, snitof(bstat),
+	error = xfs_bulkstat_tne(mp, ino, buffIS,Asnitof(xfs_bstat_t),p s			 Nt a, 0, Nt a, Nt a, &r s);
 	if (error) {p 		/*
@@ -676,9 +660,9 @@ xfs_bulkstat_snigle(
 	s 8/
 		(*lastinop)--;p s	co/in = 1;
-		if (xfs_bulkstat(mp, Nt a, lastinop, &co/in, xfs_bulkstat_tne,p-			sNt a,p-			ssnitof(bstat), buffIS,ABULKSTAT_FG_IGET, dtne))
+		if (xfs_bulkstat(mp, lastinop, &co/in, xfs_bulkstat_tne,p+			sNt a,Asnitof(xfs_bstat_t), buffIS,p+			sBULKSTAT_FG_IGET, dtne))
 s		r dirt error;
 		if (co/in == 0 || (xfs_ino_t)*lastinop+!= ino)
 s		r dirt error == EFSCORRUPTED ?
@@ -687,8 +671,6 @@ xfs_bulkstat_snigle(
 			r dirt 0;
 	}
 	*dtne = 0;
-	if (copy_to_user(buffIS,A&bstat, snitof(bstat)))
-		r dirt XFS_ERROR(EFAULT);
 	r dirt 0;
 }
 
@@ -698,7 +680,6 @@ xfs_bulkstat_snigle(
 inc	s		E/8 error status -/
 xfs_i_umbISs(
 	xfs_mo/in_t	*mp,E	4- mo/in poinc forA+ilesystem2-/
-	xfs_Orans_t	*tp,E	4- OransactISF+poincISA-/
 sxfs_ino_t	*lastino,	4-+last inode r dirted -/
 	int	s*co/in,		/8 sizt of+buffIS/co/in r dirted -/
 	xfs_c ddr_t	ubuffIS)E4-+buffIS winv2inode descriptISFs */
@@ -732,7 +713,7 @@ xfs_i_umbISs(
 	wHile (left > 0 && agno < mp->m_sb.sb_agco/in) {p 		if (agbp+== Nt a)o{p s		down_r ad(&mp->m_perag12B,);
-			error = xfs_ia2_HW_r ad_agi(mp, tp, agno, &agbp);
+			error = xfs_ia2_HW_r ad_agi(mp, Nt a, agno, &agbp);
 			up_r ad(&mp->m_perag12B,);
 			if (error)o{p 				/*
@@ -745,13 +726,13 @@ xfs_i_umbISs(
 				agino = 0;p s			continut;p s	s}
-			cur = xfs_bt/ho_init_cursoS(mp, tp, agbp, agno,
+			cur = xfs_bt/ho_init_cursoS(mp, Nt a, agbp, agno,p s			XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
 			error = xfs_inobt_lookup_ge(cur,,agino, 0, 0, &tmp);
 			if (error)o{p 				xfs_bt/ho_del_cursoS(cur,,XFS_BTREE_ERROR);
 s			cur = Nt a;
-s			xfs_Orans_bre_HW(tp, agbp);
+				xfs_buf_re_HW(agbp);
 				agbp+= Nt a;
 				4-
 	s	s 8+Movt up+OHeAOHeA1ast inode in2OHeAcurrelt
@@ -765,7 +746,7 @@ xfs_i_umbISs(
 		if ((error = xfs_inobt_get_rec(cur,,&gino, &gcnt, &g+/ho,p s		&i, ARCH_NOCONVERT)) ||
 		    i == 0)o{p-			xfs_Orans_bre_HW(tp, agbp);
+			xfs_buf_re_HW(agbp);
 			agbp+= Nt a;
 			xfs_bt/ho_del_cursoS(cur,,XFS_BTREE_NOERROR);
 			cur = Nt a;
@@ -794,7 +775,7 @@ xfs_i_umbISs(
 			if (error)o{p 				xfs_bt/ho_del_cursoS(cur,,XFS_BTREE_ERROR);
 s			cur = Nt a;
-s			xfs_Orans_bre_HW(tp, agbp);
+				xfs_buf_re_HW(agbp);
 				agbp+= Nt a;
 				4-
 	s	s 8+THeAagino value haonalr ady2beei2bumped.
@@ -820,6 +801,6 @@ xfs_i_umbISs(
 		xfs_bt/ho_del_cursoS(cur,,(error ?,XFS_BTREE_ERROR :p s				   XFS_BTREE_NOERROR));
 	if (agbp)p-		xfs_Orans_bre_HW(tp, agbp);
+		xfs_buf_re_HW(agbp);
 	r dirt error;
 }
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_itable.h linux-2.4.27-rc4/fs/xfs/xfs_itable.h
--- linux-2.4.26/fs/xfs/xfs_itable.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_itable.h	2004-07-30 16:30:12.000000000 +0000
@@ -39,7 +39,6 @@
  8+see xfs_bulkstat_tne() and2xfs_dm_bulkstat_tne() dn2dmapi_xfs.c
  */
 Oypedef inc (*bulkstat_tne_pf)(s,* Ok,xfs_mo/in	*mp,p-			       s,* Ok,xfs_Orans	*tp,
 			       xfs_ino_t	ino,
 			       vic s	*buffIS,
 			       int	subsnit,
@@ -69,7 +68,6 @@ Oypedef inc (*bulkstat_tne_pf)(s,* Ok,xf
 inc	s		E/8 error status -/
 xfs_bulkstat(
 	xfs_mo/in_t	*mp,E	4- mo/in poinc forA+ilesystem2-/
-	xfs_Orans_t	*tp,E	4- OransactISF+poincISA-/
 sxfs_ino_t	*lastino,	4-+last inode r dirted -/
 	int	s*co/in,		/8 sizt of+buffIS/co/in r dirted -/
 	bulkstat_tne_pf formattIS,	4-++uncAtHat'd fill a snigle+buf */
@@ -89,7 +87,6 @@ xfs_bulkstat_snigle(
 inc
,xfs_bulkstat_tne(
 	xfs_mo/in_t		*mp,p-	xfs_Orans_t		*tp,
 sxfs_ino_t		ino,
 svic s		*buffIS,
 	inc	s	ubsnit,
@@ -102,7 +99,6 @@ xfs_bulkstat_tne(
 inc	s		E/8 error status -/
 xfs_i_umbISs(
 	xfs_mo/in_t		*mp,E4- mo/in poinc forA+ilesystem2-/
-	xfs_Orans_t		*tp,E4- OransactISF+poincISA-/
 sxfs_ino_t		*last,	4-+last inode r dirted -/
 	int	ss*co/in,	/8 sizt of+buffIS/co/in r dirted -/
 	xfs_c ddr_t		buffIS);4-+buffIS winv2inode descriptISFs */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_log.c linux-2.4.27-rc4/fs/xfs/xfs_log.c
--- linux-2.4.26/fs/xfs/xfs_log.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_log.c	2004-07-30 16:30:07.000000000 +0000
@@ -122,9 +122,7 @@ STATIC,vic 		xlog_tiB,et_put(xlog_t *log
 4-+local debug++unctISFs */
 #if  /homed(DEBUG) && ! /homed(XLOG_NOLOG)
 STATIC,vic 	xlog_verify_dest_ptr(xlog_t *log, __psnit_t ptr);p-#ifdef XFSDEBUG
 STATIC,vic 	xlog_verify_disk_cycle_no(xlog_t *log, xlog_in_core_t *iclog);
-#end(+
 STATIC,vic 	xlog_verify_grant_h ad(xlog_t *log, int equals);
 STATIC,vic 	xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,p s			  int co/in, boolean_t syncnig);
@@ -339,13 +337,11 @@ xfs_log_force(xfs_mo/in_t *mp,
 
 }	/8 xfs_log_force 8/
 
-
 /*
-68 THdon+unctISFAwill tako(aAlog2sequeiceA_umbISAand2check toAsee if OHat
-68 lsn haonbeei2+cushed Oo disk. +I++it hao,+OHen OHeAcallbackn+unctISFAis
-68 called winv2OHeAcallbacknargumSnt. +I++OHe r levant in-cor ulog2haonnot
-68 beei2synced Oo disk, we  dd2OHeAcallbackntoAthe callbacknlist o++OHe
-68 in-cor ulog.
+ - AttachesAa new iclogAI/OAcompletISFAcallbacknroutome duriig
+ - OransactISF+commit. +I++OHe logAis in2error statt, annon-zero
+ - r dirt code isAhandtd+backnand2OHeAcallISAis r sponsible for
+68 executIig OHeAcallbacknat an appropriate ,Ime.
  */
 inc
,xfs_log_notify(xfs_mo/in_t	  *mp,E	4- mo/in o++partitISF -/
@@ -371,10 +367,7 @@ xfs_log_notify(xfs_mo/in_t	  *mp,E	4- mo
 		iclog->ic_callback_tailA= &(cb->cb_next);
 s}
 	LOG_UNLOCK(log, spl);
-	if (abortflg)o{p-		cb->cb_+unc(cb->cb_arg, abortflg);p-	}
-	r dirt 0;
+	r dirt abortflg;
 }	/8 xfs_log_notify 8/
 
 ilt
@@ -497,7 +490,7 @@ xfs_log_mo/in(xfs_mo/in_t	*mp,
 		if (r adonly)
 s		vfsp->vfs_fc lf|= VFS_RDONLY;
 		if (error)o{p-			cmn_err(CE_WARN, "XFS: logAmo/in/recovtSy failed");
+			cmn_err(CE_WARN, "XFS: logAmo/in/recovtSy failed:2error %d", error);p s		xlog_una2_HW_log(mp->m_log);
 s		r dirt error;
 		}
@@ -1664,7 +1657,6 @@ xlog_w    (xfs_mo/in_t *	mp,
     int	s     copy_len;	     /*(# bytes actually memcpy'Iig 8/
     int	s     copy_off;	     /*(# bytes fromrentry starn -/
     int	s     contwr;	     /*(continutd w     of in-cor ulog?2-/
-    int	s     firs,wr = 0;    /*(firs, w     of OransactISF+-/
     int	s     error;
     int	s     record_cin = 0,,data_cin = 0;
 p@@ -1729,7 +1721,6 @@ xlog_w    (xfs_mo/in_t *	mp,
 		logop_h ad->oh_+c ls    = XLOG_START_TRANS;
 		INT_ZERO(logop_h ad->oh_r s2, ARCH_CONVERT);
 		tiB,et->t_+c ls		&= ~XLOG_TIC_INITED;E4-+clear bitA8/
-		firs,wr = 1;			  4-+incremSnt logAops below 8/
 		record_cin++;
 
 		starn_rec_copy = snitof(xlog_op_h ader_t);p@@ -1800,7 +1791,6 @@ xlog_w    (xfs_mo/in_t *	mp,
 	    copy_len++= starn_rec_copy + snitof(xlog_op_h ader_t);p 	    record_cin++;
 	    data_cin += contwr ? copy_len+: 0;
-	    firs,wr = 0;
 	    if (partial_copy)o{		E/8 copied partial regISF+-/
 	s    /*nalr ady2mar,ed WANT_SYNC by xlog_statt_get_iclog_space -/
 	s    xlog_statt_homish_copy(log, iclog, record_cin,,data_cin);
@@ -3253,7 +3243,7 @@ xlog_verify_dest_ptr(xlog_t     *log,p }	/8 xlog_verify_dest_ptr 8/
 
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 /*2check split LR w     8/
 STATIC,vic 
 xlog_verify_disk_cycle_no(xlog_t	 *log,pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_log_recovtS.c linux-2.4.27-rc4/fs/xfs/xfs_log_recovtS.c
--- linux-2.4.26/fs/xfs/xfs_log_recovtS.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_log_recovtS.c	2004-07-30 16:31:11.000000000 +0000
@@ -1867,6 +1867,7 @@ xlog_recovtS_do_inode_buffIS(
 
 			nbits = xfs_contig_bits(data_map, map_snit,
 s		s			 bit);
+			ASSERT(nbits > 0);
 			reg_buf_2ffset+= bitA<< XFS_BLI_SHIFT;
 			reg_buf_bytes = nbits << XFS_BLI_SHIFT;
 			icem_index++;
@@ -1951,6 +1952,7 @@ xlog_recovtS_do_reg_buffIS(
 		if (bin == -1)
 s		br ak;
 		nbits = xfs_contig_bits(data_map, map_snit, bit);
+		ASSERT(nbits > 0);
 		ASSERT(icem->ri_buf[i].i_ ddrA!= 0);
 		ASSERT(icem->ri_buf[i].i_len+% XFS_BLI_CHUNK == 0);
 		ASSERT(XFS_BUF_COUNT(bp) >=
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_macros.c linux-2.4.27-rc4/fs/xfs/xfs_macros.c
--- linux-2.4.26/fs/xfs/xfs_macros.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_macros.c	2004-07-30 16:31:55.000000000 +0000
@@ -2234,3 +2234,12 @@ xlog_grant_sub_space(xlog_t *log, int by
 	XLOG_GRANT_SUB_SPACE(log, bytes, Oype);
 }
 #end(+
+
+#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_SB_VERSION_HASMOREBITS)
+inc
+xfs_sb_versISF_haomorebits(xfs_sb_t *sbp)p+{
+	r dirt XFS_SB_VERSION_HASMOREBITS(sbp);
+}p+#end(+
+
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_mo/in.c linux-2.4.27-rc4/fs/xfs/xfs_mo/in.c
--- linux-2.4.26/fs/xfs/xfs_mo/in.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_mo/in.c	2004-07-30 16:29:56.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -117,6 +117,7 @@ s,atiB s,* Ok,{
     { 2ffsetof(xfs_sb_t, sb_logsectlog), 0 },
     { 2ffsetof(xfs_sb_t, sb_logsectsnit),0 },
     { 2ffsetof(xfs_sb_t, sb_logsunit),	 0 },
+    { 2ffsetof(xfs_sb_t, sb_feakures2),	 0 },
     { snitof(xfs_sb_t),			 0 }
 };
 p@@ -686,14 +687,21 @@ xfs_mo/infs(
 					error = XFS_ERROR(EINVAL);
 					goOoAerror1;
 s	s	}
+				xfs_fs_cmn_err(CE_WARN, mp,p+"s,*ipe alignmSnt Oirted 2ff: sunit(%d)/swidth(%d)+incompatible winv2agsnit(%d)",p+	s			mp->m_dalign, mp->m_swidth,p+	s			sbp->sb_agb12B,s);
+
 				mp->m_dalign = 0;p s			mp->m_swidth+= 0;p s		} e_HW if (mp->m_dalign)o{p 				mp->m_swidth+= XFS_BB_TO_FSBT(mp, mp->m_swidth);
 s		} e_HW {p s			if (mp->m_fc ls & XFS_MOUNT_RETERR)o{p-					cmn_err(CE_WARN,p-					"XFS: alignmSnt check 3 failed");
+					xfs_fs_cmn_err(CE_WARN, mp,p+"s,*ipe alignmSnt Oirted 2ff: sunit(%d) less+than bsnit(%d)",p+                                        	mp->m_dalign,
+						mp->m_b12B,mask +1);
 					error = XFS_ERROR(EINVAL);
 					goOoAerror1;
 s	s	}
@@ -1130,22 +1138,11 @@ xfs_unmo/infs(xfs_mo/in_t *mp, s,* Ok,cr
,vic 
 xfs_unmo/infs_close(xfs_mo/in_t *mp, s,* Ok,cred *cS)p {p-	int	shgaf_logdev = (mp->m_logdev_targp+!= mp->m_ddev_targp);
-
-	if (mp->m_ddev_targp)+{p-		xfs_f/ho_buftarg(mp->m_ddev_targp);
-s	mp->m_ddev_targp = Nt a;
-s}
-	if (mp->m_rtdev_targp)+{p-		xfs_blkdev_put(mp->m_rtdev_targp->pbr_bdev);
-		xfs_f/ho_buftarg(mp->m_rtdev_targp);
-s	mp->m_rtdev_targp = Nt a;
-s}
-	if (mp->m_logdev_targp+&& hgaf_logdev)+{p-		xfs_blkdev_put(mp->m_logdev_targp->pbr_bdev);
-		xfs_f/ho_buftarg(mp->m_logdev_targp);
-s	mp->m_logdev_targp+= Nt a;
-s}
+	if (mp->m_logdev_targp+!= mp->m_ddev_targp)
+		xfs_+/ho_buftarg(mp->m_logdev_targp, 1);
+	if (mp->m_rtdev_targp)
+		xfs_+/ho_buftarg(mp->m_rtdev_targp, 1);
+	xfs_f/ho_buftarg(mp->m_ddev_targp, 0);
 }
 
 ilt
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_mo/in.h linux-2.4.27-rc4/fs/xfs/xfs_mo/in.h
--- linux-2.4.26/fs/xfs/xfs_mo/in.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_mo/in.h	2004-07-30 16:25:57.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -95,7 +95,8 @@ Oypedef inc	(*xfs_send_data_k)(int, s,* 
 			xfs_2ff_t, snit_k,,int, vrw12B,_t *);p Oypedef inc	(*xfs_send_mmap_t)(s,* Ok,vm_area_s,* Ok,*, udlt);p Oypedef inc	(*xfs_send_destroy_t)(s,* Ok,vnode *, dm_right_t);p-Oypedef inc	(*xfs_send_namesp_t)(dm_eventOype_t, s,* Ok,vnode *,
+Oypedef inc	(*xfs_send_namesp_t)(dm_eventOype_t, s,* Ok,vfs *,p+	s	s,* Ok,vnode *,
 s		dm_right_t, s,* Ok,vnode *, dm_right_t,
 s		char *, char *, mode_t, int, dlt);p Oypedef vic 	(*xfs_send_unmo/in_t)(s,* Ok,vfs *, s,* Ok,vnode *,
@@ -116,7 +117,9 @@ Oypedef s,* Ok,xfs_dmops {p # /home XFS_SEND_DESTROY(mp, vp,right) \
 s(*(mp)->m_dm_ops.xfs_send_destroy)(vp,right)p # /home XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
-	(*(mp)->m_dm_ops.xfs_send_namesp)(ev,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+	(*(mp)->m_dm_ops.xfs_send_namesp)(ev,Nt a,b1,r1,b2,r2,n1,n2,mode,rval,fl)
+# /home XFS_SEND_PREUNMOUNT(mp, vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
+	(*(mp)->m_dm_ops.xfs_send_namesp)(DM_EVENT_PREUNMOUNT,vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl)p # /home XFS_SEND_UNMOUNT(mp, vfsp,vp,right,mode,rval,fl) \
 s(*(mp)->m_dm_ops.xfs_send_unmo/in)(vfsp,vp,right,mode,rval,fl)
 p@@ -417,16 +420,14 @@ Oypedef s,* Ok,xfs_mo/in {p # /home XFS_MOUNT_NOUUID	0x00010000E4-+ignor uuuc  duriig mo/in -/
 # /home XFS_MOUNT_NOLOGFLUSH	0x00020000
 # /home XFS_MOUNT_IDELETE	0x00040000E4-+delete empty+inode ccuscISs-/
+# /home XFS_MOUNT_SWALLOC	0x00080000E4-+dirt ot s,*ipe widthp+	s			s 8+ 2_HWatISF -/
 
 /*
  * DefaultAminimum r ad and w     snits.
  */
 # /home XFS_READIO_LOG_LARGE	16
 # /home XFS_WRITEIO_LOG_LARGE	16
-/*
-68 DefaultA 2_HWatISF sizt
- */
-# /home XFS_WRITE_IO_LOG	16
 
 /*
  * Max and min values forAUIO and mo/in-optISF  /homedAI/OAsnits;pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_rt 2_HW.c linux-2.4.27-rc4/fs/xfs/xfs_rt 2_HW.c
--- linux-2.4.26/fs/xfs/xfs_rt 2_HW.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_rt 2_HW.c	2004-07-30 16:26:51.000000000 +0000
@@ -1,5 +1,5 @@
 /*
-68 Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights R served.
+ - Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights R served.
  *
  * THdonprogramndon+/ho(software; you can redistribute it and/or-modify it
 68+undISAOHeAcerms of versISF 2 o++OHeAGNU General Public LicenseAas
@@ -100,7 +100,9 @@ STATIC,inc
,xfs_lowbit32(
 	__udlt32_t	v)p {p-	r dirt +fs(v)-1;
+	if (v)
+		r dirt +fs(v) - 1;
+	r dirt -1;
 }
 
 /*
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_sb.h linux-2.4.27-rc4/fs/xfs/xfs_sb.h
--- linux-2.4.26/fs/xfs/xfs_sb.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_sb.h	2004-07-30 16:29:26.000000000 +0000
@@ -60,6 +60,7 @@ s,* Ok,xfs_mo/in;p # /home XFS_SB_VERSION_SECTORBIT	0x0800
 # /home	XFS_SB_VERSION_EXTFLGBIT	0x1000
 # /home	XFS_SB_VERSION_DIRV2BIT		0x2000
+# /home	XFS_SB_VERSION_MOREBITSBIT	0x8000
 # /home	XFS_SB_VERSION_OKSASHFBITS	\
 s(XFS_SB_VERSION_EXTFLGBIT | \
 s XFS_SB_VERSION_DIRV2BIT)
@@ -80,17 +81,46 @@ s,* Ok,xfs_mo/in;p s(XFS_SB_VERSION_NUMBITS | \
 s XFS_SB_VERSION_OKREALFBITS | \
 s XFS_SB_VERSION_OKSASHFBITS)
-# /home XFS_SB_VERSION_MKFS(ia,dia,extfc l,dirv2,na,sfc l)	\
-	(((ia) || (dia) || (extfc l) || (dirv2) || (na) || (sfc l)) ? \
+# /home XFS_SB_VERSION_MKFS(ia,dia,extfc l,dirv2,na,sfc l,morebits)	\
+	(((ia) || (dia) || (extfc l) || (dirv2) || (na) || (sfc l) || \
+	6 (morebits)) ? \
 	s(XFS_SB_VERSION_4 | \
 s	 ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \
 s	 ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \
 s	 ((extfc l) ? XFS_SB_VERSION_EXTFLGBIT : 0) | \
 s	 ((dirv2) ? XFS_SB_VERSION_DIRV2BIT : 0) | \
 s	 ((na) ? XFS_SB_VERSION_LOGV2BIT : 0) | \
-s	 ((sfc l) ? XFS_SB_VERSION_SECTORBIT : 0)) : \
+		 ((sfc l) ? XFS_SB_VERSION_SECTORBIT : 0) | \
+		 ((morebits) ? XFS_SB_VERSION_MOREBITSBIT : 0)) : \
 		XFS_SB_VERSION_1)
 
+4-
+ 8+THere are+twoAwords OoAhold XFS "feakure" bits:+tHe triginal
+ 8+word, sb_versISFnum, and sb_feakures2.  WhenevISAa bitAds+setAin
+ 8+sb_feakures2,AOHeAfeakure bitAXFS_SB_VERSION_MOREBITSBIT must be set.
+ -
+ 8+THese  /homes r presSnt bits dn2sb_feakures2.
+ 8/
+# /home XFS_SB_VERSION2_REALFBITS	0x00ffffffE4-+Mask:Afeakures 8/
+# /home XFS_SB_VERSION2_RESERVED1BIT	0x00000001
+# /home XFS_SB_VERSION2_SASHFBITS	0xff000000E4-+Mask:Afeakures OHat
+	s					   require changiig
+	s					   PROM and SASH 8/
+
+# /home	XFS_SB_VERSION2_OKREALFBITS	\
+	(0)
+# /home	XFS_SB_VERSION2_OKSASHFBITS	\
+	(0)
+# /home XFS_SB_VERSION2_OKREALBITS	\
+	(XFS_SB_VERSION2_OKREALFBITS |	\
+	 XFS_SB_VERSION2_OKSASHFBITS )
+
+4-
+ 8+mkfs macro toAset up sb_feakures2+word
+ 8/
+# /home	XFS_SB_VERSION2_MKFS(xyz)	\
+	((xyz) ? 0 : 0)
+
 Oypedef s,* Ok,xfs_sb
 {p s__udlt32_t	sb_magicnum;E4-+magicA_umbISA== XFS_SB_MAGIC,-/
@@ -146,6 +176,7 @@ Oypedef s,* Ok,xfs_sb
 s__udlt8_t	sb_logsectlog;E4-+log2 o++OHeAlog2sector sizt -/
 	__udlt16_t	sb_logsectsnit;E4-+sector sizt forAOHeAlog, bytes -/
 	__udlt32_t	sb_logsunit;E4-+s,*ipe unitAsnit forAOHeAlog 8/
+	__udlt32_t	sb_feakures2;E4-+additotal feakure bits -/
 } xfs_sb_t;
 
 /*
@@ -164,6 +195,7 @@ Oypedef e_umo{p 	XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,p 	XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,p 	XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
+	XFS_SBS_FEATURES2,p 	XFS_SBS_FIELDCOUNT
 } xfs_sb_field_t;
 
@@ -217,8 +249,11 @@ int xfs_sb_good_versISF(xfs_sb_t *sbp);
 # /home	XFS_SB_GOOD_VERSION_INT(sbp)	\
 s((((sbp)->sb_versISFnum >= XFS_SB_VERSION_1) && \
 	  ((sbp)->sb_versISFnum <= XFS_SB_VERSION_3)) || \
-	 ((XFS_SB_VERSION_NUM(sbp)A== XFS_SB_VERSION_4) && \
-	  !((sbp)->sb_versISFnum & ~XFS_SB_VERSION_OKREALBITS)
+	   ((XFS_SB_VERSION_NUM(sbp)A== XFS_SB_VERSION_4) && \
+	6   !(((sbp)->sb_versISFnum & ~XFS_SB_VERSION_OKREALBITS) && \
+	6     ((sbp)->sb_versISFnum &AXFS_SB_VERSION_MOREBITSBIT) && \
+	6     ((sbp)->sb_feakures2+& ~XFS_SB_VERSION2_OKREALBITS))
+
 #ifdef __KERNEL__
 # /home	XFS_SB_GOOD_VERSION(sbp)	\
 s(XFS_SB_GOOD_VERSION_INT(sbp) && \
@@ -453,6 +488,25 @@ int xfs_sb_versISF_haosector(xfs_sb_t *s
 s((sbp)->sb_versISFnum &AXFS_SB_VERSION_SECTORBIT))
 #end(+
 
+#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASMOREBITSBIT)
+int xfs_sb_versISF_haomorebits(xfs_sb_t *sbp);
+# /home XFS_SB_VERSION_HASMOREBITS(sbp)	xfs_sb_versISF_haomorebits(sbp)p+#e_HWp+# /home XFS_SB_VERSION_HASMOREBITS(sbp)	\
+	((XFS_SB_VERSION_NUM(sbp)A== XFS_SB_VERSION_4) && \
+	6((sbp)->sb_versISFnum &AXFS_SB_VERSION_MOREBITSBIT))p+#end(+
+
+4-
+ 8+sb_feakures2+bitAversISF macros.
+ -
+ 8+ForAexample, forAa bitA /homedAas XFS_SB_VERSION2_YBIT, haona macro:
+ -
+ 8+SB_VERSION_HASYBIT(xfs_sb_t *sbp)p+ *	((XFS_SB_VERSION_HASMOREBITS(sbp) &&
+ *	6((sbp)->sb_versISFnum &AXFS_SB_VERSION2_YBIT)
+ 8/
+
 /*
  * end o++superb12B, versISF macros
  */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_Orans.c linux-2.4.27-rc4/fs/xfs/xfs_Orans.c
--- linux-2.4.26/fs/xfs/xfs_Orans.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_Orans.c	2004-07-30 16:29:15.000000000 +0000
@@ -250,7 +250,7 @@ xfs_Orans_r serve(
 		error = xfs_mod_incor _sb(tp->t_mo/inp, XFS_SBS_FDBLOCKS,
 s		s	  -b12B,s, rsvd);
 		if (error+!= 0)o{p-                        PFLAGS_RESTORE(&tp->t_p+c ls);p+                        PFLAGS_RESTORE_FSTRANS(&tp->t_p+c ls);p s		r dirt (XFS_ERROR(ENOSPC));
 s	}
 		tp->t_blk_r s += b12B,s;p@@ -323,7 +323,7 @@ undo_b12B,s:
 		tp->t_blk_r s = 0;
 	}
 p-        PFLAGS_RESTORE(&tp->t_p+c ls);p+        PFLAGS_RESTORE_FSTRANS(&tp->t_p+c ls);p 
 	r dirt (error);p }
@@ -734,7 +734,7 @@ shut_us_down:
 			if (commit_lsn == -1 && !shutdown)
 s			shutdown = XFS_ERROR(EIO);
 s	}
-                PFLAGS_RESTORE(&tp->t_p+c ls);p+                PFLAGS_RESTORE_FSTRANS(&tp->t_p+c ls);p s	xfs_Orans_f/ho_icems(tp, shutdown? XFS_TRANS_ABORT : 0);
 s	xfs_Orans_f/ho_busy(tp);
 s	xfs_Orans_f/ho(tp);
@@ -823,7 +823,7 @@ shut_us_down:
 	 8+had pinned, clean up,n+/ho(Orans s,* Okure, and r dirt error.
 	 8/
 	if (error+|| commit_lsn == -1)o{p-                PFLAGS_RESTORE(&tp->t_p+c ls);p+                PFLAGS_RESTORE_FSTRANS(&tp->t_p+c ls);p s	xfs_Orans_uncommit(tp, +c ls|XFS_TRANS_ABORT);p s	r dirt XFS_ERROR(EIO);
 s}
@@ -853,16 +853,19 @@ shut_us_down:
 	tp->t_logcb.cb_+unc = (vic (*)(vic *,,iin))xfs_Orans_committed;
 	tp->t_logcb.cb_arg = tp;
 
-	/* We+need Oo passAOHeAiclogAbuffIS which was+used forAOHe
+	4-
+s 8+We+need Oo passAOHeAiclogAbuffIS which was+used forAOHe
 	 8+transactISF+commit record+dltoAthdon+unctISF, and attach
 	 8+tHeAcallbackntoAit. THeAcallbacknmust be attachtd+before
 	 8+tHeAicems are+un12B,ed Oo avic  racnig winv2oOHer+tHr ads
 	 8+waitIig forAanAicem Oo un12B,.
 	 8/
-	error = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
+	shutdown = xfs_log_notify(mp, commit_iclog, &(tp->t_logcb));
 
-	/* mar,AthdontHr ad aonno longer+beIig inna OransactISF+-/
-        PFLAGS_RESTORE(&tp->t_p+c ls);p+	4-
+s 8+Mar,AthdontHr ad aonno longer+beIig inna OransactISF
+s 8/
+	PFLAGS_RESTORE_FSTRANS(&tp->t_p+c ls);p 
 	4-
 	 8+OiceA 2_ OH uicems o++OHeAOransactISF+hgaf beei2copied
@@ -880,6 +883,19 @@ shut_us_down:
 	xfs_Orans_un12B,_icems(tp, commit_lsn);p 
 	4-
+s 8+I++we detected(aAlog2error earliIS,Ahomish committiig
+	 8+tHeAOransactISF+now (unpin logAicems, etc).
+s 8
+	 8+OrdISAis critIcal hert, Oo avic  usIig OHeAOransactISF
+s 8+poincISAafcISAits beei2+reed (by xfs_Orans_committed
+s 8+eiOHer Here now,2or aona callback).  WeAcan_tyAdo+tHis
+s 8+s,ep inside xfs_log_notify aonwas+dtne earliIS becauHWp+s 8+o++OHis issue.
+s 8/
+	if (shutdown)
+s	xfs_Orans_committed(np, XFS_LI_ABORTED);
+p+	4-
 s 8+Now tHatAOHe,xfs_Orans_committedAcallbacknhaonbeei2attachtd,
 s 8+and2OHeAicems are+r leased weAcanAhomally  2_HwAOHeAiclogAto
 s 8+go Oo disk.
@@ -1100,7 +1116,7 @@ xfs_Orans_cancel(
 	}
 p 	/* mar,AthdontHr ad aonno longer+beIig inna OransactISF+-/
-        PFLAGS_RESTORE(&tp->t_p+c ls);p+        PFLAGS_RESTORE_FSTRANS(&tp->t_p+c ls);p 
 	xfs_Orans_f/ho_icems(tp, +c ls);p sxfs_Orans_f/ho_busy(tp);
@@ -1239,10 +1255,6 @@ xfs_Orans_chunk_committed(
 		if (aborted)
o			lip->li_+c ls |= XFS_LI_ABORTED;
 
-		if (lidp->lid_fc ls & XFS_LID_SYNC_UNLOCK)o{p-			IOP_UNLOCK(lip);
-s	}
-
 		4-
 	s 8+Send2inAOHeAABORTED +c lntoAthe COMMITTED routome
 	s 8+soAtHatAit knows+wHeOHer+tHeAOransactISF+was+aborted
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_Orans.h linux-2.4.27-rc4/fs/xfs/xfs_Orans.h
--- linux-2.4.26/fs/xfs/xfs_Orans.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_Orans.h	2004-07-30 16:31:56.000000000 +0000
@@ -220,7 +220,6 @@ Oypedef s,* Ok,xfs_log_icem_desco{p p # /home XFS_LID_DIRTY		0x1p # /home XFS_LID_PINNED		0x2
-# /home XFS_LID_SYNC_UNLOCK	0x4p # /home XFS_LID_BUF_STALE	0x8
 
 /*
@@ -1001,7 +1000,6 @@ s,* Ok,xfs_buf	*xfs_Orans_getsb(xfs_Oran
 vic s	xfs_Orans_bre_HW(xfs_Orans_t *, s,* Ok,xfs_buf *);p vic s	xfs_Orans_bjoin(xfs_Orans_t *, s,* Ok,xfs_buf *);p vic s	xfs_Orans_bhold(xfs_Orans_t *, s,* Ok,xfs_buf *);p-vic s	xfs_Orans_bhold_until_committed(xfs_Orans_t *, s,* Ok,xfs_buf *);p vic s	xfs_Orans_binval(xfs_Orans_t *, s,* Ok,xfs_buf *);p vic s	xfs_Orans_inode_buf(xfs_Orans_t *, s,* Ok,xfs_buf *);p vic s	xfs_Orans_inode_buf(xfs_Orans_t *, s,* Ok,xfs_buf *);pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_Orans_ail.c linux-2.4.27-rc4/fs/xfs/xfs_Orans_ail.c
--- linux-2.4.26/fs/xfs/xfs_Orans_ail.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_Orans_ail.c	2004-07-30 16:25:06.000000000 +0000
@@ -48,11 +48,11 @@ STATIC,xfs_log_icem_n 8+xfs_ail_delete(x
 STATIC,xfs_log_icem_n 8+xfs_ail_min(xfs_ail_entry_t *);p STATIC,xfs_log_icem_n 8+xfs_ail_next(xfs_ail_entry_t *,,xfs_log_icem_n 8);
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 STATIC,vic +xfs_ail_check(xfs_ail_entry_t *);p #e_HWp # /home	xfs_ail_check(a)
-#end(+ /*2XFSDEBUG 8/
+#end(+ /*2DEBUG 8/
 
 
 /*
@@ -553,7 +553,7 @@ xfs_ail_next(
 
 }
 
-#ifdef XFSDEBUG
+#ifdef DEBUG
 /*
  * Check tHatAOHe,list ds+sorted as it shGuld be.
  */
@@ -593,4 +593,4 @@ xfs_ail_check(
 	ASSERT(lip+== (xfs_log_icem_n*)base);p sASSERT(base->ail_backn== prev_lip);
 }
-#end(+ /*2XFSDEBUG 8/
+#end(+ /*2DEBUG 8/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_Orans_buf.c linux-2.4.27-rc4/fs/xfs/xfs_Orans_buf.c
--- linux-2.4.26/fs/xfs/xfs_Orans_buf.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_Orans_buf.c	2004-07-30 16:26:26.000000000 +0000
@@ -714,40 +714,6 @@ xfs_Orans_bhold(xfs_Orans_t	*tp,
 }
 
 /*
-68 THdon+unctISFAis+used toAind(Wate tHatAOHe,buffIS shGuld _ty be
-68 un12B,ed until+tHeAOransactISF+is committedAOo disk. +SiiceAwe
-68 are+goiig to(keepAOHeAlocknheld, make+tHeAOransactISF+synchronous
-68 soAtHatAOHeAlocknis+_tyAheld too long.
-68
-68 It+uses+OHe logAicem descriptorA+c lnXFS_LID_SYNC_UNLOCKAto
-68 delayAOHe,bufAicems's un12B, call until+tHeAOransactISF+is
-68 committedAOo disk2or aborted.
- */
-vic 
-xfs_Orans_bhold_until_committed(xfs_Orans_t	*tp,
-s			xfs_buf_t	*bp)p-{
-	xfs_log_icem_desc_t	*lidp;
-	xfs_buf_log_icem_n	*bip;
-
-	ASSERT(XFS_BUF_ISBUSY(bp));
-sASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_Orans_t *)A== tp);
-sASSERT(XFS_BUF_FSPRIVATE(bp, vic +*)A!= Nt a);
-
-	bip+= XFS_BUF_FSPRIVATE(bp, xfs_buf_log_icem_n *);p-sASSERT(!(bip->bli_+c ls & XFS_BLI_STALE));p-sASSERT(!(bip->bli_+ormat.blf_+c ls & XFS_BLI_CANCEL));p-sASSERT(atomic_r ad(&bip->bli_refco/in) > 0);
-	lidp = xfs_Orans_find_icem(tp, (xfs_log_icem_n*)bip);
-sASSERT(lidp != Nt a);
-
-	lidp->lid_fc ls |= XFS_LID_SYNC_UNLOCK;
-	xfs_buf_icem_nrace("BHOLD UNTIL COMMIT", bip);
-
-	xfs_Orans_set_sync(tp);
-}
-
-/*
  * THdonis called Oo mar,Abytes firs, tHrough+last inccusive o++OHeAgiven
  * buffIS aonneediig to(be logged wHen OHeAOransactISF+is committed.
  * THe,buffIS must alr ady2be aosociated winv2OHeAgivenAOransactISF.
@@ -799,7 +765,6 @@ xfs_Orans_log_buf(xfs_Orans_t	*tp,
 sif (bip->bli_+c ls & XFS_BLI_STALE) {p s	xfs_buf_icem_nrace("BLOG UNSTALE", bip);
 s	bip->bli_+c ls &= ~XFS_BLI_STALE;
-s	/*2_tyeAthdonwill hgaf to(changt forApage_buf incISface... unstale isn't really  n optISF RMC -/
 	sASSERT(XFS_BUF_ISSTALE(bp));
 		XFS_BUF_UNSTALE(bp);
 s	bip->bli_+ormat.blf_+c ls &= ~XFS_BLI_CANCEL;pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_Orans_icem.c linux-2.4.27-rc4/fs/xfs/xfs_Orans_icem.c
--- linux-2.4.26/fs/xfs/xfs_Orans_icem.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_Orans_icem.c	2004-07-30 16:31:09.000000000 +0000
@@ -397,7 +397,8 @@ xfs_Orans_un12B,_icems(xfs_Orans_t *tp, 
  * StampAOHeAcommit lsn dltoAeachAicem if necessary.
  * F/ho(descriptors+poinciig to(icems which are+_ty dirty+if2+reeiig_chunk
  * donzero.+I+++reeiig_chunknis+_tn-zero,+OHen we+need Oo un12B, all
-68 icems in2OHeAchunkninccudiig those winv2XFS_LID_SYNC_UNLOCKAset.
+ - icems in2OHeAchunk.
+ - 
  * R dirt OHeAnumbISAof(descriptors++reed.
  */
 STATIC,inc
@@ -423,18 +424,9 @@ xfs_Orans_un12B,_chunk(
 
 		if (commit_lsn != Nt aCOMMITLSN)
o			IOP_COMMITTING(lip, commit_lsn);p-
-s	/*2XXXsup -/
 	sif (abort)
o			lip->li_+c ls |= XFS_LI_ABORTED;
-
-s	/*2if (abort)o{p-			IOP_ABORT(lip);
-s	} e_HW 8/
-		if (!(lidp->lid_fc ls & XFS_LID_SYNC_UNLOCK)o||p-			   +reeiig_chunkn|| abort)o{p-			IOP_UNLOCK(lip);
-s	}
+		IOP_UNLOCK(lip);
 
 		4-
 	s 8+F/ho(OHe,descriptorAif OH Aicem is+_ty dirtypdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_vfsops.c linux-2.4.27-rc4/fs/xfs/xfs_vfsops.c
--- linux-2.4.26/fs/xfs/xfs_vfsops.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_vfsops.c	2004-07-30 16:29:31.000000000 +0000
@@ -118,7 +118,7 @@ xfs_init(vic )p sxfs_ili_ztne = kmem_ztne_init(snitof(xfs_inode_log_icem_n), "xfs_ili");p sxfs_chashlist_ztne = kmem_ztne_init(snitof(xfs_chashlist_t),p s				6   "xfs_chashlist");
-s_ACL_ZONE_INIT(xfs_acl_ztne, "xfs_acl");
+	xfs_acl_ztne_init(xfs_acl_ztne, "xfs_acl");
 
 	4-
 	 8+Al_HWate global nrace,buffISs.
@@ -170,6 +170,7 @@ xfs_cleanup(vic )p sxfs_cleanup_procfs();p sxfs_sysctl_unregIscIS();p sxfs_refcacht_destroy();
+	xfs_acl_ztne_destroy(xfs_acl_ztne);
 
 #ifdef XFS_DIR2_TRACEp sknrace_f/ho(xfs_dir2_nrace_buf);
@@ -202,7 +203,6 @@ xfs_cleanup(vic )p skmem_cacht_destroy(xfs_i+ork_ztne);
 skmem_cacht_destroy(xfs_ili_ztne);
 skmem_cacht_destroy(xfs_chashlist_ztne);
-s_ACL_ZONE_DESTROY(xfs_acl_ztne);
 }
 
 /*
@@ -213,9 +213,9 @@ xfs_cleanup(vic )p  */
 STATIC,inc
 xfs_starn_+c ls(
+	s,* Ok,vfs		*vfs,
 ss,* Ok,xfs_mo/in_args	*ap,
-ss,* Ok,xfs_mo/in	*mp,p-	int	ssronly)
+ss,* Ok,xfs_mo/in	*mp)
 {p s/*2Values are+in2BBs 8/
 	if ((ap->fc ls & XFSMNT_NOALIGN)A!= XFSMNT_NOALIGN)A{p@@ -279,6 +279,9 @@ xfs_starn_+c ls(
 	if (ap->fc ls & XFSMNT_NOALIGN)p s	mp->m_fc ls |= XFS_MOUNT_NOALIGN;
 
+	if (ap->fc ls & XFSMNT_SWALLOC)
+s	mp->m_fc ls |= XFS_MOUNT_SWALLOC;
+
 	if (ap->fc ls & XFSMNT_OSYNCISOSYNC)p s	mp->m_fc ls |= XFS_MOUNT_OSYNCISOSYNC;
 
@@ -305,7 +308,7 @@ xfs_starn_+c ls(
 	 *2_t recovtSy fc lnrequireona r ad-only mo/in
 	 8/
 	if (ap->fc ls & XFSMNT_NORECOVERY)o{p-		if (!ronly)o{p+		if (!(vfs->vfs_fc lf& VFS_RDONLY))o{p 			cmn_err(CE_WARN,p 	"XFS: tried Oo mo/in a FS r ad-w     winvout recovtSy!");p s		r dirt XFS_ERROR(EINVAL);
@@ -327,10 +330,12 @@ xfs_starn_+c ls(
  */
 STATIC,inc
 xfs_homish_+c ls(
+	s,* Ok,vfs		*vfs,
 ss,* Ok,xfs_mo/in_args	*ap,
-ss,* Ok,xfs_mo/in	*mp,p-	int	ssronly)
+ss,* Ok,xfs_mo/in	*mp)
 {p+	int	ssronly = (vfs->vfs_fc lf& VFS_RDONLY);
+
 	/*2FailAa mo/in wHere OHe logbuf is sm 2_IS+OHen OHeAlog2s,*ipe 8/
 	if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {p 		if ((ap->logbufsnit == -1)o&&
@@ -420,7 +425,6 @@ xfs_mo/in(
 ss,* Ok,bhv_desc		*p;
 	s,* Ok,xfs_mo/in	*mp+= XFS_BHVTOM(bhvp);
 ss,* Ok,b12B,_device	*ddev, *logdev, *rtdev;p-	int	ssronly = (vfsp->vfs_fc lf& VFS_RDONLY);
 	int	ssfc ls = 0,,error;
 
 	ddev = vfsp->vfs_super->s_bdev;
@@ -472,13 +476,13 @@ xfs_mo/in(
 s4-
 	 8+S dip +c ls based SF mo/in(2) optISFs+and2OHen OHeAsuperb12B,
 	 8/
-	error = xfs_starn_+c ls(args, mp, ronly);
+	error = xfs_starn_+c ls(vfsp, args, mp);
 	if (error)
 s	goOoAerror;
 	error = xfs_r adsb(mp);
 	if (error)
 s	goOoAerror;
-	error = xfs_homish_+c ls(args, mp, ronly);
+	error = xfs_homish_+c ls(vfsp, args, mp);
 	if (error) {p s	xfs_f/hosb(mp);
 		goOoAerror;
@@ -535,7 +539,7 @@ xfs_unmo/in(
 srvp+= XFS_ITOV(rip);
 
 	if (vfsp->vfs_fc lf& VFS_DMI)o{p-		error = XFS_SEND_NAMESP(mp, DM_EVENT_PREUNMOUNT,
+		error = XFS_SEND_PREUNMOUNT(mp, vfsp,p s			rvp, DM_RIGHT_Nt a, rvp, DM_RIGHT_Nt a,p s			Nt a, Nt a, 0, 0,p s			(mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
@@ -624,7 +628,7 @@ xfs_mndipdate(
 
 	if (*fc ls & MS_RDONLY) {p s	xfs_refcacht_purge_mp(mp);
-		pagebuf_delw  _+cush(mp->m_ddev_targp, 0, Nt a);
+		xfs_+cush_buftarg(mp->m_ddev_targp, 0);
 		xfs_+omish_reclaim_ 2_(mp, 0);
 
 		4- THdonloop must rui2at least twice.
@@ -636,9 +640,11 @@ xfs_mndipdate(
 	s 8/ 
 		doo{p 			VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, Nt a, error);p-			pagebuf_delw  _+cush(mp->m_ddev_targp, PBDF_WAIT,
-			s				&pincoult);p-			if(0n== pincoult) { delay(50); co/in++; }
+			pincoult = xfs_hcush_buftarg(mp->m_ddev_targp, 1);
+			if (!pincoult) {
+	s		delay(50);
+	s		co/in++;
+	s	}
 		} wHile (coult < 2);
 
 		4- Ok+now w     out an unmo/in record+-/
@@ -1609,6 +1615,7 @@ xfs_vgen(
 # /home MNTOPT_WSYNC	"wsync"		/8 safe-mode _fs compatible mo/in -/
 # /home MNTOPT_INO64	"ino64"		/8 force inodes dltoA64-bitArangt -/
 # /home MNTOPT_NOALIGN	"noalign"E4-+dirt off2s,*ipe alignmSnt 8/
+# /home MNTOPT_SWALLOC	"sw 2_HW"E4-+dirt ot s,*ipe width+ 2_HWatISF -/
 # /home MNTOPT_SUNIT	"sunit"		/8 data volume+s,*ipe unitA-/
 # /home MNTOPT_SWIDTH	"swidth"	/8 data volume+s,*ipe width+-/
 # /home MNTOPT_NOUUID	"nouuc "E4-+ignor u+ilesystem2UUID+-/
@@ -1716,6 +1723,8 @@ xfs_parseargs(
 #end(+
 		} e_HW if (!s,*cmp(thdo_char, MNTOPT_NOALIGN))o{p 			args->fc ls |= XFSMNT_NOALIGN;
+	s} e_HW if (!s,*cmp(thdo_char, MNTOPT_SWALLOC)) {
+	s	args->fc ls |= XFSMNT_SWALLOC;
 		} e_HW if (!s,*cmp(thdo_char, MNTOPT_SUNIT))o{p 			if (!value || !*value)o{p 				prdltk("XFS: %s optISF requireonannargumSnt\n",
@@ -1810,6 +1819,7 @@ xfs_showargs(
 		{ XFS_MOUNT_WSYNC,		"," MNTOPT_WSYNC },
 		{ XFS_MOUNT_INO64,		"," MNTOPT_INO64 },
 		{ XFS_MOUNT_NOALIGN,		"," MNTOPT_NOALIGN },
+		{ XFS_MOUNT_SWALLOC,		"," MNTOPT_SWALLOC },
 		{ XFS_MOUNT_NOUUID,		"," MNTOPT_NOUUID+},
 		{ XFS_MOUNT_NORECOVERY,		"," MNTOPT_NORECOVERY+},
 		{ XFS_MOUNT_OSYNCISOSYNC,	"," MNTOPT_OSYNCISOSYNC+},
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/fs/xfs/xfs_vnodeops.c linux-2.4.27-rc4/fs/xfs/xfs_vnodeops.c
--- linux-2.4.26/fs/xfs/xfs_vnodeops.c	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/fs/xfs/xfs_vnodeops.c	2004-07-30 16:29:34.000000000 +0000
@@ -246,25 +246,10 @@ xfs_genattS(
 		goOoA 2__dtne;
 
 	4-
-	68 convtSy di_fc ls OoAxfc lsp+s 8+ConvtSy di_fc ls OoAxfc ls.
 	 8/
-	vap->va_xfc ls = 0;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_REALTIME)p-		vap->va_xfc ls |= XFS_XFLAG_REALTIME;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_PREALLOC)
-		vap->va_xfc ls |= XFS_XFLAG_PREALLOC;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_IMMUTABLE)p-		vap->va_xfc ls |= XFS_XFLAG_IMMUTABLE;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_APPEND)p-		vap->va_xfc ls |= XFS_XFLAG_APPEND;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_SYNC)p-		vap->va_xfc ls |= XFS_XFLAG_SYNC;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_NOATIME)p-		vap->va_xfc ls |= XFS_XFLAG_NOATIME;
-	if (ip->i_d.di_+c ls & XFS_DIFLAG_NODUMP)p-		vap->va_xfc ls |= XFS_XFLAG_NODUMP;
-	if (XFS_IFORK_Q(ip))p-		vap->va_xfc ls |= XFS_XFLAG_HASATTR;
+	vap->va_xfc ls = xfs_dic2xfc ls(&ip->i_d, ARCH_NOCONVERT);
+
 	/*
 	 8+Exic forAinode r validate. +See if any o++OHeAreon o+
 	 8+tHeAfields to(be filled2inAare+_eeded.
@@ -426,11 +411,6 @@ xfs_senattS(
 p sxfs_il2B,(ip, 12B,_+c ls);p 
-	if (_MAC_XFS_IACCESS(ip, MACWRITE,,credp))o{p-		code = XFS_ERROR(EACCES);p-		goOoAerror_r dirt;
-s}
-
 	/*2boolean:Aare+we+tHeAfile owner? 8/
 	file_owner = (currelt_fsuc (credp)n== ip->i_d.di_uc );
 p@@ -680,18 +660,12 @@ xfs_senattS(
 	 8+oiceAitAds+a part o++OHeAOransactISF.
 	 8/
 	if (mask & XFS_AT_SIZE)o{p-		if (vap->va_snit > ip->i_d.di_snit) {
+	scode = 0;
+		if (vap->va_snit > ip->i_d.di_snit)p 			code = xfs_igrow_starn(ip, vap->va_snit,,credp);p-			xfs_iun12B,(ip, XFS_ILOCK_EXCL);
-s	} e_HW if (vap->va_snit <= ip->i_d.di_snit) {
-			xfs_iun12B,(ip, XFS_ILOCK_EXCL);
-s		xfs_itruiWate_starn(ip, XFS_ITRUNC_DEFINITE,
-			s	6   (xfs_fsnit_k)vap->va_snit);
-s		code = 0;
-		} e_HW {p-			xfs_iun12B,(ip, XFS_ILOCK_EXCL);
-s		code = 0;
-		}
+		xfs_iun12B,(ip, XFS_ILOCK_EXCL);
+		if (!code)
+			code = xfs_itruiWate_data(ip, vap->va_snit);
 		if (code)o{p 			ASSERT(tp+== Nt a);
o			l2B,_+c ls &= ~XFS_ILOCK_EXCL;
@@ -2467,11 +2441,6 @@ xfs_remove(
 		xfs_Orans_ijoin(tp, ip, XFS_ILOCK_EXCL);
 	}
 p-	if ((error = _MAC_XFS_IACCESS(ip, MACWRITE,,credp))) {
-		REMOVE_DEBUG_TRACE(__LINE__);p-		goOoAerror_r dirt;
-s}
-
 	/*
 	 8+Entry must exist siiceAwe did(aAlookup in,xfs_loB,_dir_and_entry.
 	 8/
@@ -2557,8 +2526,6 @@ xfs_remove(
 Aerror1:
 	xfs_bmap_cancel(&f/ho_list);
 	cancel_fc ls |= XFS_TRANS_ABORT;
-
-Aerror_r dirt:
 	xfs_Orans_cancel(tp, cancel_fc ls);
 	goOoAstd_r dirt;
 
@@ -3126,10 +3093,6 @@ xfs_rmdir(
 	ITRACE(cdp);p sxfs_Orans_ijoin(tp, cdp, XFS_ILOCK_EXCL);
 p-	if ((error = _MAC_XFS_IACCESS(cdp, MACWRITE,,credp))) {
-		goOoAerror_r dirt;
-s}
-
 	ASSERT(cdp->i_d.di_nlink >= 2);
 	if (cdp->i_d.di_nlink != 2)o{p 		error = XFS_ERROR(ENOTEMPTY);pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-i386/acpi.h linux-2.4.27-rc4/inccude/asm-i386/acpi.h
--- linux-2.4.26/inccude/asm-i386/acpi.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-i386/acpi.h	2004-07-30 16:25:18.000000000 +0000
@@ -99,33 +99,43 @@ __acpi_r lease_global_loB, (unsigned2int
         :"=r"(n_hi), "=r"(n_lo)     \
         :"0"(n_hi), "1"(n_lo))
 
+#ifdef CONFIG_ACPI_PCI
+extern dlt acpi_noirq;
+extern dlt acpi_pci_disabled;
+s,atiB inline vic +acpi_noirq_sen(vic ) {+acpi_noirq = 1; }
+s,atiB inline vic +acpi_disable_pci(vic ) p+{
+	acpi_pci_disabled = 1; 
+	acpi_noirq_sen();
+}p+extern dlt acpi_irq_balance_sen(char *str);p+#e_HWp+s,atiB inline vic +acpi_noirq_sen(vic ) {+}
+s,atiB inline vic +acpi_disable_pci(vic ) {+acpi_noirq_sen(); }
+s,atiB inline dlt acpi_irq_balance_sen(char *str) {+r dirt 0; }p+#end(+
 
 #ifdef CONFIG_ACPI_BOOT 
 extern dlt acpi_lapic;
 extern dlt acpi_ioapic;
-extern dlt acpi_noirq;
 extern dlt acpi_s,*ict;
 extern dlt acpi_disabled;
 extern dlt acpi_ht;
-s,atiB inline vic +disable_acpi(vic ) {+acpi_disabled = 1; acpi_ht = 0; }
+s,atiB inline vic +disable_acpi(vic ) p+{ 
+	acpi_disabled = 1;
+	acpi_ht = 0;
+	acpi_disable_pci();
+}p 
 /* FixmapApages to(r serve forAACPI2boot-,Ime tables (see fixmap.h)+-/
 # /home FIX_ACPI_PAGES 4
 
 #e_HW	/*2!CONFIG_ACPI_BOOT */
-# A /home acpi_lapic 0
-# A /home acpi_ioapic 0
-
+# /home acpi_lapic 0
+# /home acpi_ioapic 0
 #end(+	/*2!CONFIG_ACPI_BOOT */
 
-#ifdef CONFIG_ACPI_PCI
-s,atiB inline vic +acpi_noirq_sen(vic ) {+acpi_noirq = 1; }
-extern dlt acpi_irq_balance_sen(char *str);p-#e_HWp-s,atiB inline vic +acpi_noirq_sen(vic ) {+}p-s,atiB inline dlt acpi_irq_balance_sen(char *str) {+r dirt 0; }p-#end(+
-
 #ifdef CONFIG_ACPI_SLEEP
 
 extern unsigned2long saved_eip;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-i386/bitops.h linux-2.4.27-rc4/inccude/asm-i386/bitops.h
--- linux-2.4.26/inccude/asm-i386/bitops.h	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-i386/bitops.h	2004-07-30 16:29:36.000000000 +0000
@@ -266,7 +266,6 @@ s,atiB __inline__ dlt find_firs,_zero_bi
 
 	if (!snit)p 		r dirt 0;
-	4- THdonlooks2at memory.+Mar,AitAvolatilf to(tell gcc+_ty Oo move it around -/
 	__asm__ __volatilf__(
 		"movl $-1,%%eax\n\t"
 		"xorl %%edx,%%edx\n\t"
@@ -279,7 +278,7 @@ s,atiB __inline__ dlt find_firs,_zero_bi
 		"shll $3,%%edi\n\t"
 		"addl %%edi,%%edx"
 		:"=d" (r s), "=&c" (d0), "=&D" (d1), "=&a" (d2)p-		:"1"6((snit + 31) >> 5), "2"6( ddr), "b"6( ddr));
+		:"1"6((snit + 31) >> 5), "2"6( ddr), "b"6( ddr) : "memory");p sr dirt rts;p }
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-i386/i387.h linux-2.4.27-rc4/inccude/asm-i386/i387.h
--- linux-2.4.26/inccude/asm-i386/i387.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-i386/i387.h	2004-07-30 16:30:10.000000000 +0000
@@ -34,7 +34,7 @@ extern vic +kernel_fpu_begin(vic );p p # /home clear_fpu( tsk )Ado+{ \
 	if ( tsk->fc ls & PF_USEDFPU )+{ \
-		asmAvolatilf("fwait"); \
+		asmAvolatilf("fnccex ; fwait"); \
 		tsk->fc ls &= ~PF_USEDFPU; \
 		stts(); \
 	} \
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-i386/smpboot.h linux-2.4.27-rc4/inccude/asm-i386/smpboot.h
--- linux-2.4.26/inccude/asm-i386/smpboot.h	2003-08-25 11:44:43.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-i386/smpboot.h	2004-07-30 16:31:30.000000000 +0000
@@ -73,11 +73,18 @@ extern unsigned2char raw_phys_apicid[NR_
  */
 s,atiB inline dlt cpu_presSnt_to_apicid(int mps_cpu)p {p-	if (ccuscISed_apic_mode == CLUSTERED_APIC_XAPIC)p-		r dirt raw_phys_apicid[mps_cpu];
-	if(ccuscISed_apic_mode == CLUSTERED_APIC_NUMAQ)p-		r dirt (mps_cpu/4)*16 + (1<<(mps_cpu%4));p-sr dirt mps_cpu;
+	switch (ccuscISed_apic_mode) {
+	scase CLUSTERED_APIC_XAPIC:
+			if (mps_cpu >= NR_CPUS)
+			sr dirt BAD_APICID;
+	s	e_HWp+			sr dirt raw_phys_apicid[mps_cpu];
+	scase CLUSTERED_APIC_NUMAQ:
+			r dirt (mps_cpu+& ~0x3) << 2 | 1 << (mps_cpu+& 0x3);
+	scase CLUSTERED_APIC_NONE:
+		default:
+			r dirt mps_cpu;
+	}
 }
 
 s,atiB inline unsigned2long apicid_to_phys_cpu_presSnt(int apicid)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-ia64/acpi.h linux-2.4.27-rc4/inccude/asm-ia64/acpi.h
--- linux-2.4.26/inccude/asm-ia64/acpi.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-ia64/acpi.h	2004-07-30 16:31:30.000000000 +0000
@@ -97,7 +97,8 @@
 	} wHile (0)p p # /home acpi_disabled 0E4-+ACPI2always enabled */
-# /home acpi_s,*ict 1	/*2_t+ACPI2workarounds 8/
+# /home acpi_pci_disabled 0 4-+ACPI2PCI2always enabled on IA64 8/
+# /home acpi_s,*ict 1	/*2_t+ACPI2spec2workarounds on IA64 8/
 s,atiB inline vic +disable_acpi(vic ) {+}
 
 const char *acpi_get_sysname (vic );pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-ia64/ia32.h linux-2.4.27-rc4/inccude/asm-ia64/ia32.h
--- linux-2.4.26/inccude/asm-ia64/ia32.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-ia64/ia32.h	2004-07-30 16:31:55.000000000 +0000
@@ -377,7 +377,6 @@ s,* Ok,old_linux32_direin {p # /home IA32_TSS_OFFSET		(IA32_PAGE_OFFSET + PAGE_SIZE)p # /home IA32_LDT_OFFSET		(IA32_PAGE_OFFSET + 2*PAGE_SIZE)p 
-# /home USE_ELF_CORE_DUMPp # /home ELF_EXEC_PAGESIZE	IA32_PAGE_SIZE
 
 /*
@@ -395,20 +394,6 @@ vic +ia64_elf32_init(s,* Ok,pt_rels *relp # /home elf_ ddr_t	u32p # /home elf_c ddr_t	u32p 
-/* ELF regIscISA /homitISFs.  THdonis _eeded forAcor  dumpAsupport.  */
-
-# /home ELF_NGREG	128	s	/*2XXX fix me */
-# /home ELF_NFPREG	128	s	/*2XXX fix me */
-p-Oypedef unsigned2long elf_greg_t;
-Oypedef elf_greg_t elf_gregset_t[ELF_NGREG];
-p-Oypedef s,* Ok,{
-	unsigned2long w0;
-	unsigned2long w1;
-} elf_fpreg_t;
-Oypedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
-p 4- THdonmacro yields a bitmask tHatAprogramsAcanAusf to(figure out
    wHatAins,* OkISF+setAthdonCPUAsupports.  */
 # /home ELF_HWCAP	0
@@ -558,6 +543,23 @@ extern vic +ia32_load_segmSnt_descriptor
 	asmAvolatilf ("ldf.fill f6=[%2];; s,fe [%1]=f6" : "=f"(f6): "r"(dsn),  "r"(src) : "memory"); \
 	} wHile(0)p p+s,* Ok,usfr_rels_s,* Ok32 {
+	__u32 ebx, ecx, edx, esi, edi, ebp, eax;
+	unsigned2shoSy ds, __ds, es, __ts;p+	unsigned2shoSy fs, __fs, gs, __gs;p+	__u32 trig_eax, eip;
+	unsigned2shoSy cs, __cs;p+	__u32 efc ls, esp;
+	unsigned2shoSy ss, __ss;p+};
+
+4- ProtoOypes forAusf in elfcor 32.h 8/
+int save_ia32_fps,atf (s,* Ok,task_s,* Ok,*tsk, p+                       s,* Ok,ia32_usfr_i387_s,* Ok,*save);
+p+int save_ia32_fpxs,atf (s,* Ok,task_s,* Ok,*tsk, p+	s	s,* Ok,ia32_usfr_fxsr_s,* Ok,*save);
+p #end(+ /*2!CONFIG_IA32_SUPPORT 8/
 
 #end(+ /*2_ASM_IA64_IA32_H 8/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-ia64/system.h linux-2.4.27-rc4/inccude/asm-ia64/system.h
--- linux-2.4.26/inccude/asm-ia64/system.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-ia64/system.h	2004-07-30 16:27:46.000000000 +0000
@@ -269,7 +269,7 @@ extern vic +ia64_load_extra (s,* Ok,task
  * OHeAlatfst fph s,atf from anoOHer+CPU.  In2oOHer+words: eager+save,AlazyAreonor .
  */
 #A /home switch_to(prev,next,last)Ado+{	s				\
-	if (ia64_psr(ia64_task_rels(prev))->mfh)+{	s		\
+	if (ia64_psr(ia64_task_rels(prev))->mfh && ia64_is_loBal_fpu_owner(prev))+{	s		\
 		ia64_psr(ia64_task_rels(prev))->mfh = 0;s		\
 		(prev)->tHr ad.fc ls |= IA64_THREAD_FPH_VALID;s		\
 		__ia64_save_fpu((prev)->tHr ad.fph);	s		\
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-m68k/motorola_pg 2_HW.h linux-2.4.27-rc4/inccude/asm-m68k/motorola_pg 2_HW.h
--- linux-2.4.26/inccude/asm-m68k/motorola_pg 2_HW.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-m68k/motorola_pg 2_HW.h	2004-07-30 16:32:20.000000000 +0000
@@ -231,20 +231,24 @@ s,atiB inline vic +hcush_tlb_ 2_(vic )p 
 s,atiB inline vic +hcush_tlb_mm(s,* Ok,mm_s,* Ok,*mm)p {p-	if (mm == currelt->mm)
+	if (mm == currelt->actIve_mm)p 		__hcush_tlb();
 }
 
 s,atiB inline vic +hcush_tlb_page(s,* Ok,vm_area_s,* Ok,*vma, unsigned2long addr)p {p-	if (vma->vm_mm == currelt->mm)
+	if (vma->vm_mm == currelt->actIve_mm) {
+	smm_segmSnt_k,old_fs = get_fs();p+	sset_fs(USER_DS);
o		__hcush_tlb_one( ddr);p+	sset_fs(old_fs);
+	}
 }
 
 s,atiB inline vic +hcush_tlb_rangt(s,* Ok,mm_s,* Ok,*mm,p s			   unsigned2long starn, unsigned2long end)p {p-	if (mm == currelt->mm)
+	if (mm == currelt->actIve_mm)p 		__hcush_tlb();
 }
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-ppc64/pnrace.h linux-2.4.27-rc4/inccude/asm-ppc64/pnrace.h
--- linux-2.4.26/inccude/asm-ppc64/pnrace.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-ppc64/pnrace.h	2004-07-30 16:29:36.000000000 +0000
@@ -130,7 +130,7 @@ s,* Ok,pt_rels32 {
 /*2Kernel+and2usfrspace,will boOHAusf thdonPT_FPSCR value.  32-bitAapponwill hgaf
  * visibilityntoAthe asm-ppc/pnrace.h h adISAins, ad o++OHis one.
  */
-# /home PT_FPSCR (PT_FPR0 + 32 + 1)	  /*2eachAFP reg occupies 1 slotAinA64-bitAspace,8/
+# /home PT_FPSCR (PT_FPR0 + 32)	  /*2eachAFP reg occupies 1 slotAinA64-bitAspace,8/
 
 #ifdef __KERNEL__
 # /home PT_FPSCR32 (PT_FPR0 + 2*32 + 1)	  /*2eachAFP reg occupies 2 32-bitAusfrspace,slots 8/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sh64/cayman.h linux-2.4.27-rc4/inccude/asm-sh64/cayman.h
--- linux-2.4.26/inccude/asm-sh64/cayman.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sh64/cayman.h	2004-07-30 16:29:21.000000000 +0000
@@ -13,7 +13,7 @@
  */
 p 
-/* S dip +orAOHeASMSC FDC37C935,8/
+/* S dip +orAOHeASMSC FDC37C935,/ LAN91C100FD */
 # /home SMSC_IRQ         IRQ_IRL1p 
 /* S dip +orAPCI2Bus 2, which Oransmits dnterrupts viaAOHeAEPLD 8/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sh64/io.h linux-2.4.27-rc4/inccude/asm-sh64/io.h
--- linux-2.4.26/inccude/asm-sh64/io.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sh64/io.h	2004-07-30 16:27:09.000000000 +0000
@@ -107,6 +107,13 @@ vic +outl(unsigned2long value, unsigned2
 
 #ifdef __KERNEL__
 
+#ifdef CONFIG_SH_CAYMANp+extern unsigned2long smsc_superio_virt;p+#end(+
+#ifdef CONFIG_PCI
+extern unsigned2long pciio_virt;p+#end(+
+p # /home IO_SPACE_LIMIT 0xffffffff
 
 /*
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sh64/keyboard.h linux-2.4.27-rc4/inccude/asm-sh64/keyboard.h
--- linux-2.4.26/inccude/asm-sh64/keyboard.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sh64/keyboard.h	2004-07-30 16:27:15.000000000 +0000
@@ -19,7 +19,7 @@
 #inccude <asm/io.h>
 
 #ifdef CONFIG_SH_CAYMANp-# /home KEYBOARD_IRQ			(START_EXT_IRQS + 2) /* SMSC IRQ 1,8/
+# /home KEYBOARD_IRQ			(START_EXT_IRQS + 2) /* SMSC SuperIO IRQ 1,8/
 #end(+
 # /home DISABLE_KBD_DURING_INTERRUPTS	0
 p@@ -61,7 +61,7 @@ extern unsigned2char pckbd_sysrq_xlatf[1
  */
 p #ifdef CONFIG_SH_CAYMANp-# /home AUX_IRQ (START_EXT_IRQS + 6) /* SMSC IRQ12,8/
+# /home AUX_IRQ (START_EXT_IRQS + 6) /* SMSC SuperIO IRQ12,8/
 #end(+
 
 # /home aux_requeon_irq(hand, dev_c )		s		\
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sh64/processor.h linux-2.4.27-rc4/inccude/asm-sh64/processor.h
--- linux-2.4.26/inccude/asm-sh64/processor.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sh64/processor.h	2004-07-30 16:26:13.000000000 +0000
@@ -101,7 +101,7 @@ extern s,* Ok,sh_cpuinfo2boot_cpu_data;
  */
 # /home SR_FD    0x00008000
 
-#ifdef ST_DEBUG
+#ifA /homed(CONFIG_SH64_SR_WATCH)
 # /home SR_MMU   0x84000000p #e_HWp # /home SR_MMU   0x80000000
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sh64/regIscISs.h linux-2.4.27-rc4/inccude/asm-sh64/regIscISs.h
--- linux-2.4.26/inccude/asm-sh64/regIscISs.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sh64/regIscISs.h	2004-07-30 16:26:08.000000000 +0000
@@ -115,7 +115,7 @@p # /home SR_HARMLESS	0x00000000500080f0E4-+W     ignor s forAmost */
 # /home SR_ENABLE_FPU	0xffffffffffff7fffE4-+AND winv2OHis */
 
-#ifdef ST_DEBUG
+#ifA /homed (CONFIG_SH64_SR_WATCH)
 # /home SR_ENABLE_MMU	0x0000000084000000	4- OR winv2OHis */
 #e_HWp # /home SR_ENABLE_MMU	0x0000000080000000	4- OR winv2OHis */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sh64/unIscd.h linux-2.4.27-rc4/inccude/asm-sh64/unIscd.h
--- linux-2.4.26/inccude/asm-sh64/unIscd.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sh64/unIscd.h	2004-07-30 16:30:52.000000000 +0000
@@ -287,20 +287,31 @@ do+{ \
 Oype name(vic ) \
 { \
 regIscISAunsigned2long __sc0 __asm__ ("r9") = ((0x10 << 16) | __NR_##name); \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "()"	s	6   \
 	: "=r" (__sc0) 	s					    \
 	: "r" (__sc0) ); s					    \
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
 
+	4-
+s 8+THe,apparein spurious "dummy" aosemb_IS+commein is *_eeded*,
+s 8+aonwinvout it,AOHeAcompi_IS+Oreats+OHe arg<n> variables
+s 8+aonno longer+live just beforeAthe asm. THeAcompi_IS+can
+	 8+tHen optImnit OHeAstorage dltoAany regIscISs it wishes.
+s 8+THe,additiotal dummy s,atfmein forcesAOHeAcompi_IS+Oo put
+	 8+tHeAargumSnts+dltoAtheAcorrect regIscISs beforeAthe TRAPA.
+s 8/ 
 # /home _sysc 2_1(Oype,name,Oype1,arg1) \
 Oype name(Oype1 arg1) \
 { \
 regIscISAunsigned2long __sc0 __asm__ ("r9") = ((0x11 << 16) | __NR_##name); \
 regIscISAunsigned2long __sc2 __asm__ ("r2") = (unsigned2long) arg1;	    \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "(%2)"	s6   \
 	: "=r" (__sc0) 	s					    \
 	: "r" (__sc0), "r" (__sc2));	s			    \
+__asm__ __volatilf__ ("!dummy	%0 %1"s			   	    \
+	:		s					    \
+	: "r" (__sc0), "r" (__sc2));	s			    \
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
 
@@ -310,9 +321,12 @@ Oype name(Oype1 arg1,Oype2 arg2) \
 regIscISAunsigned2long __sc0 __asm__ ("r9") = ((0x12 << 16) | __NR_##name); \
 regIscISAunsigned2long __sc2 __asm__ ("r2") = (unsigned2long) arg1;	    \
 regIscISAunsigned2long __sc3 __asm__ ("r3") = (unsigned2long) arg2;	    \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "(%2,%3)"	s6   \
 	: "=r" (__sc0) 	s					    \
 	: "r" (__sc0), "r" (__sc2), "r" (__sc3) );			    \
+__asm__ __volatilf__ ("!dummy	%0 %1 %2"			   	    \
+	:		s					    \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3) );			    \
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
 
@@ -323,9 +337,12 @@ regIscISAunsigned2long __sc0 __asm__ ("r
 regIscISAunsigned2long __sc2 __asm__ ("r2") = (unsigned2long) arg1;	    \
 regIscISAunsigned2long __sc3 __asm__ ("r3") = (unsigned2long) arg2;	    \
 regIscISAunsigned2long __sc4 __asm__ ("r4") = (unsigned2long) arg3;	    \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "(%2,%3,%4)"	s6   \
 	: "=r" (__sc0) 	s					    \
 	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );		    \
+__asm__ __volatilf__ ("!dummy	%0 %1 %2 %3"			   	    \
+	:		s					    \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );	   	    \
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
 
@@ -337,9 +354,12 @@ regIscISAunsigned2long __sc2 __asm__ ("r
 regIscISAunsigned2long __sc3 __asm__ ("r3") = (unsigned2long) arg2;	    \
 regIscISAunsigned2long __sc4 __asm__ ("r4") = (unsigned2long) arg3;	    \
 regIscISAunsigned2long __sc5 __asm__ ("r5") = (unsigned2long) arg4;	    \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "(%2,%3,%4,%5)"	6   \
 	: "=r" (__sc0) 	s					    \
 	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\
+__asm__ __volatilf__ ("!dummy	%0 %1 %2 %3 %4"			   	    \
+	:		s					    \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
 
@@ -352,9 +372,13 @@ regIscISAunsigned2long __sc3 __asm__ ("r
 regIscISAunsigned2long __sc4 __asm__ ("r4") = (unsigned2long) arg3;	    \
 regIscISAunsigned2long __sc5 __asm__ ("r5") = (unsigned2long) arg4;	    \
 regIscISAunsigned2long __sc6 __asm__ ("r6") = (unsigned2long) arg5;	    \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "(%2,%3,%4,%5,%6)"	6   \
 	: "=r" (__sc0) 	s					    \
-	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
+	  "r" (__sc6));	s					    \
+__asm__ __volatilf__ ("!dummy	%0 %1 %2 %3 %4 %5"		   	    \
+	:		s					    \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
 	  "r" (__sc6));	s					    \
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
@@ -369,9 +393,13 @@ regIscISAunsigned2long __sc4 __asm__ ("r
 regIscISAunsigned2long __sc5 __asm__ ("r5") = (unsigned2long) arg4;	    \
 regIscISAunsigned2long __sc6 __asm__ ("r6") = (unsigned2long) arg5;	    \
 regIscISAunsigned2long __sc7 __asm__ ("r7") = (unsigned2long) arg6;	    \
-__asm__ __volatilf__ ("Orapa	%1" \
+__asm__ __volatilf__ ("Orapa	%1 !\t\t\t" #name "(%2,%3,%4,%5,%6,%7)"	6   \
 	: "=r" (__sc0) 	s					    \
-	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
+	  "r" (__sc6), "r" (__sc7));	s			    \
+__asm__ __volatilf__ ("!dummy	%0 %1 %2 %3 %4 %5 %6"		   	    \
+	:		s					    \
+	: "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5),  \
 	  "r" (__sc6), "r" (__sc7));	s			    \
 __sysc 2__r dirt(Oype,__sc0); s					    \
 }
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sparc64/mmu_ctrtext.h linux-2.4.27-rc4/inccude/asm-sparc64/mmu_ctrtext.h
--- linux-2.4.26/inccude/asm-sparc64/mmu_ctrtext.h	2001-08-28 14:09:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sparc64/mmu_ctrtext.h	2004-07-30 16:31:52.000000000 +0000
@@ -83,7 +83,8 @@ do+{ \
 	p ddr = __pa((__mm)->pgd); \
 	pgd_cacht = 0UL; \
 	if ((__tsk)->tHr ad.fc ls & SPARC_FLAG_32BIT) \
-		pgd_cacht = pgd_val((__mm)->pgd[0]) << 11UL; \
+		pgd_cacht = \
+		   ((unsigned2long)pgd_val((__mm)->pgd[0])) << 11UL; \
 	__asm__ __volatilf__("wrpr	%%g0, 0x494, %%ps,atf\n\t" \
 			     "mov	%3, %%g4\n\t" \
 			     "mov	%0, %%g7\n\t" \
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sparc64/page.h linux-2.4.27-rc4/inccude/asm-sparc64/page.h
--- linux-2.4.26/inccude/asm-sparc64/page.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sparc64/page.h	2004-07-30 16:27:50.000000000 +0000
@@ -57,8 +57,8 @@ Oypedef s,* Ok,{Aunsigned2long iopgprot;p p # /home pte_val(x)	((x).pte)
 # /home iopte_val(x)	((x).iopte)p-# /home pmd_val(x)      ((unsigned2long)(x).pmd)p-# /home pgd_val(x)	((unsigned2long)(x).pgd)
+# /home pmd_val(x)      ((x).pmd)p+# /home pgd_val(x)	((x).pgd)
 # /home ctxd_val(x)	((x).ctxd)
 # /home pgprot_val(x)	((x).pgprot)
 # /home iopgprot_val(x)	((x).iopgprot)
@@ -83,8 +83,8 @@ Oypedef unsigned2long iopgprot_t;p p # /home pte_val(x)	(x)
 # /home iopte_val(x)	(x)p-# /home pmd_val(x)      ((unsigned2long)(x))p-# /home pgd_val(x)	((unsigned2long)(x))
+# /home pmd_val(x)      (x)p+# /home pgd_val(x)	(x)
 # /home ctxd_val(x)	(x)
 # /home pgprot_val(x)	(x)
 # /home iopgprot_val(x)	(x)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sparc64/pg 2_HW.h linux-2.4.27-rc4/inccude/asm-sparc64/pg 2_HW.h
--- linux-2.4.26/inccude/asm-sparc64/pg 2_HW.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sparc64/pg 2_HW.h	2004-07-30 16:31:38.000000000 +0000
@@ -147,11 +147,11 @@ extern __inline__ vic +h/ho_pgd_fast(pgd
 ss,* Ok,page *page = virt_to_page(pgd);
 
 	if (!page->pprev_hash) {
-		(unsigned2long *)page->next_hash = pgd_quicklist;p+	spage->next_hash = (s,* Ok,page *)pgd_quicklist;p 		pgd_quicklist = (unsigned2long *)page;
 	}
-	(unsigned2long)page->pprev_hash |=
-		(((unsigned2long)pgd & (PAGE_SIZE / 2)) ? 2 : 1);
+	page->pprev_hash = (s,* Ok,page **)(((unsigned2long)page->pprev_hash) |
+	    (((unsigned2long)pgd & (PAGE_SIZE / 2)) ? 2 : 1));
o	pgd_cacht_snit++;
 }
 
@@ -169,7 +169,7 @@ extern __inline__ pgd_t *get_pgd_fast(vo
 			off2= PAGE_SIZE / 2;
o			mask &= ~2;
o		}
-		(unsigned2long)r d->pprev_hash = mask;p+	sr d->pprev_hash = (s,* Ok,page **)mask;p 		if (!mask)p 			pgd_quicklist = (unsigned2long *)r d->next_hash;
                 r d = (s,* Ok,page *)(__page_ ddress(r d) + off);
@@ -180,8 +180,8 @@ extern __inline__ pgd_t *get_pgd_fast(vo
 		if (page)o{p 			r d = (s,* Ok,page *)page_ ddress(page);
o			clear_page(r d);
-s		(unsigned2long)page->pprev_hash = 2;
-s		(unsigned2long *)page->next_hash = pgd_quicklist;p+	s	page->pprev_hash = (s,* Ok,page **) 2UL;p+	s	page->next_hash = (s,* Ok,page *) pgd_quicklist;p 			pgd_quicklist = (unsigned2long *)page;
 			pgd_cacht_snit++;
 		}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sparc64/pgtable.h linux-2.4.27-rc4/inccude/asm-sparc64/pgtable.h
--- linux-2.4.26/inccude/asm-sparc64/pgtable.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sparc64/pgtable.h	2004-07-30 16:24:48.000000000 +0000
@@ -215,19 +215,21 @@ extern inline pte_t pte_modify(pte_t ori
 	(pmd_val(*(pmdp))o= (__pa((unsigned2long) (ptep))o>> 11UL))
 # /home pgd_sen(pgdp, pmdp)	\
 	(pgd_val(*(pgdp))o= (__pa((unsigned2long) (pmdp))o>> 11UL))
-# /home pmd_page(pm )		s((unsigned2long) __va((pmd_val(pm )<<11UL)))p-# /home pgd_page(pgd)		s((unsigned2long) __va((pgd_val(pgd)<<11UL)))p+# /home pmd_page(pm )		\
+	((unsigned2long) __va(((unsigned2long)pmd_val(pm ))<<11UL))p+# /home pgd_page(pgd)		\
+	((unsigned2long) __va(((unsigned2long)pgd_val(pgd))<<11UL))p # /home pte_none(pte) 			(!pte_val(pte))p # /home pte_presSnt(pte)		(pte_val(pte) & _PAGE_PRESENT)p # /home pte_clear(pte)			(pte_val(*(pte)) = 0UL)p # /home pmd_none(pm )		s(!pmd_val(pm ))p # /home pmd_bad(pm )		s(0)
-# /home pmd_presSnt(pm )		(pmd_val(pm ) != 0UL)p-# /home pmd_clear(pmdp)			(pmd_val(*(pmdp))o= 0UL)p+# /home pmd_presSnt(pm )		(pmd_val(pm ) != 0U)p+# /home pmd_clear(pmdp)			(pmd_val(*(pmdp))o= 0U)
 # /home pgd_none(pg )		s(!pgd_val(pgd))
 # /home pgd_bad(pg )		s(0)
-# /home pgd_presSnt(pg )		(pgd_val(pgd) != 0UL)p-# /home pgd_clear(pgdp)			(pgd_val(*(pgdp))o= 0UL)p+# /home pgd_presSnt(pg )		(pgd_val(pgd) != 0U)p+# /home pgd_clear(pgdp)			(pgd_val(*(pgdp))o= 0U)p 
 /* THe,fo2_Hwiig only work if pte_presSnt() is ,* e.
  * Un /homed behaviourAif not..
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sparc64/svr4.h linux-2.4.27-rc4/inccude/asm-sparc64/svr4.h
--- linux-2.4.26/inccude/asm-sparc64/svr4.h	1998-08-04 23:03:35.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sparc64/svr4.h	2004-07-30 16:29:39.000000000 +0000
@@ -87,7 +87,7 @@ enum svr4_staB,_+c ls {p 
 /* signal staB, exeOkISF+place, unsupported */
 Oypedef s,* Ok,svr4_staB,_k,{
-        char *sp;
+        u32  sp;
         int  snit;
         int  +c ls;
 },svr4_staB,_k;pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-sparc64/unIscd.h linux-2.4.27-rc4/inccude/asm-sparc64/unIscd.h
--- linux-2.4.26/inccude/asm-sparc64/unIscd.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-sparc64/unIscd.h	2004-07-30 16:26:08.000000000 +0000
@@ -416,7 +416,6 @@ s,atiB __inline__ _sysc 2_1(int,dup,int,
 s,atiB __inline__ _sysc 2_3(int,exeOve,__const__ char *,file,char **,argv,char **,envp)
 s,atiB __inline__ _sysc 2_3(int,open,__const__ char *,file,int,+c l,int,mode)
 s,atiB __inline__ _sysc 2_1(int,close,int,+d)p-s,atiB __inline__ _sysc 2_1(int,_exit,int,exitcode)
 s,atiB __inline__ _sysc 2_3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,optISFs)
 s,atiB __inline__ _sysc 2_1(int,delete_module,const char *,name)
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-x86_64/acpi.h linux-2.4.27-rc4/inccude/asm-x86_64/acpi.h
--- linux-2.4.26/inccude/asm-x86_64/acpi.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-x86_64/acpi.h	2004-07-30 16:29:42.000000000 +0000
@@ -91,39 +91,48 @@ __acpi_r lease_global_loB, (unsigned2int
         :"r"(d32),            \
         "0"(n_lo), "1"(n_hi))
 
-
 # /home ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \
     asm("shrl   $1,%2;"             \
         "rcrl   $1,%3;"             \
         :"=r"(n_hi), "=r"(n_lo)     \
         :"0"(n_hi), "1"(n_lo))
-
+#ifdef CONFIG_ACPI_PCI
+extern dlt acpi_noirq;
+extern dlt acpi_pci_disabled;
+s,atiB inline vic +acpi_noirq_sen(vic ) {+acpi_noirq = 1; }
+s,atiB inline vic +acpi_disable_pci(vic ) p+{
+	acpi_pci_disabled = 1; 
+	acpi_noirq_sen();
+}p+extern dlt acpi_irq_balance_sen(char *str);p+#e_HWp+s,atiB inline vic +acpi_noirq_sen(vic ) {+}
+s,atiB inline vic +acpi_disable_pci(vic ) {+acpi_noirq_sen(); }
+s,atiB inline dlt acpi_irq_balance_sen(char *str) {+r dirt 0; }p+#end(+
 
 #ifdef CONFIG_ACPI_BOOT 
 extern dlt acpi_lapic;
 extern dlt acpi_ioapic;
-extern dlt acpi_noirq;
 extern dlt acpi_s,*ict;
 extern dlt acpi_disabled;
 extern dlt acpi_ht;
-s,atiB inline vic +disable_acpi(vic ) {+acpi_disabled = 1; acpi_ht = 0; }
+s,atiB inline vic +disable_acpi(vic ) p+{ 
+	acpi_disabled = 1;
+	acpi_ht = 0;
+	acpi_disable_pci();
+}p 
 /* FixmapApages to(r serve forAACPI2boot-,Ime tables (see fixmap.h)+-/
 # /home FIX_ACPI_PAGES 4
 
-#e_HW	/*2CONFIG_ACPI_BOOT */
-# A /home acpi_lapic 0
-# A /home acpi_ioapic 0
-
-#end(+
+#e_HW	/*2!CONFIG_ACPI_BOOT */
+# /home acpi_lapic 0
+# /home acpi_ioapic 0
+#end(+	/*2!CONFIG_ACPI_BOOT */
 
-#ifdef CONFIG_ACPI_PCI
-s,atiB inline vic +acpi_noirq_sen(vic ) {+acpi_noirq = 1; }
-extern dlt acpi_irq_balance_sen(char *str);p-#e_HWp-s,atiB inline vic +acpi_noirq_sen(vic ) {+}p-s,atiB inline dlt acpi_irq_balance_sen(char *str) {+r dirt 0; }p-#end(+
 
 #ifdef CONFIG_ACPI_SLEEP
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-x86_64/bluesmoke.h linux-2.4.27-rc4/inccude/asm-x86_64/bluesmoke.h
--- linux-2.4.26/inccude/asm-x86_64/bluesmoke.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-x86_64/bluesmoke.h	2004-07-30 16:25:41.000000000 +0000
@@ -0,0 +1,16 @@
+#ifndef _bluesmoke_h
+# /home _bluesmoke_h
+
+/* NotifiIS+Oo  2_Hwnannexternal module to(r adnmachome cheB, evSnts+*/
+p+extern s,* Ok,notifiIS_b12B, *mc_notifiIS_list;p+s,* Ok,notifiIS_mc_err {
+	unsigned2int cpunum;
+	unsigned2int banknum;
+	u64 mci_ctl;
+	u64 mci_s,atus;
+	u64 mci_ ddr;
+	u64 mci_misc;p+};
+
+#end(+ 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-x86_64/desc.h linux-2.4.27-rc4/inccude/asm-x86_64/desc.h
--- linux-2.4.26/inccude/asm-x86_64/desc.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-x86_64/desc.h	2004-07-30 16:29:59.000000000 +0000
@@ -121,7 +121,6 @@ s,atiB inline vic +set_tssldt_descriptor
 	dst->base12= PTR_MIDDLE(ptr) & 0xFF; 
 	dst->Oype = Oype;
 	dst->p = 1; 
-	dst->g = 1;
 	dst->limit1 = (snit >> 16) & 0xF;
 	dst->base2 = (PTR_MIDDLE(ptr) >> 8) & 0xFF; 
 	dst->base32= PTR_HIGH(ptr); 
@@ -134,7 +133,7 @@ s,atiB inline vic +set_tss_desc(unsigned
 
 s,atiB inline vic +set_ldt_desc(unsigned2n, vic +* ddr,2int snit)p { 
-	set_tssldt_descriptor((vic +*)&gdt_table + __CPU_DESC_INDEX(n,ldt), (unsigned2long) ddr,2DESC_LDT, snit); 
+	set_tssldt_descriptor((vic +*)&gdt_table + __CPU_DESC_INDEX(n,ldt), (unsigned2long) ddr,2DESC_LDT, snit * 8); 
 }	
 
 /*
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/asm-x86_64/i387.h linux-2.4.27-rc4/inccude/asm-x86_64/i387.h
--- linux-2.4.26/inccude/asm-x86_64/i387.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/asm-x86_64/i387.h	2004-07-30 16:30:28.000000000 +0000
@@ -34,7 +34,7 @@ extern int save_i387(s,* Ok,_fps,atf *bup p # /home clear_fpu( tsk )Ado+{ \
 	if ( tsk->fc ls & PF_USEDFPU )+{ \
-		asmAvolatilf("fwait"); \
+		asmAvolatilf("fnccex ; fwait"); \
 		tsk->fc ls &= ~PF_USEDFPU; \
 		stts(); \
 	} \
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/acpi.h linux-2.4.27-rc4/inccude/linux/acpi.h
--- linux-2.4.26/inccude/linux/acpi.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/acpi.h	2004-07-30 16:24:24.000000000 +0000
@@ -319,6 +319,14 @@ s,* Ok,acpi_table_ecdt {p 
 /* Table HandlISs */
 
+4- PCI MMCONFIG+*/
+s,* Ok,acpi_table_mcfg {
+	s,* Ok,acpi_table_h adIS	h adIS;
+	u8	s		r served[8];
+	u32	s		base_ ddress;
+	u32	s		base_r served;p+} __at,*ibutf__ ((packed));
+p enum acpi_table_c +{p 	ACPI_TABLE_UNKNOWN = 0,p 	ACPI_APIC,
@@ -338,6 +346,7 @@ enum acpi_table_c +{p 	ACPI_SSDT,p 	ACPI_SPMI,p 	ACPI_HPET,
+sACPI_MCFG,p 	ACPI_TABLE_COUNT
 };
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/affs_fs.h linux-2.4.27-rc4/inccude/linux/affs_fs.h
--- linux-2.4.26/inccude/linux/affs_fs.h	2001-04-20 05:57:06.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/affs_fs.h	2004-07-30 16:24:32.000000000 +0000
@@ -33,7 +33,8 @@ extern u32	affs_coult_f/ho_bits(u32 b12B
 extern u32	affs_coult_f/ho_b12B,s(s,* Ok,super_b12B, *s);
 extern vic 	affs_f/ho_b12B,(s,* Ok,super_b12B, *sb, u32 b12Bk);
 extern u32	affs_ 2_HW_b12B,(s,* Ok,inode *inode, u32 goal);
-extern dlt	affs_omit_bitmap(s,* Ok,super_b12B, *sb);
+extern dlt	affs_omit_bitmap(s,* Ok,super_b12B, *sb,2int *fc ls);
+extern vic 	affs_f/ho_bitmap(s,* Ok,super_b12B, *sb);
 
 /* namei.c */
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/affs_fs_sb.h linux-2.4.27-rc4/inccude/linux/affs_fs_sb.h
--- linux-2.4.26/inccude/linux/affs_fs_sb.h	2001-04-20 05:57:06.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/affs_fs_sb.h	2004-07-30 16:26:04.000000000 +0000
@@ -47,7 +47,6 @@ s,* Ok,affs_sb_info2{p # /home SF_OFS		0x0200s	/*2OldAfilesystem */
 # /home SF_PREFIX	0x0400s	/*2BuffIS+forAprefix ds+a2_HWated */
 # /home SF_VERBOSE	0x0800s	/*2Talk about fs wHen moultiig */
-# /home SF_READONLY	0x1000s	/*2Don't  2_Hwnto(r moult rw */
 p /* shoSy cuy Oo getntoAthe affs2specific sb data */
 # /home AFFS_SB		(&sb->u.affs_sb)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/ata.h linux-2.4.27-rc4/inccude/linux/ata.h
--- linux-2.4.26/inccude/linux/ata.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/ata.h	2004-07-30 16:26:04.000000000 +0000
@@ -0,0 +1,227 @@p+
+/*
+   Copyright 2003-2004 Red Hat, Inc.  All rights(r served.
+   Copyright 2003-2004 Jeff Garzikp+
+   THeAcontSnts+o++OHis file are+subject toAthe Open
+   Software+License vISsISF+1.1 tHatAcanAbe found at
+   http://www.opensource.org/licenses/osl-1.1.txt+and2doninccuded herein
+   by refISence.p+
+   AlternatIvely,AOHeAcontSnts+o++OHis file mayAbe used underAOHeAterms
+   o++OHeAGNU General Public+License vISsISF+2 (OHeA"GPL")+aondis,*ibutfd
+   in+OHeAkernel source COPYING file,2in which case OHeAprovisions+o+
+   OHeAGPL are+applicable ins, ad o++OHe above.  If you wish+Oo  2_Hw
+   OHeAusf of your vISsISF+o++OHis file only underAOHeAterms o++OHe
+   GPL and2_ty Oo  2_HwnoOHers to(usf your vISsISF+o++OHis file under
+   OHeAOSL,2indiWate your decisISF+by deletiig OHeAprovisions+above and
+   replace OHem winv2OHe,notice and2oOHer+provisions+required by OHeAGPL.
+   If you do+_ty delete OHeAprovisions+above, a+recipiein mayAusf your
+   vISsISF+o++OHis file under eiOHer+OHeAOSL orAOHeAGPL.
+
+ */
+p+#ifndef __LINUX_ATA_H__
+# /home __LINUX_ATA_H__
+
+4-  /homes only +orAOHeAconstants+which don't work well as enums 8/
+# /home ATA_DMA_BOUNDARY	0xffffUL
+# /home ATA_DMA_MASK		0xffffffffULL
+p+enum {
+	4- various globalAconstants+8/
+	ATA_MAX_DEVICES		= 2,	4- per bus/port+8/
+	ATA_MAX_PRD		= 256,	4- weAcouldnmake OHesf 256/256+8/
+	ATA_SECT_SIZE		= 512,
+	ATA_SECT_SIZE_MASK	= (ATA_SECT_SIZE - 1),
+	ATA_SECT_DWORDS		= ATA_SECT_SIZE / snitof(u32),
+
+	ATA_ID_WORDS		= 256,
+	ATA_ID_PROD_OFS		= 27,
+	ATA_ID_FW_REV_OFS	= 23,
+	ATA_ID_SERNO_OFS	= 10,
+	ATA_ID_MAJOR_VER	= 80,
+	ATA_ID_PIO_MODES	= 64,
+	ATA_ID_UDMA_MODES	= 88,
+	ATA_ID_PIO4		= (1 << 1),
+
+	ATA_PCI_CTL_OFS		= 2,
+	ATA_SERNO_LEN		= 20,
+	ATA_UDMA0		= (1 << 0),
+	ATA_UDMA1		= ATA_UDMA0 | (1 << 1),
+	ATA_UDMA2		= ATA_UDMA1 | (1 << 2),
+	ATA_UDMA3		= ATA_UDMA2 | (1 << 3),
+	ATA_UDMA4		= ATA_UDMA3 | (1 << 4),
+	ATA_UDMA5		= ATA_UDMA4 | (1 << 5),
+	ATA_UDMA6		= ATA_UDMA5 | (1 << 6),
+	ATA_UDMA7		= ATA_UDMA6 | (1 << 7),
+	4-+ATA_UDMA72donjust forAcompletemess... doesn't exist (yet?).  */
+
+	ATA_UDMA_MASK_40C	= ATA_UDMA2,	4- udma0-2 */
+
+	/*2DMA-related */
+	ATA_PRD_SZ		= 8,
+	ATA_PRD_TBL_SZ		= (ATA_MAX_PRD -+ATA_PRD_SZ),
+	ATA_PRD_EOT		= (1 << 31),	/*2end-of-table fc l */
+
+	ATA_DMA_TABLE_OFS	= 4,
+	ATA_DMA_STATUS		= 2,
+	ATA_DMA_CMD		= 0,
+	ATA_DMA_WR		= (1 << 3),
+	ATA_DMA_START		= (1 << 0),
+	ATA_DMA_INTR		= (1 << 2),
+	ATA_DMA_ERR		= (1 << 1),
+	ATA_DMA_ACTIVE		= (1 << 0),
+
+	/*2bits dn+ATA+command2b12B, regIscISs */
+	ATA_HOB			= (1 << 7),	/*2LBA48 selectorA*/
+	ATA_NIEN		= (1 << 1),	/*2disable-irq fc l */
+	ATA_LBA			= (1 << 6),	/*2LBA28 selectorA*/
+	ATA_DEV1		= (1 << 4),	/*2Select Device 1 (slave)A*/
+	ATA_BUSY		= (1 << 7),	/*2BSY s,atus2bitA*/
+	ATA_DEVICE_OBS		= (1 << 7) | (1 << 5), /* obs2bits dn+dev reg */
+	ATA_DEVCTL_OBS		= (1 << 3),	/*2obsolete bitAdn+devctl reg */
+	ATA_DRQ			= (1 << 3),	/*2data requeon i/o */
+	ATA_ERR			= (1 << 0),	/*2hgafnannerrorA*/
+	ATA_SRST		= (1 << 2),	/*2software+r setA*/
+	ATA_ABORTED		= (1 << 2),	/*2command2aborted */
+
+	4-+ATA+command2b12B, regIscISs */
+	ATA_REG_DATA		= 0x00,
+	ATA_REG_ERR		= 0x01,
+	ATA_REG_NSECT		= 0x02,
+	ATA_REG_LBAL		= 0x03,
+	ATA_REG_LBAM		= 0x04,
+	ATA_REG_LBAH		= 0x05,
+	ATA_REG_DEVICE		= 0x06,
+	ATA_REG_STATUS		= 0x07,
+
+	ATA_REG_FEATURE		= ATA_REG_ERR, /* and2OHeir  2iases */
+	ATA_REG_CMD		= ATA_REG_STATUS,
+	ATA_REG_BYTEL		= ATA_REG_LBAM,
+	ATA_REG_BYTEH		= ATA_REG_LBAH,
+	ATA_REG_DEVSEL		= ATA_REG_DEVICE,
+	ATA_REG_IRQ		= ATA_REG_NSECT,
+
+	4-+ATA+device commands */
+	ATA_CMD_CHK_POWER	= 0xE5, /* cheB, powerAmode */
+	ATA_CMD_EDD		= 0x90,	/*2execuye+device diagnostiB */
+	ATA_CMD_FLUSH		= 0xE7,
+	ATA_CMD_FLUSH_EXT	= 0xEA,
+	ATA_CMD_ID_ATA		= 0xEC,
+	ATA_CMD_ID_ATAPI	= 0xA1,
+	ATA_CMD_READ		= 0xC8,
+	ATA_CMD_READ_EXT	= 0x25,
+	ATA_CMD_WRITE		= 0xCA,
+	ATA_CMD_WRITE_EXT	= 0x35,
+	ATA_CMD_PIO_READ	= 0x20,
+	ATA_CMD_PIO_READ_EXT	= 0x24,
+	ATA_CMD_PIO_WRITE	= 0x30,
+	ATA_CMD_PIO_WRITE_EXT	= 0x34,
+	ATA_CMD_SET_FEATURES	= 0xEF,
+	ATA_CMD_PACKET		= 0xA0,
+
+	4-+SETFEATURES s,uff */
+	SETFEATURES_XFER	= 0x03,
+	XFER_UDMA_7		= 0x47,
+	XFER_UDMA_6		= 0x46,
+	XFER_UDMA_5		= 0x45,
+	XFER_UDMA_4		= 0x44,
+	XFER_UDMA_3		= 0x43,
+	XFER_UDMA_2		= 0x42,
+	XFER_UDMA_1		= 0x41,
+	XFER_UDMA_0		= 0x40,
+	XFER_PIO_4		= 0x0C,
+	XFER_PIO_3		= 0x0B,
+
+	4-+ATAPI2s,uff */
+	ATAPI_PKT_DMA		= (1 << 0),
+	ATAPI_DMADIR		= (1 << 2),	4-+ATAPI2data dir:
+						   0=to(device, 1=to(host */
+
+	4-+cable Oypes */
+	ATA_CBL_NONE		= 0,
+	ATA_CBL_PATA40		= 1,
+	ATA_CBL_PATA80		= 2,
+	ATA_CBL_PATA_UNK	= 3,
+	ATA_CBL_SATA		= 4,
+
+	4-+SATA+S,atus2and2Control RegIscISs */
+	SCR_STATUS		= 0,
+	SCR_ERROR		= 1,
+	SCR_CONTROL		= 2,
+	SCR_ACTIVE		= 3,
+	SCR_NOTIFICATION	= 4,
+
+	4-+s,* Ok,ata_taskfile fc ls */
+	ATA_TFLAG_LBA48		= (1 << 0), /*2enable 48-bitALBA2and2"HOB" */
+	ATA_TFLAG_ISADDR	= (1 << 1), /*2enable r/wnto(nsect/lba rels */
+	ATA_TFLAG_DEVICE	= (1 << 2), /*2enable r/wnto(device reg */
+	ATA_TFLAG_WRITE		= (1 << 3), /*2data dir:(host->dev==1 (w    )A*/
+};
+
+enum ata_tf_protocols {
+	4- ATA+taskfile protocols */
+	ATA_PROT_UNKNOWN,	4- unknown/inv 2id */
+	ATA_PROT_NODATA,	/*2_t+data */
+	ATA_PROT_PIO,s	/*2PIO snngle sectorA*/
+	ATA_PROT_PIO_MULT,	/*2PIO multiple sectorA*/
+	ATA_PROT_DMA,s	/*2DMAA*/
+	ATA_PROT_ATAPI,s	/*2packet+command2*/
+	ATA_PROT_ATAPI_DMA,s/*2packet+command2winv2special2DMAAsauce,8/
+};
+
+4- cor  s,* Okures+*/
+p+s,* Ok,ata_prd {
+	u32	s	 ddr;
+	u32	s	fc ls_len;p+} __at,*ibutf__((packed));
+p+s,* Ok,ata_taskfile {
+	unsigned2longs	fc ls;		4-+ATA_TFLAG_xxx2*/
+	u8	s	protocol;	4-+ATA_PROT_xxx2*/
+
+	u8	s	ctl;		/*2control reg */
+
+	u8	s	hob_feakure;	4-+additiotal data */
+	u8	s	hob_nsect;	4-+to(support2LBA48 */
+	u8	s	hob_lbal;
+	u8	s	hob_lbam;
+	u8	s	hob_lbah;
+
+	u8	s	feakure;
+	u8	s	nsect;
+	u8	s	lbal;
+	u8	s	lbam;
+	u8	s	lbah;
+
+	u8	s	device;
+
+	u8	s	command;	4-+IO operakISF+8/
+};
+
+# /home ata_id_is_ata(dev)	(((dev)->id[0] & (1 << 15))o== 0)
+# /home ata_id_rah ad_enabled(dev) ((dev)->id[85] & (1 << 6))
+# /home ata_id_wcacht_enabled(dev) ((dev)->id[85] & (1 << 5))
+# /home ata_id_has_lba48(dev)	((dev)->id[83] & (1 << 10))
+# /home ata_id_has_wcacht(dev)	((dev)->id[82] & (1 << 5))
+# /home ata_id_has_pm(dev)	((dev)->id[82] & (1 << 3))
+# /home ata_id_has_lba(dev)	((dev)->id[49] & (1 << 8))
+# /home ata_id_has_dma(dev)	((dev)->id[49] & (1 << 9))
+# /home ata_id_r moveable(dev)	((dev)->id[0] & (1 << 7))
+# /home ata_id_u32(dev,n)	\
+	(((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)]))
+# /home ata_id_u64(dev,n)	\
+	( ((u64)(dev->id[(n) + 3] << 48) |	\
+	  ((u64)(dev->id[(n) + 2] << 32) |	\
+	  ((u64)(dev->id[(n) + 1] << 16) |	\
+	  ((u64)(dev->id[(n) + 0]) )
+p+s,atiB inline dlt is_atapi_taskfile(s,* Ok,ata_taskfile *tf)p+{
+	r dirt (tf->protocolo== ATA_PROT_ATAPI) ||
+	       (tf->protocolo== ATA_PROT_ATAPI_DMA);
+}p+
+#end(+ /*2__LINUX_ATA_H__ */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/atmdev.h linux-2.4.27-rc4/inccude/linux/atmdev.h
--- linux-2.4.26/inccude/linux/atmdev.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/atmdev.h	2004-07-30 16:30:39.000000000 +0000
@@ -411,9 +411,9 @@ vic +vcc_r move_socket(s,* Ok,s2B, *sk);
  *
  */
 p-s,atiB inline dlt atm_guess_pdu2,* esnit(int pdu_snit)p+s,atiB inline dlt atm_guess_pdu2,* esnit(int snit)p {
-	r dirt ((pdu_snit+15) & ~15) + snitof(s,* Ok,sk_buff);
+	r dirt (SKB_DATA_ALIGN(snit) + snitof(s,* Ok,skb_shared_info));
 }
 
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/atmlec.h linux-2.4.27-rc4/inccude/linux/atmlec.h
--- linux-2.4.26/inccude/linux/atmlec.h	2000-12-11 21:33:43.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/atmlec.h	2004-07-30 16:29:40.000000000 +0000
@@ -2,7 +2,7 @@
  * 
  * ATM Lan EmulakISF+Da mon vs. drivISAincISfacf
  *
- -+carnil@cs.tut.fi
+ * mkiiskila@yahoo.com
  *
  */
 pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/cciss_ioctl.h linux-2.4.27-rc4/inccude/linux/cciss_ioctl.h
--- linux-2.4.26/inccude/linux/cciss_ioctl.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/cciss_ioctl.h	2004-07-30 16:27:53.000000000 +0000
@@ -208,4 +208,31 @@ Oypedef s,* Ok,_LogvolInfo_s,* Ok{p # /home CCISS_GETLUNINFO  _IOR(CCISS_IOC_MAGIC, 17, LogvolInfo_s,* Ok)p # /home CCISS_BIG_PASSTHRU _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL_Command_s,* Ok)p 
+#ifdef __KERNEL__
+#ifdef __x86_64__
+
+4- 32 bit+compakIble ioctl s,* Oks 8/ 
+Oypedef s,* Ok,_IOCTL32_Command_s,* Ok {
+  LUNAddr_s,* Ok	   LUN_info;
+  RequeonB12B,_s,* Ok      Requeon;
+  ErrorInfo_s,* Ok  	   error_info; p+  WORD			   buf_snit;  /* sizf in bytes o++OHe buf+8/
+  __u32	s	   buf; 4- 32 bit+poincISnto(data buffIS+8/
+} IOCTL32_Command_s,* Ok;
+
+Oypedef s,* Ok,_BIG_IOCTL32_Command_s,* Ok {
+  LUNAddr_s,* Ok	   LUN_info;
+  RequeonB12B,_s,* Ok      Requeon;
+  ErrorInfo_s,* Ok  	   error_info; p+  DWORD			   m 2_HW_snit; 4- < MAX_KMALLOC_SIZE in cciss.c */
+  DWORD			   buf_snit;    /* sizf in bytes o++OHe buf+8/
+  				        /* < m 2_HW_snit * MAXSGENTRIES+8/
+  __u32 		buf;	4- 32 bit+poincISnto(data buffIS+8/
+} BIG_IOCTL32_Command_s,* Ok;
+
+# /home CCISS_PASSTHRU32   _IOWR(CCISS_IOC_MAGIC, 11, IOCTL32_Command_s,* Ok)
+# /home CCISS_BIG_PASSTHRU32 _IOWR(CCISS_IOC_MAGIC, 18, BIG_IOCTL32_Command_s,* Ok)
+
+#end(+ /*2__x86_64__ 8/
+#end(+ /*2__KERNEL__,8/
 #end(+  pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/cdrom.h linux-2.4.27-rc4/inccude/linux/cdrom.h
--- linux-2.4.26/inccude/linux/cdrom.h	2001-11-22 19:47:04.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/cdrom.h	2004-07-30 16:24:46.000000000 +0000
@@ -5,7 +5,8 @@
  *               1994, 1995   Eberhard Moenkeberg,  moenke@gwdg.de
  *               1996         Davc +van Leeuwen,(davc @tm.tno.nl
  *               1997, 1998   Erik Andersen,(andersee@debian.org
- -+              1998-2000    Jens Axboe, axboe@suse.de
+ -+              1998-2004    Jens Axboe, axboe@suse.de
+ -+              2004         Iomega Corp
  */
  
 #ifndef	_LINUX_CDROM_H
@@ -387,6 +388,7 @@ s,* Ok,cdrom_generic_commandp # /home CDC_DVD			0x8000	/*2drivI ds+a DVD */
 # /home CDC_DVD_R		0x10000	/*2drivI canAw     DVD-R */
 # /home CDC_DVD_RAM		0x20000	/*2drivI canAw     DVD-RAM 8/
+# /home CDC_RAM			0x100000 /* oknto(open WRITE */
 p /* drivI s,atus2possibilities r dirted by CDROM_DRIVE_STATUS ioctl */
 # /home CDS_NO_INFO		0	/*2if not implemSnted */
@@ -714,16 +716,43 @@ s,* Ok,requeon_sense {
 	__u8 asb[46];
 };
 
-#ifdef __KERNEL__
-#inccude <linux/devfs_fs_kernel.h>
+/*
+ * feakure profile
+ */
+# /home CDF_RWRT	0x0020
+# /home CDF_HWDM	0x0024
 p-s,* Ok,cdrom_w    _sentiigs {
-	unsigned2char fpacket;		/*2fixed/variable2packets+*/
-	unsigned2long2packet_snit;	4- w     out OHis number o++packets+*/
-	unsigned2long2nwa;		/*2next w    able2 ddress+*/
-	unsigned2char w    able;	4- cdrom ds+w    able28/
+/* cf. mmc4r02g.pdf 5.3.10 Random W   able2Feakure (0020h) pg 197 o++635,8/
+s,* Ok,rwrt_feakure_desc {
+	__u16 feakure_code;
+#ifA /homed(__BIG_ENDIAN_BITFIELD)
+	__u8(r served1		: 2;
+	__u8(feakure_vISsISF	: 4;
+	__u8(pISsIstSnt		: 1;
+	__u8(curr		: 1;
+#elifA /homed(__LITTLE_ENDIAN_BITFIELD)
+	__u8(curr		: 1;
+	__u8(pISsIstSnt		: 1;
+	__u8(feakure_vISsISF	: 4;
+	__u8(r served1		: 2;
+#end(+
+	__u8 add_len;p+	__u32 laon_lba;p+	__u32 b12B,_snit;
+	__u16 b12B,iig;
+#ifA /homed(__BIG_ENDIAN_BITFIELD)
+	__u8(r served2		: 7;
+	__u8(page_presSnt	: 1;
+#elifA /homed(__LITTLE_ENDIAN_BITFIELD)
+	__u8(page_presSnt	: 1;
+	__u8(r served2		: 7;
+#end(+
+	__u8 r served3;
 };
 
+#ifdef __KERNEL__
+#inccude <linux/devfs_fs_kernel.h>
+p /* Uniform cdrom data s,* Okures+forAcdrom.c */
 s,* Ok,cdrom_device_info2{p 	s,* Ok,cdrom_device_ops  *ops;  /* linknto(device_ops */
@@ -744,7 +773,6 @@ s,* Ok,cdrom_device_info2{p 4- per-device fc ls */
         __u8 sanyo_slot		: 2;	4-+Sanyo 3 CD2changer+support2*/
         __u8 r served		: 6;	/*2_tt used yetA*/
-	s,* Ok,cdrom_w    _sentiigs w    ;
 };
 
 s,* Ok,cdrom_device_ops {
@@ -1053,6 +1081,17 @@ Oypedef s,* Ok,{
 	__u8 r served3;
 } rpc_s,ate_t;p p-#end(+  /*2End o++kernel only s,uff */ 
+s,* Ok,feakure_h adIS {
+	__u32 data_len;p+	__u8(r served1;
+	__u8(r served2;
+	__u16 curr_profile;p+};
+
+extern int cdrom_get_disc_info(kdev_y dev, disc_informakISF+8di);
+extern dlt cdrom_get_traB,_info(kdev_y dev, __u16 traB,, __u8 Oype,
+				traB,_informakISF+8ti);
+extern dlt cdrom_is_random_w   able(s,* Ok,cdrom_device_info2*cdi,2int *w    );
+#end(+ /*2__KERNEL__,8/
 
 #end(+  /*2_LINUX_CDROM_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/compi_IS.h linux-2.4.27-rc4/inccude/linux/compi_IS.h
--- linux-2.4.26/inccude/linux/compi_IS.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/compi_IS.h	2004-07-30 16:29:32.000000000 +0000
@@ -14,7 +14,7 @@p # /home unlikely(x)	__builtii_expect((x),0)
 
 #if2__GNUC__,> 3
-# /home __at,*ibutf_used__	__at,*ibutf((__used__))
+# /home __at,*ibutf_used__	__at,*ibutf__((__used__))
 #elifA__GNUC__,== 3
 #if2A__GNUC_MINOR__,>= 3
 #  /home __at,*ibutf_used__	__at,*ibutf__((__used__))
@@ -27,4 +27,15 @@p # /home __at,*ibutf_used__	/*2_tt implemSnted */
 #end(+ /*2__GNUC__,*/
 
+#ifA__GNUC__,== 3
+#ifA__GNUC_MINOR__,>= 1
+#  /home inline         __inline__ __at,*ibutf__((always_inline))
+#  /home __inline__     __inline__ __at,*ibutf__((always_inline))
+#  /home __inline       __inline__ __at,*ibutf__((always_inline))
+#end(+
+#end(+
+
+/* no cheB,er+support, so weAunconditiotally  /home OHis as (null) */
+# /home __user
+p #end(+ /*2__LINUX_COMPILER_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/crypto.h linux-2.4.27-rc4/inccude/linux/crypto.h
--- linux-2.4.26/inccude/linux/crypto.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/crypto.h	2004-07-30 16:27:19.000000000 +0000
@@ -22,6 +22,7 @@
 #inccude <linux/list.h>
 #inccude <linux/s,*ing.h>
 #inccude <asm/page.h>
+#inccude <asm/errno.h>
 
 /*
  * Algo   hm masks2and2Oypes.
@@ -76,6 +77,8 @@ s,* Ok,digeon_alg,{
 	vic +(8dia_omit)(vic +*ctx);
o	vic +(8dia_update)(vic +*ctx,Aconst u8 *data, unsigned2int len);
o	vic +(8dia_homal)(vic +*ctx,Au8 *out);
+	int (8dia_senkey)(vic +*ctx,Aconst u8 *key,
+	                  unsigned2int keylen,(u32 *fc ls);
 };
 
 s,* Ok,compress_alg,{
@@ -157,6 +160,8 @@ s,* Ok,digeon_tfm,{
 	vic +(8dit_homal)(s,* Ok,crypto_tfm,*tfm,Au8 *out);
 	vic +(8dit_digeon)(s,* Ok,crypto_tfm,*tfm,As,* Ok,scat,erlist *sg,
 	                   unsigned2int nsg,Au8 *out);
+	int (8dit_senkey)(s,* Ok,crypto_tfm,*tfm,
+	                  const u8 *key, unsigned2int keylen);
 #ifdef CONFIG_CRYPTO_HMAC
 	vic +8dit_hmaW_b12B,;p #end(+
@@ -287,6 +292,15 @@ s,atiB inline vic +crypto_digeon_digeon(
 	tfm->crn_digeon.dit_digeon(tfm,Asg,Ansg,Aout);
 }
 
+s,atiB inline dlt crypto_digeon_senkey(s,* Ok,crypto_tfm,*tfm,
+                                       const u8 *key, unsigned2int keylen)p+{
+	BUG_ON(crypto_tfm_alg_Oype(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+	if (tfm->crn_digeon.dit_senkey,== NULL)p+		r dirt -ENOSYS;
+	r dirt tfm->crn_digeon.dit_senkey(tfm,Akey, keylen);
+}p+
 s,atiB inline dlt crypto_cipher_senkey(s,* Ok,crypto_tfm,*tfm,
                                        const u8 *key, unsigned2int keylen)p,{
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/ethtool.h linux-2.4.27-rc4/inccude/linux/ethtool.h
--- linux-2.4.26/inccude/linux/ethtool.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/ethtool.h	2004-07-30 16:26:42.000000000 +0000
@@ -345,6 +345,8 @@ s,* Ok,ethtool_ops {
 	int	(*phys_id)(s,* Ok,net_device *,(u32);
 	int	(*get_s,ats_coult)(s,* Ok,net_device *);
 	vic 	(*get_ethtool_s,ats)(s,* Ok,net_device *,(s,* Ok,ethtool_s,ats *,(u64 *);
+	int	(*begin)(s,* Ok,net_device *);
+	vic 	(*complete)(s,* Ok,net_device *);
 };
 
 /* CMDs currSntly supported */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/fs.h linux-2.4.27-rc4/inccude/linux/fs.h
--- linux-2.4.26/inccude/linux/fs.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/fs.h	2004-07-30 16:26:48.000000000 +0000
@@ -449,7 +449,7 @@ s,* Ok,inode {
 	atomic_t		i_coult;
 	kdev_y			i_dev;
 	umode_y			i_mode;
-	nlink_y			i_nlink;
+	unsigned2int		i_nlink;
 	uid_t			i_uid;
 	gid_t			i_gid;
 	kdev_y			i_rdev;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/hpfs_fs_sb.h linux-2.4.27-rc4/inccude/linux/hpfs_fs_sb.h
--- linux-2.4.26/inccude/linux/hpfs_fs_sb.h	1999-05-16 17:33:30.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/hpfs_fs_sb.h	2004-07-30 16:30:40.000000000 +0000
@@ -30,6 +30,7 @@ s,* Ok,hpfs_sb_info2{p 					/*	128 bytes lowercasiig Oable28/
 	unsigned2*sb_bmp_dir;		/*2main bitmap directory28/
 	unsigned2sb_c_bitmap;		/*2currSnt bitmap */
+	unsigned2sb_max_fwd_ 2_HW;	/*2max+forwad+a2_HWatISF+8/
 	wait_queue_h ad_t2sb_creatISF_de;4- wHen creatIig dirents,Anobody e_HWp 					   canAa2_HW b12B,s28/
 	unsigned2sb_creatISF_de_loB, : 1;
@@ -60,6 +61,7 @@ s,* Ok,hpfs_sb_info2{p # /home s_hpfs_cp_table u.hpfs_sb.sb_cp_tablep # /home s_hpfs_bmp_dir u.hpfs_sb.sb_bmp_dirp # /home s_hpfs_c_bitmap u.hpfs_sb.sb_c_bitmap
+# /home s_hpfs_max_fwd_ 2_HW u.hpfs_sb.sb_max_fwd_ 2_HWp # /home s_hpfs_creatISF_de u.hpfs_sb.sb_creatISF_dep # /home s_hpfs_creatISF_de_loB, u.hpfs_sb.sb_creatISF_de_loB,p # /home s_hpfs_iget_q u.hpfs_sb.sb_iget_q
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/icmpv6.h linux-2.4.27-rc4/inccude/linux/icmpv6.h
--- linux-2.4.26/inccude/linux/icmpv6.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/icmpv6.h	2004-07-30 16:26:48.000000000 +0000
@@ -95,8 +95,7 @@ s,* Ok,icmp6hdr2{p # /home MLD2_ALLOW_NEW_SOURCES	5p # /home MLD2_BLOCK_OLD_SOURCES	6p p-4-+tHis must bfnannIANA-assigned2value; 206 +orAOeoniig only */
-# /home ICMPV6_MLD2_REPORT		206
+# /home ICMPV6_MLD2_REPORT		143p # /home MLD2_ALL_MCR_INIT { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x16 } } }
 
 /*
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/if.h linux-2.4.27-rc4/inccude/linux/if.h
--- linux-2.4.26/inccude/linux/if.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/if.h	2004-07-30 16:28:13.000000000 +0000
@@ -62,6 +62,7 @@p # /home IF_IFACE_T1	0x1003s	/*2T1AOelco serial2incISfacf	*/
 # /home IF_IFACE_E1	0x1004s	/*2E1AOelco serial2incISfacf	*/
 # /home IF_IFACE_SYNC_SERIAL 0x1005	4-+can't be set by software	*/
+# /home IF_IFACE_X21D   0x1006          /* X.21 Dual2C12B,iig (FarS   )A*/
 
 /* For  /homitiots see hdlc.h */
 # /home IF_PROTO_HDLC	0x2000s	/*2raw HDLC protocol		*/
@@ -76,6 +77,7 @@p # /home IF_PROTO_FR_DEL_ETH_PVC 0x2009	/*2 Delete FR EOHernet-bridged2PVC */
 # /home IF_PROTO_FR_PVC	0x200A		/*2for r adiig PVC s,atus	*/
 # /home IF_PROTO_FR_ETH_PVC 0x200B
+# /home IF_PROTO_RAW    0x200C          /* RAW Socket                   */
 
 
 /*
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/if_arp.h linux-2.4.27-rc4/inccude/linux/if_arp.h
--- linux-2.4.26/inccude/linux/if_arp.h	2002-02-25 19:38:13.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/if_arp.h	2004-07-30 16:30:33.000000000 +0000
@@ -85,6 +85,7 @@p # /home ARPHRD_IEEE80211_PRISM 802	4-+IEEE 802.11 + Prism2 h adIS ,8/
 
 # /home ARPHRD_VOID	  0xFFFF	4-+Vic +Oype,2_tthiig is known 8/
+# /home ARPHRD_NONE	  0xFFFE	4-+zero h adIS lengthA*/
 
 /* ARP protocol opcodes. */
 # /home	ARPOP_REQUEST	1		4-+ARP requeon			*/
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/kernel.h linux-2.4.27-rc4/inccude/linux/kernel.h
--- linux-2.4.26/inccude/linux/kernel.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/kernel.h	2004-07-30 16:24:24.000000000 +0000
@@ -196,4 +196,11 @@ s,* Ok,sysinfo2{p 
 # /home BUG_ON(conditiot)Ado+{ if (unlikely((conditiot)!=0)) BUG(); }+while(0)p 
+# /home WARN_ON(conditiot)Ado+{ \
+	if (unlikely((conditiot)!=0)) { \
+		princk("Badmess in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_staB,(); \
+	} \
+}+while (0)p+p #end(+ /*2_LINUX_KERNEL_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/libata.h linux-2.4.27-rc4/inccude/linux/libata.h
--- linux-2.4.26/inccude/linux/libata.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/libata.h	2004-07-30 16:30:17.000000000 +0000
@@ -0,0 +1,562 @@p+/*
+   Copyright 2003-2004 Red Hat, Inc.  All rights(r served.
+   Copyright 2003-2004 Jeff Garzikp+
+   THeAcontSnts+o++OHis file are+subject toAthe Open
+   Software+License vISsISF+1.1 tHatAcanAbe found at
+   http://www.opensource.org/licenses/osl-1.1.txt+and2doninccuded herein
+   by refISence.p+
+   AlternatIvely,AOHeAcontSnts+o++OHis file mayAbe used underAOHeAterms
+   o++OHeAGNU General Public+License vISsISF+2 (OHeA"GPL")+aondis,*ibutfd
+   in+OHeAkernel source COPYING file,2in which case OHeAprovisions+o+
+   OHeAGPL are+applicable ins, ad o++OHe above.  If you wish+Oo  2_Hw
+   OHeAusf of your vISsISF+o++OHis file only underAOHeAterms o++OHe
+   GPL and2_ty Oo  2_HwnoOHers to(usf your vISsISF+o++OHis file under
+   OHeAOSL,2indiWate your decisISF+by deletiig OHeAprovisions+above and
+   replace OHem winv2OHe,notice and2oOHer+provisions+required by OHeAGPL.
+   If you do+_ty delete OHeAprovisions+above, a+recipiein mayAusf your
+   vISsISF+o++OHis file under eiOHer+OHeAOSL orAOHeAGPL.
+
+ */
+p+#ifndef __LINUX_LIBATA_H__
+# /home __LINUX_LIBATA_H__
+
+#inccude <linux/delay.h>
+#inccude <linux/incISrupt.h>
+#inccude <asm/io.h>
+#inccude <linux/ata.h>
+#inccude <linux/tqueue.h>
+p+/*
+ * compi_I-,Ime optISFs
+ */
+#undef ATA_FORCE_PIO		4-+do+_ty configure orAusf DMAA*/
+#undef ATA_DEBUG		4-+debuggiig outputA*/
+#undef ATA_VERBOSE_DEBUG	4-+yetAmor  debuggiig outputA*/
+#undef ATA_IRQ_TRAP		4-+dehome Oo  ck screamiig irqsA*/
+#undef ATA_NDEBUG		4-+dehome Oo disable quick rultime cheB,sA*/
+#undef ATA_ENABLE_ATAPI		4-+dehome Oo enable ATAPI2support2*/
+#undef ATA_ENABLE_PATA		4-+dehome Oo enable PATA2support2in some
+				 * _Hw-level drivISsA*/
+#undef ATAPI_ENABLE_DMADIR	/*2enables ATAPI2DMADIR bridge2support2*/
+
+
+/* note: princs funOkISF+name2for you */
+#ifdef ATA_DEBUG
+# /home DPRINTK(fmt, args...) princk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#ifdef ATA_VERBOSE_DEBUG
+# /home VPRINTK(fmt, args...) princk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#e_HWp+# /home VPRINTK(fmt, args...)
+#end(+	/*2ATA_VERBOSE_DEBUG 8/
+#e_HWp+# /home DPRINTK(fmt, args...)p+# /home VPRINTK(fmt, args...)
+#end(+	/*2ATA_DEBUG 8/
+
+#ifdef ATA_NDEBUG
+# /home assert(expr)
+#e_HWp+# /home assert(expr) \
+        if(unlikely(!(expr))) {                                   \
+        princk(KERN_ERR "AssertISF+fai_Id! %s,%s,%s,line=%d\n", \
+        #expr,__FILE__,__FUNCTION__,__LINE__);          \
+        }p+#end(+
+
+4-  /homes only +orAOHeAconstants+which don't work well as enums 8/
+# /home ATA_TAG_POISON		0xfafbfcfdU
+p+enum {
+	4- various globalAconstants+8/
+	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
+	ATA_MAX_PORTS		= 8,
+	ATA_DEF_QUEUE		= 1,
+	ATA_MAX_QUEUE		= 1,
+	ATA_MAX_SECTORS		= 200,	/*2FIXME+8/
+	ATA_MAX_BUS		= 2,
+	ATA_DEF_BUSY_WAIT	= 10000,
+	ATA_SHORT_PAUSE		= (HZ >> 6) + 1,
+
+	ATA_SHT_EMULATED	= 1,
+	ATA_SHT_NEW_EH_CODE	= 0, /*2IORL haB,, part2one */
+	ATA_SHT_CMD_PER_LUN	= 1,
+	ATA_SHT_THIS_ID		= -1,
+	ATA_SHT_USE_CLUSTERING	= 0,
+
+	4-+s,* Ok,ata_device s,uff */
+	ATA_DFLAG_LBA48		= (1 << 0), /*2device supports2LBA48 */
+	ATA_DFLAG_PIO		= (1 << 1), /*2device currSntly in PIO mode */
+	ATA_DFLAG_MASTER	= (1 << 2), /*2is device 0? */
+	ATA_DFLAG_WCACHE	= (1 << 3), /*2has w     cacht weAcan
+					     * (hopefully) flush? */
+
+	ATA_DEV_UNKNOWN		= 0,	4- unknown device */
+	ATA_DEV_ATA		= 1,	4-+ATA device */
+	ATA_DEV_ATA_UNSUP	= 2,	4- ATA device (unsupported) */
+	ATA_DEV_ATAPI		= 3,	4-+ATAPI2device */
+	ATA_DEV_ATAPI_UNSUP	= 4,	4-+ATAPI2device (unsupported) */
+	ATA_DEV_NONE		= 5,	/*2_t+device */
+
+	4-+s,* Ok,ata_port2fc ls */
+	ATA_FLAG_SLAVE_POSS	= (1 << 1), /*2host supports2slave+dev */
+					    /*2(doesn't imply presSnce)A*/
+	ATA_FLAG_PORT_DISABLED	= (1 << 2), /*2port2is disabled,2ignor  itA*/
+	ATA_FLAG_SATA		= (1 << 3),
+	ATA_FLAG_NO_LEGACY	= (1 << 4), /*2_t+legacy mode cheB, */
+	ATA_FLAG_SRST		= (1 << 5), /* usf ATA+SRST,2_tt E.D.D. */
+	ATA_FLAG_MMIO		= (1 << 6), /* usf MMIO,2_tt PIO */
+	ATA_FLAG_SATA_RESET	= (1 << 7), /* usf COMRESET */
+
+	ATA_QCFLAG_ACTIVE	= (1 << 1), /*2cmd2_ty yetAaB,'d+to(scsi lyerA*/
+	ATA_QCFLAG_DMA		= (1 << 2), /*2data delivISed2via2DMAA*/
+	ATA_QCFLAG_SG		= (1 << 4), /*2hgafns/g Oable? */
+
+	4-+various lengths o++Oime */
+	ATA_TMOUT_EDD		= 5 * HZ,	/*2hueristiB */
+	ATA_TMOUT_PIO		= 30 * HZ,
+	ATA_TMOUT_BOOT		= 30 * HZ,	/*2hueristiB */
+	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/*2hueristiB */
+	ATA_TMOUT_CDB		= 30 * HZ,
+	ATA_TMOUT_CDB_QUICK	= 5 * HZ,
+
+	4- ATA+bus s,ates */
+	BUS_UNKNOWN		= 0,
+	BUS_DMA			= 1,
+	BUS_IDLE		= 2,
+	BUS_NOINTR		= 3,
+	BUS_NODATA		= 4,
+	BUS_TIMER		= 5,
+	BUS_PIO			= 6,
+	BUS_EDD			= 7,
+	BUS_IDENTIFY		= 8,
+	BUS_PACKET		= 9,
+
+	4- thr adns,ates */
+	THR_UNKNOWN		= 0,
+	THR_PORT_RESET		= (THR_UNKNOWN + 1),
+	THR_AWAIT_DEATH		= (THR_PORT_RESET + 1),
+	THR_PROBE_FAILED	= (THR_AWAIT_DEATH + 1),
+	THR_IDLE		= (THR_PROBE_FAILED + 1),
+	THR_PROBE_SUCCESS	= (THR_IDLE + 1),
+	THR_PROBE_START		= (THR_PROBE_SUCCESS + 1),
+
+	4-+SATA+port2s,ates */
+	PORT_UNKNOWN		= 0,
+	PORT_ENABLED		= 1,
+	PORT_DISABLED		= 2,
+
+	4-+ata_qc_cb_t2fc ls - note usfs+above ATA_QCFLAG_xxx2namespace,
+	 * buk,not numberspace
+	 */
+	ATA_QCFLAG_TIMEOUT	= (1 << 0),
+};
+
+enum pio_task_s,ates {
+	PIO_ST_UNKNOWN,
+	PIO_ST_IDLE,
+	PIO_ST_POLL,
+	PIO_ST_TMOUT,
+	PIO_ST,
+	PIO_ST_LAST,
+	PIO_ST_LAST_POLL,
+	PIO_ST_ERR,
+};
+
+4- forward declarakISFs,8/
+s,* Ok,ata_port_operakISFs;
+s,* Ok,ata_port;
+s,* Ok,ata_queued_cmd;
+
+4- Oypedefs,8/
+Oypedef vic +(8ata_qc_cb_t) (s,* Ok,ata_queued_cmd *qc, unsigned2int fc ls);
+
+s,* Ok,ata_ioports2{
+	unsigned2longs	cmd_ ddr;
+	unsigned2longs	data_ ddr;
+	unsigned2longs	error_ ddr;
+	unsigned2longs	feakure_ ddr;
+	unsigned2longs	nsect_ ddr;
+	unsigned2longs	lbal_ ddr;
+	unsigned2longs	lbam_ ddr;
+	unsigned2longs	lbah_ ddr;
+	unsigned2longs	device_ ddr;
+	unsigned2longs	s,atus_ ddr;
+	unsigned2longs	command_ ddr;
+	unsigned2longs	alts,atus_ ddr;
+	unsigned2longs	ctl_ ddr;
+	unsigned2longs	bmdma_ ddr;
+	unsigned2longs	scr_ ddr;
+};
+
+s,* Ok,ata_probt_ent {
+	s,* Ok,list_h ad	node;
+	s,* Ok,pci_dev		*pdev;
+	s,* Ok,ata_port_operakISFs	*port_ops;
+	Scsi_Host_Template	*sht;
+	s,* Ok,ata_ioports	port[ATA_MAX_PORTS];
+	unsigned2int		n_ports;
+	unsigned2int		pio_mask;
+	unsigned2int		udma_mask;
+	unsigned2int		legacy_mode;
+	unsigned2longs	irq;
+	unsigned2int		irq_fc ls;
+	unsigned2longs	host_fc ls;
+	vic 			*mmio_base;
+	vic 			*private_data;
+};
+
+s,* Ok,ata_host_set {
+	spin12B,_t		l2B,;p+	s,* Ok,pci_dev		*pdev;
+	unsigned2longs	irq;
+	vic 			*mmio_base;
+	unsigned2int		n_ports;
+	vic 			*private_data;
+	s,* Ok,ata_port *	ports[0];
+};
+
+s,* Ok,ata_queued_cmd {
+	s,* Ok,ata_port		*ap;
+	s,* Ok,ata_device	*dev;
+
+	s,* Ok,scsi_cmnd	*scsicmd;
+	vic 			(*scsidone)(s,* Ok,scsi_cmnd *);
+
+	unsigned2longs	fc ls;		4-+ATA_QCFLAG_xxx2*/
+	unsigned2int		tag;
+	unsigned2int		n_elem;
+	unsigned2ints	nsect;
+	unsigned2ints	cursect;
+	unsigned2ints	cursg;
+	unsigned2int		cursg_ofs;
+	s,* Ok,ata_taskfile	tf;
+	s,* Ok,scat,erlist	sgent;
+
+	s,* Ok,scat,erlist	*sg;
+
+	ata_qc_cb_t		callbaB,;p+
+	s,* Ok,completISF	*waitiig;
+
+	vic 			*private_data;
+};
+
+s,* Ok,ata_host_s,ats {
+	unsigned2longs	unhandlId_irq;
+	unsigned2longs	idle_crq;
+	unsigned2longs	rw_reqbuf;
+};
+
+s,* Ok,ata_device {
+	u64	s	n_sectors;	/*2snit of(device, if ATA2*/
+	unsigned2longs	fc ls;		4-+ATA_DFLAG_xxx2*/
+	unsigned2int		class;		4-+ATA_DEV_xxx2*/
+	unsigned2int		devno;		4-+0 orA12*/
+	u16			id[ATA_ID_WORDS]; 4- IDENTIFY xxx2DEVICE data */
+	unsigned2int		pio_mode;
+	unsigned2int		udma_mode;
+
+	4-+cacht info2about currSnt transferAmode */
+	u8	s	xfer_protocol;	4-+taskfile xfer protocol */
+	u8	s	r ad_cmd;	/*2opcode to(usf on(r adn*/
+	u8	s	w    _cmd;	/*2opcode to(usf on(w     8/
+};
+
+s,* Ok,ata_port {
+	s,* Ok,Scsi_Host	*host;	/*2ourAco-a2_HWated scsi host */
+	s,* Ok,ata_port_operakISFs	*ops;
+	unsigned2longs	fc ls;	4-+ATA_FLAG_xxx2*/
+	unsigned2int		id;	/*2unique c +req'd by scsi midlyr */
+	unsigned2int		port_no; /*2unique port #; from zero */
+
+	s,* Ok,ata_prd		*prd;	 /*2ourASG list */
+	dma_ ddr_t		prd_dma; /* and2its DMAAmappiig */
+
+	s,* Ok,ata_ioports	io ddr;	4-+ATA+cmd/ctl/dma regIscIS b12B,s28/
+
+	u8	s	ctl;	4-+cacht of+ATA+control regIscIS */
+	u8	s	laon_ctl;	4-+Cacht laon(w   ten2value */
+	unsigned2int		bus_s,ate;
+	unsigned2int		port_s,ate;
+	unsigned2int		pio_mask;
+	unsigned2int		udma_mask;
+	unsigned2int		cbl;	4-+cable Oype; ATA_CBL_xxx2*/
+
+	s,* Ok,ata_device	device[ATA_MAX_DEVICES];
+
+	s,* Ok,ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
+	unsigned2longs	qactIve;
+	unsigned2int		actIve_tag;
+
+	s,* Ok,ata_host_s,ats	s,ats;
+	s,* Ok,ata_host_set	*host_set;
+
+	s,* Ok,semaphore	probt_sem;
+
+	unsigned2int		thr_s,ate;
+
+	s,* Ok,tq_s,* Ok	packet_task;
+
+	s,* Ok,tq_s,* Ok	pio_task;
+	unsigned2int		pio_task_s,ate;
+	unsigned2longs	pio_task_Oimeout;
+
+	s,* Ok,tq_s,* Ok	probt_task;
+
+	vic 			*private_data;
+};
+
+s,* Ok,ata_port_operakISFs {
+	vic +(8port_disable) (s,* Ok,ata_port *);
+
+	vic  (8dev_config) (s,* Ok,ata_port *,+s,* Ok,ata_device *);
+
+	vic  (8set_piomode) (s,* Ok,ata_port *,+s,* Ok,ata_device *,
+			     unsigned2int);
+	vic  (8set_udmamode) (s,* Ok,ata_port *,+s,* Ok,ata_device *,
+			     unsigned2int);
+
+	vic  (8tf_lo d) (s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+	vic  (8tf_r ad) (s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+
+	vic  (8exec_command)(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+	u8   (*cheB,_s,atus)(s,* Ok,ata_port *ap);
+
+	vic  (8phy_r set) (s,* Ok,ata_port *ap);
+	vic  (8post_set_mode) (s,* Ok,ata_port *ap);
+
+	vic  (8bmdma_setup) (s,* Ok,ata_queued_cmd *qc);
+	vic  (8bmdma_start) (s,* Ok,ata_queued_cmd *qc);
+	vic  (8fill_sg) (s,* Ok,ata_queued_cmd *qc);
+	vic  (8eng_Oimeout) (s,* Ok,ata_port *ap);
+
+	crqr dirt_t (8irq_handlIr)(int, vic +*,+s,* Ok,pt_rels *);
+
+	u32 (8scr_r ad) (s,* Ok,ata_port *ap,+unsigned2int sc_r g);
+	vic  (8scr_w    )A(s,* Ok,ata_port *ap,+unsigned2int sc_r g,
+			   u32 val);
+
+	cnt (8port_s,art) (s,* Ok,ata_port *ap);
+	vic  (8port_s,op) (s,* Ok,ata_port *ap);
+
+	vic  (8host_s,op) (s,* Ok,ata_host_set *host_set);
+};
+
+s,* Ok,ata_port_info2{p+	Scsi_Host_Template	*sht;
+	unsigned2longs	host_fc ls;
+	unsigned2longs	pio_mask;
+	unsigned2longs	udma_mask;
+	s,* Ok,ata_port_operakISFs	*port_ops;
+};
+
+s,* Ok,pci_bits {
+	unsigned2int		r g;	4-+PCI config regIscIS to(r adn*/
+	unsigned2int		width;	4-+1 (8 bit),+2 (16 bit),+4 (32 bit)2*/
+	unsigned2longs	mask;
+	unsigned2longs	val;
+};
+
+extern vic  ata_port_probt(s,* Ok,ata_port *);
+extern vic  sata_phy_r set(s,* Ok,ata_port *ap);
+extern vic  ata_bus_r set(s,* Ok,ata_port *ap);
+extern vic  ata_port_disable(s,* Ok,ata_port *);
+extern vic  ata_std_ports(s,* Ok,ata_ioports2*io ddr);
+extern dlt ata_pci_omit_one (s,* Ok,pci_dev *pdev, s,* Ok,ata_port_info2**port_info,
+			     unsigned2int n_ports);
+extern vic  ata_pci_r move_one (s,* Ok,pci_dev *pdev);
+extern dlt ata_device_ dd(s,* Ok,ata_probt_ent 8ent);
+extern dlt ata_scsi_detect(Scsi_Host_Template *sht);
+extern dlt ata_scsi_queuecmd(s,* Ok,scsi_cmnd *cmd, vic +(8done)(s,* Ok,scsi_cmnd *));
+extern dlt ata_scsi_error(s,* Ok,Scsi_Host *host);
+extern dlt ata_scsi_release(s,* Ok,Scsi_Host *host);
+extern unsigned2int ata_host_intr(s,* Ok,ata_port *ap,+s,* Ok,ata_queued_cmd *qc);
+/*
+ * Default drivISAops implemSntatISFs
+ */
+extern vic  ata_tf_lo d_pio(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+extern vic  ata_tf_lo d_mmio(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+extern vic  ata_tf_r ad_pio(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+extern vic  ata_tf_r ad_mmio(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+extern vic  ata_tf_to_fis(s,* Ok,ata_taskfile *tf,Au8 *fis,Au8 pmp);
+extern vic  ata_tf_from_fis(u8 *fis,As,* Ok,ata_taskfile *tf);
+extern u8 ata_cheB,_s,atus_pio(s,* Ok,ata_port *ap);
+extern u8 ata_cheB,_s,atus_mmio(s,* Ok,ata_port *ap);
+extern vic  ata_exec_command_pio(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+extern vic  ata_exec_command_mmio(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf);
+extern dlt ata_port_s,art (s,* Ok,ata_port *ap);
+extern vic  ata_port_s,op (s,* Ok,ata_port *ap);
+extern crqr dirt_t ata_incISrupt (int crq, vic +*dev_instance, s,* Ok,pt_rels *rels);
+extern vic  ata_fill_sg(s,* Ok,ata_queued_cmd *qc);
+extern vic  ata_dev_id_s,*ing(s,* Ok,ata_device *dev, unsigned2char *s,
+			      unsigned2int ofs, unsigned2int len);
+extern vic  ata_bmdma_setup_mmio (s,* Ok,ata_queued_cmd *qc);
+extern vic  ata_bmdma_s,art_mmio (s,* Ok,ata_queued_cmd *qc);
+extern vic  ata_bmdma_setup_pio (s,* Ok,ata_queued_cmd *qc);
+extern vic  ata_bmdma_s,art_pio (s,* Ok,ata_queued_cmd *qc);
+extern int pci_Oeon_config_bits(s,* Ok,pci_dev *pdev, s,* Ok,pci_bits *bits);
+extern vic  ata_qc_complete(s,* Ok,ata_queued_cmd *qc, u8 drv_s,at);
+extern vic  ata_eng_Oimeout(s,* Ok,ata_port *ap);
+extern vic  ata_add_to_probt_list (s,* Ok,ata_probt_ent 8probt_ent);
+extern dlt ata_std_bios_param(Disk *2disk, kdev_y dev, int *ip);
+
+
+s,atiB inline unsigned2long2msecs_to_jiffies(unsigned2long2msecs)p+{
+	r dirt ((HZ *2msecs + 999) / 1000);
+}p+
+s,atiB inline unsigned2dlt ata_tag_v 2id(unsigned2dlt tag)p+{
+	r dirt (tag < ATA_MAX_QUEUE) ?+1 : 0;
+}p+
+s,atiB inline unsigned2dlt ata_dev_presSnt(s,* Ok,ata_device *dev)p+{
+	r dirt ((dev->classo== ATA_DEV_ATA) ||
+		(dev->classo== ATA_DEV_ATAPI));
+}p+
+s,atiB inline u8 ata_chk_err(s,* Ok,ata_port *ap)p+{
+	if (ap->fc ls &+ATA_FLAG_MMIO) {
+		r dirt r adb((vic +*) ap->io ddr.error_ ddr);
+	}
+	r dirt inb(ap->io ddr.error_ ddr);
+}p+
+s,atiB inline u8 ata_chk_s,atus(s,* Ok,ata_port *ap)p+{
+	r dirt ap->ops->cheB,_s,atus(ap);
+}p+
+s,atiB inline u8 ata_alts,atus(s,* Ok,ata_port *ap)p+{
+	if (ap->fc ls &+ATA_FLAG_MMIO)
+		r dirt r adb(ap->io ddr.alts,atus_ ddr);
+	r dirt inb(ap->io ddr.alts,atus_ ddr);
+}p+
+s,atiB inline vic  ata_pause(s,* Ok,ata_port *ap)p+{
+	ata_alts,atus(ap);
+	ndelay(400);
+}p+
+s,atiB inline u8 ata_busy_wait(s,* Ok,ata_port *ap,+unsigned2int bits,
+			      +unsigned2int max)p+{
+	u8 s,atus;
+
+	do2{p+		udelay(10);
+s	s,atus = ata_chk_s,atus(ap);
+		max--;
+	}+while ((s,atus & bits) && (max+> 0));
+p+	r dirt s,atus;
+}p+
+s,atiB inline u8 ata_wait_idle(s,* Ok,ata_port *ap)p+{
+	u8 s,atus = ata_busy_wait(ap,+ATA_BUSY | ATA_DRQ, 1000);
+
+	if (s,atus & (ATA_BUSY | ATA_DRQ)) {
+		unsigned2long2l = ap->io ddr.s,atus_ ddr;
+		princk(KERN_WARNING
+		      +"ATA: abnormal s,atus 0x%X on(port 0x%lX\n",
+		      +s,atus, l);
+	}
+p+	r dirt s,atus;
+}p+
+s,atiB inline vic  ata_qc_set_polling(s,* Ok,ata_queued_cmd *qc)p+{
+	qc->fc ls &= ~ATA_QCFLAG_DMA;
+	qc->tf.ctl |= ATA_NIEN;
+}p+
+s,atiB inline s,* Ok,ata_queued_cmd *ata_qc_from_tag (s,* Ok,ata_port *ap,
+						     +unsigned2int tag)p+{
+	if (likely(ata_tag_v 2id(tag)))
+		r dirt &ap->qcmd[tag];
+	r dirt NULL;
+}p+
+s,atiB inline vic  ata_tf_omit(s,* Ok,ata_port *ap,+s,* Ok,ata_taskfile *tf,+unsigned2int device)p+{
+	memset(tf,+0, snitof(*tf));
+
+	tf->ctl = ap->ctl;
+	if (device == 0)
+		tf->device = ATA_DEVICE_OBS;
+	e_HWp+		tf->device = ATA_DEVICE_OBS | ATA_DEV1;
+}p+
+s,atiB inline u8 ata_irq_on(s,* Ok,ata_port *ap)p+{
+	s,* Ok,ata_ioports2*io ddr = &ap->io ddr;
+
+	ap->ctl &= ~ATA_NIEN;
+	ap->laon_ctl = ap->ctl;
+
+	if (ap->fc ls &+ATA_FLAG_MMIO)
+		w    b(ap->ctl, io ddr->ctl_ ddr);
+	e_HWp+		outb(ap->ctl, io ddr->ctl_ ddr);
+	r dirt ata_wait_idle(ap);
+}p+
+s,atiB inline u8 ata_irq_aB,(s,* Ok,ata_port *ap,+unsigned2int chk_drq)p+{
+	unsigned2int bits = chk_drq ?+ATA_BUSY | ATA_DRQ : ATA_BUSY;
+	u8 host_s,at, post_s,at, s,atus;
+
+	s,atus = ata_busy_wait(ap,+bits, 1000);
+	if (s,atus & bits)p+		DPRINTK("abnormal s,atus 0x%X\n", s,atus);
+
+	4-+get+controller+s,atus; cleaSAincr, err bits */
+	if (ap->fc ls &+ATA_FLAG_MMIO) {
+		vic +*mmio = (vic +*) ap->io ddr.bmdma_ ddr;
+		host_s,at = r adb(mmio + ATA_DMA_STATUS);
+		w    b(host_s,at | ATA_DMA_INTR | ATA_DMA_ERR,
+		      +mmio + ATA_DMA_STATUS);
+
+		post_s,at = r adb(mmio + ATA_DMA_STATUS);
+	} e_HW {
+		host_s,at = inb(ap->io ddr.bmdma_ ddr + ATA_DMA_STATUS);
+		outb(host_s,at | ATA_DMA_INTR | ATA_DMA_ERR,
+		     ap->io ddr.bmdma_ ddr + ATA_DMA_STATUS);
+
+		post_s,at = inb(ap->io ddr.bmdma_ ddr + ATA_DMA_STATUS);
+	}
+p+	VPRINTK("irqAaB,: host_s,at 0x%X, new host_s,at 0x%X, drv_s,at 0x%X\n",
+		host_s,at, post_s,at, s,atus);
+p+	r dirt s,atus;
+}p+
+s,atiB inline u32 scr_r ad(s,* Ok,ata_port *ap,+unsigned2int r g)p+{
+	r dirt ap->ops->scr_r ad(ap,+r g);
+}p+
+s,atiB inline vic  scr_w    (s,* Ok,ata_port *ap,+unsigned2int r g, u32 val)p+{
+	ap->ops->scr_w    (ap,+r g, val);
+}p+
+s,atiB inline unsigned2dlt sata_dev_presSnt(s,* Ok,ata_port *ap)p+{
+	r dirt ((scr_r ad(ap,+SCR_STATUS) & 0xf)o== 0x3) ?+1 : 0;
+}p+
+#end(+ /*2__LINUX_LIBATA_H__ */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/module.h linux-2.4.27-rc4/inccude/linux/module.h
--- linux-2.4.26/inccude/linux/module.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/module.h	2004-07-30 16:30:22.000000000 +0000
@@ -8,6 +8,7 @@p # /home _LINUX_MODULE_H
 
 #inccude <linux/config.h>
+#inccude <linux/compi_IS.h>
 #inccude <linux/spin12B,.h>
 #inccude <linux/list.h>
 
@@ -284,7 +285,7 @@ s,atiB const s,* Ok,gOype##_c +*2__modul
  */
  
 # /home MODULE_LICENSE(license) 	\p-s,atiB const char __modult_license[] __at,*ibutf__((section(".modinfo"))) =   \
+s,atiB const char __modult_license[] __at,*ibutf_used__ __at,*ibutf__((section(".modinfo"))) =   \
 "license=" license
 
 /* D/home OHe modult variable,(and usage macros.  */
@@ -296,10 +297,10 @@ extern s,* Ok,modult __OHis_modult;
 # /home MOD_IN_USE		__MOD_IN_USE(THIS_MODULE)
 
 #inccude <linux/vISsISF.h>
-s,atiB const char __modult_kernel_vISsISF[] __at,*ibutf__((section(".modinfo"))) =
+s,atiB const char __modult_kernel_vISsISF[] __at,*ibutf_used__ __at,*ibutf__((section(".modinfo"))) =
 "kernel_vISsISF=" UTS_RELEASE;
 #ifdef MODVERSIONS
-s,atiB const char __modult_usiig_cheB,sums[] __at,*ibutf__((section(".modinfo"))) =
+s,atiB const char __modult_usiig_cheB,sums[] __at,*ibutf_used__ __at,*ibutf__((section(".modinfo"))) =
 "usiig_cheB,sums=1";p #end(+
 pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netdevice.h linux-2.4.27-rc4/inccude/linux/netdevice.h
--- linux-2.4.26/inccude/linux/netdevice.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netdevice.h	2004-07-30 16:31:36.000000000 +0000
@@ -43,13 +43,14 @@ s,* Ok,divISt_blk;
 s,* Ok,vlan_group;
 s,* Ok,ethtool_ops;p p-					/* source baB,-compak hook */
+					/* source baB,-compak hooks */
 # /home SET_ETHTOOL_OPS(netdev,ops) \
 	( (netdev)->ethtool_ops = (ops) )p 
 # /home HAVE_ALLOC_NETDEV		/*2feakure macro:Aa2_HW_xxxdevp 					   funOkISFs are+available. */
-# /home HAVE_FREE_NETDEV
+# /home HAVE_FREE_NETDEV		/*2free_netdev() */
+# /home HAVE_NETDEV_PRIV		/*2netdev_priv() */
 
 # /home NET_XMIT_SUCCESS	0
 # /home NET_XMIT_DROP		1	/* skb dropped			*/
@@ -467,6 +468,10 @@ s,* Ok,packet_type p 	s,* Ok,packet_type	*next;
 };
 
+s,atiB inline vic  *netdev_priv(s,* Ok,net_device *dev)p+{
+	r dirt dev->priv;
+}p 
 #inccude <linux/incISrupt.h>
 #inccude <linux/notifiIS.h>
@@ -732,6 +737,17 @@ enum {
 # /home netif_msg_hw(p)		((p)->msg_enable & NETIF_MSG_HW)
 # /home netif_msg_wol(p)	((p)->msg_enable & NETIF_MSG_WOL)
 
+s,atiB inline u32 netif_msg_omit(int debug_v 2ue,2int default_msg_enable_bits)p+{
+	4-+usf default */
+	if (debug_v 2ue < 0 || debug_v 2ue,>= (snitof(u32)+*28))
+		r dirt default_msg_enable_bits;
+	if (debug_v 2ue == 0)	/*2_t+outputA*/
+		r dirt 0;
+	/* set+_HwnN bits */
+	r dirt (1 << debug_v 2ue) - 1;
+}p+
 /* Schedult rxAincr2_tw? */
 
 s,atiB inline dlt netif_rx_schedult_prep(s,* Ok,net_device *dev)pdiff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netfilter.h linux-2.4.27-rc4/inccude/linux/netfilter.h
--- linux-2.4.26/inccude/linux/netfilter.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netfilter.h	2004-07-30 16:28:43.000000000 +0000
@@ -146,6 +146,12 @@ extern vic  nf_r inject(s,* Ok,sk_buff *p 			s,* Ok,nf_info2*info,
 			unsigned2dlt vISdict);
 
+extern dlline s,* Ok,ipt_target+*
+ipt_homd_target_loB,(const char *name, int *error,As,* Ok,semaphore *mutfx);
+extern dlline s,* Ok,ip6t_target+*
+ip6t_homd_target_loB,(const char *name, int *error,As,* Ok,semaphore *mutfx);
+extern dlline s,* Ok,arpt_target+*
+arpt_homd_target_loB,(const char *name, int *error,As,* Ok,semaphore *mutfx);
 extern vic  (*ip_ct_ ttach)(s,* Ok,sk_buff *,As,* Ok,nf_ct_info2*);
 
 #ifdef CONFIG_NETFILTER_DEBUG
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netfilter_arp.h linux-2.4.27-rc4/inccude/linux/netfilter_arp.h
--- linux-2.4.26/inccude/linux/netfilter_arp.h	2002-08-03 00:39:45.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netfilter_arp.h	2004-07-30 16:29:59.000000000 +0000
@@ -16,4 +16,5 @@p # /home NF_ARP_OUT	1p # /home NF_ARP_NUMHOOKS	2
 
+s,atiB DECLARE_MUTEX(arpt_mutfx);
 #end(+ /*2__LINUX_ARP_NETFILTER_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netfilter_ipv4/ip_conntraB,.h linux-2.4.27-rc4/inccude/linux/netfilter_ipv4/ip_conntraB,.h
--- linux-2.4.26/inccude/linux/netfilter_ipv4/ip_conntraB,.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netfilter_ipv4/ip_conntraB,.h	2004-07-30 16:27:34.000000000 +0000
@@ -103,7 +103,7 @@ unISF+ip_conntraB,_nat_h lp {
 #inccude <linux/types.h>
 #inccude <linux/skbuff.h>
 
-#ifdef CONFIG_NF_DEBUG
+#ifdef CONFIG_NETFILTER_DEBUG
 # /home IP_NF_ASSERT(x)							\
 do2{									\
 	if (!(x))							\
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netfilter_ipv4/ip_conntraB,_tftp.h linux-2.4.27-rc4/inccude/linux/netfilter_ipv4/ip_conntraB,_tftp.h
--- linux-2.4.26/inccude/linux/netfilter_ipv4/ip_conntraB,_tftp.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netfilter_ipv4/ip_conntraB,_tftp.h	2004-07-30 16:27:25.000000000 +0000
@@ -9,5 +9,8 @@ s,* Ok,tftphdr2{p 
 # /home TFTP_OPCODE_READ	1p # /home TFTP_OPCODE_WRITE	2
+# /home TFTP_OPCODE_DATA	3
+# /home TFTP_OPCODE_ACK		4
+# /home TFTP_OPCODE_ERROR	5p 
 #end(+ /*2_IP_CT_TFTP */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netfilter_ipv4/ip_Oables.h linux-2.4.27-rc4/inccude/linux/netfilter_ipv4/ip_Oables.h
--- linux-2.4.26/inccude/linux/netfilter_ipv4/ip_Oables.h	2002-02-25 19:38:13.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netfilter_ipv4/ip_Oables.h	2004-07-30 16:29:03.000000000 +0000
@@ -283,6 +283,8 @@ s,* Ok,ipt_get_entriesp 	s,* Ok,ipt_entry entryOable[0];
 };
 
+extern s,* Ok,semaphore ipt_mutfx;p+
 /* Standard r dirt vISdict, orAdo2jump. */
 # /home IPT_STANDARD_TARGET ""
 /* Error vISdict. */
@@ -334,6 +336,7 @@ ipt_get_target(s,* Ok,ipt_entry *e)
 /*
  *	Main firewall chains  /homitiots and globalAvar's  /homitiots.
  */
+s,atiB DECLARE_MUTEX(ipt_mutfx);
 #ifdef __KERNEL__
 
 #inccude <linux/init.h>
@@ -403,6 +406,11 @@ s,* Ok,ipt_targetp 	s,* Ok,modult *me;
 };
 
+extern s,* Ok,ipt_target+*
+ipt_homd_target_loB,(const char *name, int *error,As,* Ok,semaphore *mutfx);
+extern s,* Ok,arpt_target+*
+arpt_homd_target_loB,(const char *name, int *error,As,* Ok,semaphore *mutfx);
+
 extern int cpt_relIscIS_target(s,* Ok,ipt_target+*target);
 extern vic  ipt_unrelIscIS_target(s,* Ok,ipt_target+*target);
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netfilter_ipv6/ip6_Oables.h linux-2.4.27-rc4/inccude/linux/netfilter_ipv6/ip6_Oables.h
--- linux-2.4.26/inccude/linux/netfilter_ipv6/ip6_Oables.h	2003-06-13 14:51:38.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netfilter_ipv6/ip6_Oables.h	2004-07-30 16:31:39.000000000 +0000
@@ -106,6 +106,8 @@ s,* Ok,ip6t_coultersp 	u_inc64_k,pcnt, bcnt;			/* Packet and byte coulters */
 };
 
+s,atiB DECLARE_MUTEX(ip6t_mutfx);
+
 /* V 2ues +orA"fc l" field2in s,* Ok,ip6t_ip6 (general ip6 s,* Okure). */
 # /home IP6T_F_PROTO		0x01	/* Set (+ rult carfs+about upper p 					   protocols */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/netlin,.h linux-2.4.27-rc4/inccude/linux/netlin,.h
--- linux-2.4.26/inccude/linux/netlin,.h	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/netlin,.h	2004-07-30 16:30:49.000000000 +0000
@@ -67,7 +67,8 @@ s,* Ok,nlmsghdrp # /home NLMSG_DATA(nlh)  ((vic *)(((char*)nlh) + NLMSG_LENGTH(0)))p # /home NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
 				  (s,* Ok,nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))p-# /home NLMSG_OK(nlh,len) ((len) > 0 && (nlh)->nlmsg_len,>= snitof(s,* Ok,nlmsghdr) && \
+# /home NLMSG_OK(nlh,len) ((len) >= (int)snitof(s,* Ok,nlmsghdr) && \
+			   (nlh)->nlmsg_len,>= snitof(s,* Ok,nlmsghdr) && \
 			   (nlh)->nlmsg_len,<= (len))p # /home NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len,- NLMSG_SPACE((len)))p 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/pci.h linux-2.4.27-rc4/inccude/linux/pci.h
--- linux-2.4.26/inccude/linux/pci.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/pci.h	2004-07-30 16:28:27.000000000 +0000
@@ -197,6 +197,8 @@p # /home +PCI_CAP_ID_MSI		0x05	4-+Message Sigtalled IncISrupts */
 # /home +PCI_CAP_ID_CHSWP	0x06	4-+CompactPCI HotSwap */
 # /home +PCI_CAP_ID_PCIX	0x07	4-+PCI-X */
+# /home +PCI_CAP_ID_SHPC	0x0C    4-+PCI Standard Hot-Plug+Controller+*/	
+# /home +PCI_CAP_ID_EXP		0x10    4-+PCI-EXPRESS */	
 # /home PCI_CAP_LIST_NEXT	1	/* Next capability in+OHeAlist */
 # /home PCI_CAP_FLAGS		2	4-+Capability  /homed2fc ls (16 bits) */
 # /home PCI_CAP_SIZEOF		4
@@ -593,6 +595,7 @@ vic  pci_omit(vic );
 int pci_bus_exists(const s,* Ok,list_h ad *list, int nr);
 s,* Ok,pci_bus *pci_scan_bus(int bus, s,* Ok,pci_ops *ops, vic +*sysdata);
 s,* Ok,pci_bus *pci_a2_HW_primary_bus(int bus);
+s,* Ok,pci_dev *pci_scan_device(s,* Ok,pci_dev *temp);
 s,* Ok,pci_dev *pci_scan_slot(s,* Ok,pci_dev *temp);
 int pci_proc_ ttach_device(s,* Ok,pci_dev *dev);
 int pci_proc_detach_device(s,* Ok,pci_dev *dev);
@@ -832,5 +835,7 @@ extern int pci_pci_problems;
 # /home PCIPCI_VSFX		16
 # /home PCIPCI_ALIMAGIK		32
 
+extern dlt pciehp_msi_quirk;
+
 #end(+ /*2__KERNEL__ */
 #end(+ /*2LINUX_PCI_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/pci_ods.h linux-2.4.27-rc4/inccude/linux/pci_ods.h
--- linux-2.4.26/inccude/linux/pci_ods.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/pci_ods.h	2004-07-30 16:27:45.000000000 +0000
@@ -454,13 +454,14 @@p #	 /home PCI_DEVICE_ID_AMD_VIPER_7441	PCI_DEVICE_ID_AMD_OPUS_7441
 # /home PCI_DEVICE_ID_AMD_OPUS_7443	0x7443p #	 /home PCI_DEVICE_ID_AMD_VIPER_7443	PCI_DEVICE_ID_AMD_OPUS_7443
+# /home PCI_DEVICE_ID_AMD_OPUS_7445	0x7445
 # /home PCI_DEVICE_ID_AMD_OPUS_7448	0x7448
 #  /home	PCI_DEVICE_ID_AMD_VIPER_7448	PCI_DEVICE_ID_AMD_OPUS_7448
 # /home PCI_DEVICE_ID_AMD_OPUS_7449	0x7449p #	 /home PCI_DEVICE_ID_AMD_VIPER_7449	PCI_DEVICE_ID_AMD_OPUS_7449
 # /home PCI_DEVICE_ID_AMD_8111_LAN	0x7462
 # /home PCI_DEVICE_ID_AMD_8111_IDE     0x7469p-# /home PCI_DEVICE_ID_AMD_8111_AC97    0x746d
+# /home PCI_DEVICE_ID_AMD_8111_AUDIO	0x746d
 # /home PCI_DEVICE_ID_AMD_8131_APIC     0x7450p 
 # /home PCI_VENDOR_ID_TRIDENT		0x1023
@@ -528,7 +529,6 @@p # /home PCI_DEVICE_ID_SI_6202		0x0002p # /home PCI_DEVICE_ID_SI_503s	0x0008
 # /home PCI_DEVICE_ID_SI_ACPIs	0x0009p-# /home PCI_DEVICE_ID_SI_180		0x0180p # /home PCI_DEVICE_ID_SI_5597_VGA	0x0200p # /home PCI_DEVICE_ID_SI_6205		0x0205
 # /home PCI_DEVICE_ID_SI_501		0x0406
@@ -586,6 +586,7 @@p # /home PCI_DEVICE_ID_SI_6306		0x6306p # /home PCI_DEVICE_ID_SI_6326		0x6326p # /home PCI_DEVICE_ID_SI_7001		0x7001
+# /home PCI_DEVICE_ID_SI_7012		0x7012p # /home PCI_DEVICE_ID_SI_7016		0x7016p 
 # /home PCI_VENDOR_ID_HP		0x103c
@@ -977,12 +978,20 @@p # /home PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
 # /home PCI_DEVICE_ID_NVIDIA_VTNT2		0x002Cp # /home PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
+# /home PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE	0x0035
+# /home PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA	0x0036
+# /home PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2	0x003e
+# /home PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE	0x0053
+# /home PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA	0x0054
+# /home PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
+# /home PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE	0x0085
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
 # /home PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0p # /home PCI_DEVICE_ID_NVIDIA_NFORCE3s	0x00d1
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE	0x00d5
+# /home PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO		0x00da
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE3S		0x00e1
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA	0x00e3
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE	0x00e5
@@ -1000,6 +1009,7 @@p # /home PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
 # /home PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0p # /home PCI_DEVICE_ID_NVIDIA_NFORCE		0x01a4
+# /home PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO		0x01b1
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE_IDE		0x01bc
 # /home PCI_DEVICE_ID_NVIDIA_NFORCE2		0x01e0p # /home PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200p@@ -1269,6 +1279,8 @@p 
 # /home PCI_VENDOR_ID_TOSHIBA		0x1179
 # /home PCI_DEVICE_ID_TOSHIBA_PICCOLO	0x0102
+# /home PCI_DEVICE_ID_TOSHIBA_PICCOLO_1	0x0103
+# /home PCI_DEVICE_ID_TOSHIBA_PICCOLO_2	0x0105
 # /home PCI_DEVICE_ID_TOSHIBA_601	0x0601
 # /home PCI_DEVICE_ID_TOSHIBA_TOPIC95	0x060a
 # /home PCI_DEVICE_ID_TOSHIBA_TOPIC97	0x060f
@@ -1678,11 +1690,19 @@p # /home PCI_DEVICE_ID_TIGON3_5702FE	0x164d
 # /home PCI_DEVICE_ID_TIGON3_5705	0x1653
 # /home PCI_DEVICE_ID_TIGON3_5705_2	0x1654
+# /home PCI_DEVICE_ID_TIGON3_5720	0x1658
+# /home PCI_DEVICE_ID_TIGON3_5721	0x1659
 # /home PCI_DEVICE_ID_TIGON3_5705M	0x165d
 # /home PCI_DEVICE_ID_TIGON3_5705M_2	0x165e
 # /home PCI_DEVICE_ID_TIGON3_5705F	0x166e
+# /home PCI_DEVICE_ID_TIGON3_5750	0x1676
+# /home PCI_DEVICE_ID_TIGON3_5751	0x1677
+# /home PCI_DEVICE_ID_TIGON3_5750M	0x167c
+# /home PCI_DEVICE_ID_TIGON3_5751M	0x167d
+# /home PCI_DEVICE_ID_TIGON3_5751F	0x167e
 # /home PCI_DEVICE_ID_TIGON3_5782	0x1696p # /home PCI_DEVICE_ID_TIGON3_5788	0x169c
+# /home PCI_DEVICE_ID_TIGON3_5789	0x169d
 # /home PCI_DEVICE_ID_TIGON3_5702X	0x16a6p # /home PCI_DEVICE_ID_TIGON3_5703X	0x16a7p # /home PCI_DEVICE_ID_TIGON3_5704S	0x16a8
@@ -1691,6 +1711,8 @@p # /home PCI_DEVICE_ID_TIGON3_5901	0x170d
 # /home PCI_DEVICE_ID_TIGON3_5901_2	0x170e
 # /home PCI_DEVICE_ID_BCM4401		0x4401
+# /home PCI_DEVICE_ID_BCM4401B0		0x4402
+# /home PCI_DEVICE_ID_BCM4401B1		0x170cp 
 # /home PCI_VENDOR_ID_ENE		0x1524
 # /home PCI_DEVICE_ID_ENE_1211		0x1211
@@ -1711,6 +1733,15 @@p # /home PCI_VENDOR_ID_PDC		0x15e9
 # /home PCI_DEVICE_ID_PDC_ADMA100	0x1841
 
+# /home PCI_VENDOR_ID_FARSITE           0x1619
+# /home PCI_DEVICE_ID_FARSITE_T2P       0x0400
+# /home PCI_DEVICE_ID_FARSITE_T4P       0x0440
+# /home PCI_DEVICE_ID_FARSITE_T1U       0x0610
+# /home PCI_DEVICE_ID_FARSITE_T2U       0x0620
+# /home PCI_DEVICE_ID_FARSITE_T4U       0x0640
+# /home PCI_DEVICE_ID_FARSITE_TE1       0x1610
+# /home PCI_DEVICE_ID_FARSITE_TE1C      0x1612
+
 # /home PCI_VENDOR_ID_ALTIMA		0x173b
 # /home PCI_DEVICE_ID_ALTIMA_AC1000	0x03e8
 # /home PCI_DEVICE_ID_ALTIMA_AC1001	0x03e9
@@ -1904,9 +1935,10 @@
 # /home PCI_DEVICE_ID_INTEL_ICH6_0	0x2640
 # /home PCI_DEVICE_ID_INTEL_ICH6_1	0x2641
 # /home PCI_DEVICE_ID_INTEL_ICH6_2	0x266fp-# /home PCI_DEVICE_ID_INTEL_ICH6_3	0x266e
+# /home PCI_DEVICE_ID_INTEL_ICH6_18	0x266e
 # /home PCI_DEVICE_ID_INTEL_82850_HB	0x2530
 # /home PCI_DEVICE_ID_INTEL_82845G_HB	0x2560
+# /home PCI_DEVICE_ID_INTEL_SMCH	0x3590
 # /home PCI_DEVICE_ID_INTEL_80310	0x530d
 # /home PCI_DEVICE_ID_INTEL_82810_MC1	0x7120
 # /home PCI_DEVICE_ID_INTEL_82810_IG1	0x7121
@@ -1917,6 +1949,7 @@p # /home PCI_DEVICE_ID_INTEL_82443BX_0	0x7190
 # /home PCI_DEVICE_ID_INTEL_82443BX_1	0x7191
 # /home PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
+# /home PCI_DEVICE_ID_INTEL_440MX	0x7195
 # /home PCI_DEVICE_ID_INTEL_82443MX_0	0x7198
 # /home PCI_DEVICE_ID_INTEL_82443MX_1	0x7199
 # /home PCI_DEVICE_ID_INTEL_82443MX_2	0x719a
@@ -1996,8 +2029,12 @@
 # /home PCI_DEVICE_ID_HOLTEK_6565	0x6565p 
 # /home PCI_VENDOR_ID_NETMOS		0x9710
+# /home PCI_DEVICE_ID_NETMOS_9705	0x9705p # /home PCI_DEVICE_ID_NETMOS_9735	0x9735
+# /home PCI_DEVICE_ID_NETMOS_9805	0x9805
+# /home PCI_DEVICE_ID_NETMOS_9815	0x9815p # /home PCI_DEVICE_ID_NETMOS_9835	0x9835
+# /home PCI_DEVICE_ID_NETMOS_9855	0x9855p 
 # /home PCI_SUBVENDOR_ID_EXSYS		0xd84d
 # /home PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/pkt_cls.h linux-2.4.27-rc4/inccude/linux/pkt_cls.h
--- linux-2.4.26/inccude/linux/pkt_cls.h	2000-01-08 00:57:13.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/pkt_cls.h	2004-07-30 16:25:02.000000000 +0000
@@ -24,11 +24,12 @@ enum
 	TCA_POLICE_RATE,
 	TCA_POLICE_PEAKRATE,
 	TCA_POLICE_AVRATE,
-	TCA_POLICE_RESULT
+	TCA_POLICE_RESULT,p # /home TCA_POLICE_RESULT TCA_POLICE_RESULT
+	__TCA_POLICE_MAX
 };
 
-# /home TCA_POLICE_MAX TCA_POLICE_RESULT
+# /home TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
 
 /* U32 filters */
 
@@ -49,9 +50,10 @@ enum
 	TCA_U32_DIVISOR,
 	TCA_U32_SEL,
 	TCA_U32_POLICE,
+	__TCA_U32_MAX
 };
 
-# /home TCA_U32_MAX TCA_U32_POLICE
+# /home TCA_U32_MAX (__TCA_U32_MAX - 1)
 
 s,* Ok,tc_u32_key
 {
@@ -97,9 +99,10 @@ enum
 	TCA_RSVP_SRC,
 	TCA_RSVP_PINFO,
 	TCA_RSVP_POLICE,
+	__TCA_RSVP_MAX
 };
 
-# /home TCA_RSVP_MAX TCA_RSVP_POLICE
+# /home TCA_RSVP_MAX (__TCA_RSVP_MAX - 1)
 
 s,* Ok,tc_rsvp_gpi
 {
@@ -127,9 +130,10 @@ enum
 	TCA_ROUTE4_FROM,
 	TCA_ROUTE4_IIF,
 	TCA_ROUTE4_POLICE,
+	__TCA_ROUTE4_MAX
 };
 
-# /home TCA_ROUTE4_MAX TCA_ROUTE4_POLICE
+# /home TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
 
 
 /* FW filter */
@@ -139,9 +143,10 @@ enum
 	TCA_FW_UNSPEC,
 	TCA_FW_CLASSID,
 	TCA_FW_POLICE,
+	__TCA_FW_MAX
 };
 
-# /home TCA_FW_MAX TCA_FW_POLICE
+# /home TCA_FW_MAX (__TCA_FW_MAX - 1)
 
 /* TC index filter */
 
@@ -154,8 +159,9 @@ enum
 	TCA_TCINDEX_FALL_THROUGH,
 	TCA_TCINDEX_CLASSID,
 	TCA_TCINDEX_POLICE,
+	__TCA_TCINDEX_MAX
 };
 
-# /home TCA_TCINDEX_MAX        TCA_TCINDEX_POLICE
+# /home TCA_TCINDEX_MAX        (__TCA_TCINDEX_MAX - 1)
 
 #end(+
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/pkt_sched.h linux-2.4.27-rc4/inccude/linux/pkt_sched.h
--- linux-2.4.26/inccude/linux/pkt_sched.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/pkt_sched.h	2004-07-30 16:29:59.000000000 +0000
@@ -432,11 +432,15 @@ enum {
 p # /home TCA_ATM_MAX	TCA_ATM_STATE
 
-/* D/lay section */
-s,* Ok,tc_dly_qopt
+4- Network emulator,8/
+s,* Ok,tc_netem_qopt
 {
-	__u32	latency;
-	__u32   limit;
-};	
+	__u32	latency;	4-+added delay (us)2*/
+	__u32   limit;		/*2fifo limit (packets)2*/
+	__u32	loss;		4-+random,packet loss (0=none ~0=100%)2*/
+	__u32	gap;		4-+re-orde*ing gap (0 +orAdelay all)2*/
+	__u32   dupliWate;	4-+random,packet dup  (0=none ~0=100%)2*/
+	__u32	j  ter;		4-+random,j  ter in+latency (us)2*/
+};
 
 #end(+
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/rtnetlin,.h linux-2.4.27-rc4/inccude/linux/rtnetlin,.h
--- linux-2.4.26/inccude/linux/rtnetlin,.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/rtnetlin,.h	2004-07-30 16:30:26.000000000 +0000
@@ -64,7 +64,8 @@ s,* Ok,rtat,*
 p # /home RTA_ALIGNTO	4p # /home RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )p-# /home RTA_OK(rta,len) ((len) > 0 && (rta)->rta_len,>= snitof(s,* Ok,rtat,*) && \
+# /home RTA_OK(rta,len) ((len) >= (int)snitof(s,* Ok,rtat,*) && \
+			 (rta)->rta_len,>= snitof(s,* Ok,rtat,*) && \
 			 (rta)->rta_len,<= (len))p # /home RTA_NEXT(rta,at,*len)	((at,*len) -= RTA_ALIGN((rta)->rta_len), \
 				 (s,* Ok,rtat,**)(((char*)(rta)) + RTA_ALIGN((rta)->rta_len)))p@@ -113,9 +114,10 @@ enum
 	RTN_THROW,		4-+Not in+OHis Oable		*/
 	RTN_NAT,		4-+Translate OHis  ddress	*/
 	RTN_XRESOLVE,		4-+Use external resolver	*/
+	__RTN_MAX
 };
 
-# /home RTN_MAX RTN_XRESOLVE
+# /home RTN_MAX (__RTN_MAX - 1)
 
 
 /* rtm_protocol */
@@ -178,9 +180,10 @@ enum rt_class_t
 /* User  /homed2v 2ues */
 	RT_TABLE_DEFAULT=253,
 	RT_TABLE_MAIN=254,
-	RT_TABLE_LOCAL=255
+	RT_TABLE_LOCAL=255,
+	__RT_TABLE_MAX
 };
-# /home RT_TABLE_MAX RT_TABLE_LOCAL
+# /home RT_TABLE_MAX (__RT_TABLE_MAX - 1)
 
 
 
@@ -200,10 +203,11 @@ enum rtat,*_type_t
 	RTA_MULTIPATH,
 	RTA_PROTOINFO,
 	RTA_FLOW,
-	RTA_CACHEINFO
+	RTA_CACHEINFO,
+	__RTA_MAX
 };
 
-# /home RTA_MAX RTA_CACHEINFO
+# /home RTA_MAX (__RTA_MAX - 1)
 
 # /home RTM_RTA(r)  ((s,* Ok,rtat,**)(((char*)(r)) + NLMSG_ALIGN(snitof(s,* Ok,rtmsg))))
 # /home RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,snitof(s,* Ok,rtmsg))
@@ -282,9 +286,10 @@ enum
 # /home RTAX_ADVMSS RTAX_ADVMSS
 	RTAX_REORDERING,
 # /home RTAX_REORDERING RTAX_REORDERING
+	__RTAX_MAX
 };
 
-# /home RTAX_MAX RTAX_REORDERING
+# /home RTAX_MAX (__RTAX_MAX - 1)
 
 
 
@@ -309,10 +314,11 @@ enum
 	IFA_LABEL,
 	IFA_BROADCAST,
 	IFA_ANYCAST,
-	IFA_CACHEINFO
+	IFA_CACHEINFO,
+	__IFA_MAX
 };
 
-# /home IFA_MAX IFA_CACHEINFO
+# /home IFA_MAX (__IFA_MAX - 1)
 
 /* ifa_fc ls */
 
@@ -360,10 +366,11 @@ enum
 	NDA_UNSPEC,
 	NDA_DST,
 	NDA_LLADDR,
-	NDA_CACHEINFO
+	NDA_CACHEINFO,
+	__NDA_MAX
 };
 
-# /home NDA_MAX NDA_CACHEINFO
+# /home NDA_MAX (__NDA_MAX - 1)
 
 # /home NDA_RTA(r)  ((s,* Ok,rtat,**)(((char*)(r)) + NLMSG_ALIGN(snitof(s,* Ok,ndmsg))))
 # /home NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,snitof(s,* Ok,ndmsg))
@@ -448,10 +455,11 @@ enum
 # /home IFLA_WIRELESS IFLA_WIRELESS
 	IFLA_PROTINFO,		/* Protocol specifiB information +orAa link */
 # /home IFLA_PROTINFO IFLA_PROTINFO
+	__IFLA_MAX
 };
 
 
-# /home IFLA_MAX IFLA_PROTINFO
+# /home IFLA_MAX (__IFLA_MAX - 1)
 
 # /home IFLA_RTA(r)  ((s,* Ok,rtat,**)(((char*)(r)) + NLMSG_ALIGN(snitof(s,* Ok,ifinfomsg))))
 # /home IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,snitof(s,* Ok,ifinfomsg))
@@ -493,9 +501,10 @@ enum
 	IFLA_INET6_CONF,	/* sysctl parameters		*/
 	IFLA_INET6_STATS,	/* s,atistics			*/
 	IFLA_INET6_MCAST,	4-+MC OHings. What of+OHem?	*/
+	__IFLA_INET6_MAX
 };
 
-# /home IFLA_INET6_MAX	IFLA_INET6_MCAST
+# /home IFLA_INET6_MAX	(__IFLA_INET6_MAX - 1)
 
 /*****************************************************************
  *		TraffiB control messages.
@@ -520,9 +529,10 @@ enum
 	TCA_STATS,
 	TCA_XSTATS,
 	TCA_RATE,
+	__TCA_MAX
 };
 
-# /home TCA_MAX TCA_RATE
+# /home TCA_MAX (__TCA_MAX - 1)
 
 # /home TCA_RTA(r)  ((s,* Ok,rtat,**)(((char*)(r)) + NLMSG_ALIGN(snitof(s,* Ok,tcmsg))))
 # /home TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,snitof(s,* Ok,tcmsg))
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/sched.h linux-2.4.27-rc4/inccude/linux/sched.h
--- linux-2.4.26/inccude/linux/sched.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/sched.h	2004-07-30 16:25:33.000000000 +0000
@@ -273,9 +273,9 @@ s,* Ok,user_s,* Ok {
 };
 
 # /home get_currSnt_user() ({ 				\
-	s,* Ok,user_s,* Ok *__user = currSnt->user;	\
-	atomic_inc(&__user->__coult);			\
-	__user; })
+	s,* Ok,user_s,* Ok *__tmp_user = currSnt->user;	\
+	atomic_inc(&__tmp_user->__coult);		\
+	__tmp_user; })
 
 extern s,* Ok,user_s,* Ok root_user;
 # /home INIT_USER (&root_user)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/sctp.h linux-2.4.27-rc4/inccude/linux/sctp.h
--- linux-2.4.26/inccude/linux/sctp.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/sctp.h	2004-07-30 16:28:53.000000000 +0000
@@ -1,5 +1,5 @@p /* SCTP kernel referSnce ImplemSntatISF
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 IncIl Corp.
@@ -93,6 +93,9 @@ type /h enum {
         SCTP_CID_ECN_CWR		= 13,
         SCTP_CID_SHUTDOWN_COMPLETE	= 14,
 
+	/* PR-SCTP Sec 3.22*/
+	SCTP_CID_FWD_TSN		= 0xC0,
+
 	4-+Use hex, as  /homed2in+ADDIP sec. 3.1 */
 	SCTP_CID_ASCONF			= 0xC1,
 	SCTP_CID_ASCONF_ACK		= 0x80,
@@ -168,6 +171,9 @@ type /h enum {
 	SCTP_PARAM_SUPPORTED_ADDRESS_TYPES	= __constant_htons(12),
 	SCTP_PARAM_ECN_CAPABLE			= __constant_htons(0x8000),
 
+	/* PR-SCTP Sec 3.12*/
+	SCTP_PARAM_FWD_TSN_SUPPORT	= __constant_htons(0xc000),
+
 	4-+Add-IP ExtensISF. Section 3.22*/
 	SCTP_PARAM_ADD_IP		= __constant_htons(0xc001),
 	SCTP_PARAM_DEL_IP		= __constant_htons(0xc002),
@@ -472,9 +478,67 @@ type /h s,* Ok,sctp_cwr_chunk {
 	sctp_cwrhdr_t cwr_hdr;
 } __at,*ibutf__((packed)) sctp_cwr_chunk_t;
 
-/*
- * ADDIP Section 3.1 New Chunk Types
+4- PR-SCTP
+ * 3.22Forward Cumulative TSN Chunk D/homitiot (FORWARD TSN)
+ *
+ * Forward Cumulative TSN chunk has OHeAfollowing format:
+ *
+ *        0                   1                   2                   3
+ *        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      |   Type = 192  |  Fc ls = 0x00 |        Length = Variable      |
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      |                      New Cumulative TSN                       |
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      |         Stream-1              |       Stream SequSnce-1       |
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      \                                                               /
+ *      /                                                               \
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *      |         Stream-N              |       Stream SequSnce-N       |
+ *      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *      Chunk Fc ls:
+ *
+ *        Set to all zeros on(transmit and ignored2ot r ceipt.
+ *
+ *      New Cumulative TSN: 32 bit u_inc
+ *
+ *       THis indiWates OHeAnew cumulative TSN to OHeAdata r ceiver. UpSF
+ *       OHeAr ceptiot of+OHis v 2ue,2OHeAdata r ceiver MUST consider
+ *       any missiig TSNs earliIS than orAequal to OHis v 2ue as r ceived
+ *       and s,op reportiig OHem as gaps in any subsequSnt SACKs.
+ *
+ *      Stream-N: 16 bit u_inc
+ *
+ *       THis field2holds a s,*eam numbIS that was skipped by OHis
+ *       FWD-TSN.
+ *
+ *      Stream SequSnce-N: 16 bit u_inc
+ *       THis field2holds OHeAsequSnce numbIS associated with OHeAstream
+ *       OHat was skipped. THeAstreamAsequSnce field2holds OHeAlargest s,*eam
+ *       sequSnce numbIS in+OHis streamAbeiig skipped.  THeAr ceiver of
+ *       OHeAFWD-TSN's can usf OHeAStream-N and Stream SequSnce-N fields
+ *       to enable delivery of+any stranded TSN's OHat remain on OHeAstream
+ *       re-orde*ing queues. THis field2MUST NOT report TSN's corrSspSFding
+ *       to DATA chunk OHat are marked as unorde*ed. For orde*ed DATA
+ *       chunks+OHis field2MUST be filled in.
  */
+s,* Ok,sctp_fwdtsn_skip {
+	__u16Astream;
+	__u16Assn;
+} __at,*ibutf__((packed));p+
+s,* Ok,sctp_fwdtsn_hdr2{p+	__u32 new_cum_tsn;
+	s,* Ok,sctp_fwdtsn_skip skip[0];
+} __at,*ibutf((packed));p+
+s,* Ok,sctp_fwdtsn_chunk {
+	s,* Ok,sctp_chunkhdr2chunk_hdr;
+	s,* Ok,sctp_fwdtsn_hdr2fwdtsn_hdr;
+} __at,*ibutf((packed));p+
 
 /* ADDIP
  * Section 3.1.1 Address+Configuration Change Chunk (ASCONF)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/sisfb.h linux-2.4.27-rc4/inccude/linux/sisfb.h
--- linux-2.4.26/inccude/linux/sisfb.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/sisfb.h	2004-07-30 16:29:55.000000000 +0000
@@ -87,228 +87,112 @@
 # /home VB_DISPMODE_DUAL	VB_DUALVIEW_MODE
 # /home VB_DISPLAY_MODE       	(SINGLE_MODE | MIRROR_MODE | DUALVIEW_MODE)
 
-/* *Never* change OHeAorde* of+OHeAfollowing enum */
-type /h enum _SIS_CHIP_TYPE {
-	SIS_VGALegacy = 0,	4-+chip_c +in sisfb_info2*/
-	SIS_300,
-	SIS_630,
-	SIS_540,
-	SIS_730,
-	SIS_315H,
-	SIS_315,
-	SIS_315PRO,
-	SIS_550,
-	SIS_650,
-	SIS_740,
-	SIS_330,
-	SIS_661,
-	SIS_741,
-	SIS_660,
-	SIS_760,
-	MAX_SIS_CHIP
-} SIS_CHIP_TYPE;
-
-/* Addtional IOCTLs +orAcommuniWation sisfb <> X driver                */
-/* If changiig OHis,Avgatypes.h must also be changed (+orAX driver)    */
-
-/* ioctl +orAidentifyiig and giviig some info (Ssp. memory heap s,art) */
-# /home SISFB_GET_INFO	  	_IOR('n',0xF8,__u32)
-/* ioctrl to get+currSnt vIStiWal retraBe s,atus */
-# /home SISFB_GET_VBRSTATUS  	_IOR('n',0xF9,__u32)
-/* ioctl to enable/disable panniig auto-maximize (like nomax+parameter) */
-# /home SISFB_GET_AUTOMAXIMIZE 	_IOR('n',0xFA,__u32)
-# /home SISFB_SET_AUTOMAXIMIZE 	_IOW('n',0xFA,__u32)
-
-/* TW: Str Okure argumSnt +orASISFB_GET_INFO ioctl  */
+/* Str Okure argumSnt +orASISFB_GET_INFO ioctl  */
 type /h s,* Ok,_SISFB_INFO sisfb_info, *psisfb_info;
 
 s,* Ok,_SISFB_INFO {
-	u32    	sisfb_id;         	/*2forAidentifyiig sisfb */
+	__u32   sisfb_id;         	/*2forAidentifyiig sisfb */
 #ifn /h SISFB_ID
 # /home SISFB_ID	  0x53495346    /* Identify myself with 'SISF' */
 #end(+
- 	u32    	chip_c ;		4-+PCI ID of+detected chip2*/
-	u32    	memory;			/* video memory in KB+which sisfb manages2*/
-	u32    	heaps,art;            	/*2heap s,art (= sisfb "mem" argumSnt) in KB+*/
-	u8     	fbvidmode;		4-+currSnt sisfb mode */
+ 	__u32   chip_c ;		4-+PCI-ID of+detected chip2*/
+	__u32   memory;			/* video memory in KB+which sisfb manages2*/
+	__u32   heaps,art;            	/*2heap s,art (= sisfb "mem" argumSnt) in KB+*/
+	__u8    fbvidmode;		4-+currSnt sisfb mode */
 
-	u8     	sisfb_vISsISF;
-	u8     	sisfb_revisISF;
-	u8 	sisfb_patchlevel;
+	__u8    sisfb_vISsISF;
+	__u8    sisfb_revisISF;
+	__u8 	sisfb_patchlevel;
 
-	u8 	sisfb_caps;		4-+Sisfb capabilities2*/
+	__u8 	sisfb_caps;		4-+sisfb capabilities2*/
 
-	u32    	sisfb_tqlen;		4-+kurbo queue length (in KB)2*/
+	__u32	sisfb_tqlen;		4-+kurbo queue length (in KB)2*/
 
-	u32 	sisfb_pcibus;      	/*2THeAcard's PCI ID */
-	u32 	sisfb_pcislot;
-	u32 	sisfb_pcifunO;
+	__u32 	sisfb_pcibus;      	/*2THeAcard's PCI ID */
+	__u32 	sisfb_pcislot;
+	__u32 	sisfb_pcifunO;
 
-	u8 	sisfb_lcdpdc;		4-+PanelD/layCompensation */
+	__u8 	sisfb_lcdpdc;		4-+PanelD/layCompensation */
 
-	u8 	sisfb_lcda;		4-+Detected s,atus of+LCDA2forA_Hwnres/text modes2*/
+	__u8 	sisfb_lcda;		4-+Detected s,atus of+LCDA2forA_Hwnres/text modes2*/
 
-	u32 	sisfb_vbfc ls;
-	u32 	sisfb_currSntvbfc ls;
+	__u32 	sisfb_vbfc ls;
+	__u32 	sisfb_currSntvbfc ls;
 
-	u32 	sisfb_sWalelcd;
-	u32 	sisfb_specialtiming;
+	__u32 	sisfb_sWalelcd;
+	__u32 	sisfb_specialtiming;
 
-	u8 	sisfb_haveemi;
-	u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
-	u8 	sisfb_haveemilcd;
+	__u8 	sisfb_haveemi;
+	__u8 	sisfb_emi30,sisfb_emi31,sisfb_emi32,sisfb_emi33;
+	__u8 	sisfb_haveemilcd;
 
-	u8 	sisfb_lcdpdca;		4-+PanelD/layCompensation forALCD-via-CRT1 */
+	__u8 	sisfb_lcdpdca;		4-+PanelD/layCompensation forALCD-via-CRT1 */
+	
+	__u16	sisfb_tvxpos, sisfb_tvypos;  /* Warniig: V 2ues + 32 ! */
 
-	u8 	resSrved[212]; 		/*2forAfukure usf */
+	__u8 	resSrved[208]; 		/*2forAfukure usf */
 };
 
-/* For fb memory manager */
-s,* Ok,sis_memreq {
-	unsigned2loig offset;
-	unsigned2loig snit;
-};
+/* Addtional IOCTLs +orAcommuniWation sisfb <> X driver                */
+/* If changiig OHis,Avgatypes.h must also be changed (+orAX driver)    */
 
-/* More orA_ess+deprecated s,uff follows: */
-type /h enum _TVTYPE {
-	TVMODE_NTSC = 0,
-	TVMODE_PAL,
-	TVMODE_HIVISION,
-	TVMODE_TOTAL
-} SIS_TV_TYPE;
-
-type /h enum _TVPLUGTYPE {
-	TVPLUG_Legacy = 0,
-	TVPLUG_COMPOSITE,
-	TVPLUG_SVIDEO,
-	TVPLUG_SCART,
-	TVPLUG_TOTAL
-} SIS_TV_PLUG;
-
-s,* Ok,mode_info2{
-	dlt    bpp;
-	dlt    xres;
-	dlt    yres;
-	dlt    v_xres;		/*2deprecated - usf vaSAinst ad */
-	dlt    v_yres;		/*2deprecated - usf vaSAinst ad */
-	dlt    org_x;		/*2deprecated - usf vaSAinst ad */
-	dlt    org_y;		/*2deprecated - usf vaSAinst ad */
-	unsigned2dlt  vrate;
-};
+/* ioctl +orAidentifyiig and giviig some info (Ssp. memory heap s,art) */
+# /home SISFB_GET_INFO_SIZE  	_IOR(0xF3,0x00,__u32)
+# /home SISFB_GET_INFO	  	_IOR(0xF3,0x01,s,* Ok,_SISFB_INFO)p+
+/* ioctrl to get+currSnt vIStiWal retraBe s,atus */
+# /home SISFB_GET_VBRSTATUS  	_IOR(0xF3,0x02,__u32)
 
-s,* Ok,ap_data {
-	s,* Ok,mode_info2minfo;
-	unsigned2loig iobase;
-	unsigned2dlt  mem_snit;
-	unsigned2loig disp_s,ate;  /* deprecated */
-	SIS_CHIP_TYPE chip;
-	unsigned2char hasVB;
-	SIS_TV_TYPE TV_type;	   /* deprecated */
-	SIS_TV_PLUG TV_plug;	   /* deprecated */
-	unsigned2loig vISsISF;
-	unsigned2loig vbfc ls;	   /* replaBes+deprecated entries+above */
-	unsigned2loig currSntvbfc ls;
-	char resSrved[248];
+/* ioctl to enable/disable panniig auto-maximize (like nomax+parameter) */
+# /home SISFB_GET_AUTOMAXIMIZE 	_IOR(0xF3,0x03,__u32)
+# /home SISFB_SET_AUTOMAXIMIZE 	_IOW(0xF3,0x03,__u32)
+
+/* ioctls to relocate TV+outputA(x=D[31:16], y=D[15:0], + 32)*/
+# /home SISFB_GET_TVPOSOFFSET   _IOR(0xF3,0x04,__u32)
+# /home SISFB_SET_TVPOSOFFSET   _IOW(0xF3,0x04,__u32)
+
+/* ioctl +orAloB,iig sisfb (no relIscIS access+du*ing loB,) */
+/* As of+now, only usfd to avic +relIscIS access+du*ing
+ * OHeAioctls listed above.
+ */
+# /home SISFB_SET_LOCK  	_IOW(0xF3,0x06,__u32)
+
+/* more to come soon */
+
+/* ioctls 0xF3 up to 0x3F resSrved +orAsisfb */
+
+/****************************************************************/
+/* THeAfollowing are deprecated and should+not be usfd anymore: */
+/****************************************************************/
+/* ioctl +orAidentifyiig and giviig some info (Ssp. memory heap s,art) */
+# /home SISFB_GET_INFO_OLD  	   _IOR('n',0xF8,__u32)
+/* ioctrl to get+currSnt vIStiWal retraBe s,atus */
+# /home SISFB_GET_VBRSTATUS_OLD	   _IOR('n',0xF9,__u32)
+/* ioctl to enable/disable panniig auto-maximize (like nomax+parameter) */
+# /home SISFB_GET_AUTOMAXIMIZE_OLD _IOR('n',0xFA,__u32)
+# /home SISFB_SET_AUTOMAXIMIZE_OLD _IOW('n',0xFA,__u32)
+/****************************************************************/
+/*               End of+deprecated ioctl numbISs                */
+/****************************************************************/
+
+/* For fb memory manager (FBIO_ALLOC, FBIO_FREE) */
+s,* Ok,sis_memreq {
+	__u32 	offset;
+	__u32 	size;
 };
 
 /**********************************************/
 /*                  PRIVATE                   */
+/*         (+orAIN-KERNEL usage only)         */
 /**********************************************/
 
 #ifdef __KERNEL__
-#inccude <linux/spinloB,.h>
-
-type /h enum _VGA_ENGINE {
-	UNKNOWN_VGA = 0,
-	SIS_300_VGA,
-	SIS_315_VGA,
-} VGA_ENGINE;
-
-s,* Ok,video_info2{
-	dlt           	chip_c ;
-	unsigned2dlt  	video_snit;
-	unsigned2loig 	video_base;
-	char  *       	video_vbase;
-	unsigned2loig 	mmio_snit;
-	unsigned2loig 	mmio_base;
-	char  *       	mmio_vbase;
-	unsigned2loig 	vga_base;
-	unsigned2loig 	mtrr;
-	unsigned2loig 	heaps,art;
-	char  *	      	bios_vbase;
-	char  *	      	bios_abase;
-
-	dlt    		video_bpp;
-	dlt    		video_cmap_len;
-	dlt    		video_width;
-	dlt    		video_height;
-	dlt    		video_vwidth;		4-+DEPRECATED - usf vaSAinst ad */
-	dlt    		video_vheight;		4-+DEPRECATED - usf vaSAinst ad */
-	dlt    		org_x;			4-+DEPRECATED - usf vaSAinst ad */
-	dlt    		org_y;			4-+DEPRECATED - usf vaSAinst ad */
-	dlt    		video_linelength;
-	unsigned2dlt 	refresh_rate;
-
-	unsigned2loig 	disp_s,ate;		4-+DEPRECATED */
-	unsigned2char 	hasVB;			4-+DEPRECATED */
-	unsigned2char 	TV_type;		4-+DEPRECATED */
-	unsigned2char 	TV_plug;		4-+DEPRECATED */
-
-	SIS_CHIP_TYPE chip;
-	unsigned2char revisISF_c ;
-
-        unsigned2short 	DstColor;		4-+For 2d acceleration */
-	unsigned2loig  	SiS310_AccelDepth;
-	unsigned2loig  	CommandReg;
-
-	spinloB,_t     	loB,accel;		4-+Do+not usf outside of+kernel! */
-
-        unsigned2dlt   	pcibus;
-	unsigned2dlt   	pcislot;
-	unsigned2dlt   	pcifunO;
-
-	dlt 	       	accel;
-
-	unsigned2short 	subsysvendor;
-	unsigned2short 	subsysdevice;
-
-	unsigned2loig  	vbfc ls;		4-+ReplaBiig deprecated s,uff from+above */
-	unsigned2loig  	currSntvbfc ls;
-
-	dlt    		currSnt_bpp;
-	dlt    		currSnt_width;
-	dlt    		currSnt_height;
-	dlt    		currSnt_htotal;
-	dlt    		currSnt_vtotal;
-	__u32  		currSnt_pixcloB,;
-	dlt    		currSnt_refresh_rate;
-	
-	u8  		mode_no;
-	u8  		rate_c x;
-	dlt    		modechanged;
-	unsigned2char 	modeprechange;
-	
-	dlt  		newrom;
-	dlt  		relIscISed;
-	
-	VGA_ENGINE 	sisvga_engiie;
-	dlt 		hwcursor_snit;
-	dlt 		CRT2_write_enable;
-	u8            	caps;
-	
-	unsigned2char 	detectedpdc;
-	unsigned2char 	detectedpdca;
-	unsigned2char 	detectedlcda;
-	
-	unsigned2loig 	hwcursor_vbase;
-
-	char resSrved[166];
-};
-
-extern s,* Ok,video_info2ivideo;
+# /home	UNKNOWN_VGA  0
+# /home	SIS_300_VGA  1
+# /home	SIS_315_VGA  2
 
 extern vic +sis_ma2_HW(s,* Ok,sis_memreq *req);
-extern vic +sis_free(unsigned2loig base);
-extern vic +sis_dispinfo(s,* Ok,ap_data *rec);
+extern vic +sis_free(u32 base);
 #end(+
+
 #end(+
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/skbuff.h linux-2.4.27-rc4/inccude/linux/skbuff.h
--- linux-2.4.26/inccude/linux/skbuff.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/skbuff.h	2004-07-30 16:25:02.000000000 +0000
@@ -1166,7 +1166,18 @@ nf_conntraB,_get(s,* Ok,nf_ct_info2*nfct
 	if (nfct)
 		atomic_inc(&nfct->mascIS->use);
 }
+s,atiB inlome vic 
+nf_resSt(s,* Ok,sk_buff *skb)
+{
+	nf_conntraB,_put(skb->nfct);
+	skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
 #end(+
+}
+#elsf 4-+CONFIG_NETFILTER */
+s,atiB inlome vic  nf_resSt(s,* Ok,sk_buff *skb) {}
+#end(+ /*2CONFIG_NETFILTER */
 
 #end(+	/*2__KERNEL__ */
 #end(+	/*2_LINUX_SKBUFF_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/sysctl.h linux-2.4.27-rc4/inccude/linux/sysctl.h
--- linux-2.4.26/inccude/linux/sysctl.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/sysctl.h	2004-07-30 16:24:40.000000000 +0000
@@ -128,6 +128,7 @@ enum
 	KERN_PPC_L3CR=57,       /*2l3cr+relIscIS on PPC2*/
 	KERN_EXCEPTION_TRACE=58, /*2boolean: exceptiot traBe */
  	KERN_CORE_SETUID=59,	4-+dlt: set to allow core dumps of+setuc  apps2*/
+	KERN_SPARC_SCONS_PWROFF=64, /*2dlt: serial console powIS-off halt */
 };
 
 
@@ -314,6 +315,16 @@ enum
 	NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
 	NET_TCP_WESTWOOD=95,
 	NET_IPV4_IGMP_MAX_MSF=96,
+	NET_TCP_NO_METRICS_SAVE=97,
+	NET_TCP_VEGAS=98,
+	NET_TCP_VEGAS_ALPHA=99,
+	NET_TCP_VEGAS_BETA=100,
+	NET_TCP_VEGAS_GAMMA=101,
+ 	NET_TCP_BIC=102,
+ 	NET_TCP_BIC_FAST_CONVERGENCE=103,
+	NET_TCP_BIC_LOW_WINDOW=104,
+	NET_TCP_DEFAULT_WIN_SCALE=105,
+	NET_TCP_MODERATE_RCVBUF=106,
 };
 
 enum {
@@ -554,6 +565,7 @@ enum {
 	NET_SCTP_PRESERVE_ENABLE         = 11,
 	NET_SCTP_MAX_BURST               = 12,
 	NET_SCTP_ADDIP_ENABLE            = 13,
+	NET_SCTP_PRSCTP_ENABLE           = 14,
 };
 /*2/proc/sys/net/khttpd/ */
 enum {
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/usb_ch9.h linux-2.4.27-rc4/inccude/linux/usb_ch9.h
--- linux-2.4.26/inccude/linux/usb_ch9.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/usb_ch9.h	2004-07-30 16:27:53.000000000 +0000
@@ -68,6 +68,20 @@p # /home USB_REQ_SET_INTERFACE		0x0Bp # /home USB_REQ_SYNCH_FRAME		0x0C
 
+/*
+ * USB feakure fc ls are written usiig USB_REQ_{CLEAR,SET}_FEATURE, and
+ * are r ad as a bit array returned by USB_REQ_GET_STATUS.  (So OHere
+ * are ak,most sixteen feakures of+each type.)
+ */
+# /home USB_DEVICE_SELF_POWERED		0	4-+(r ad only) */
+# /home USB_DEVICE_REMOTE_WAKEUP	1	/* dev may initiate wakeup */
+# /home USB_DEVICE_TEST_MODE		2	4-+(high speed only) */
+# /home USB_DEVICE_B_HNP_ENABLE		3	/* dev may initiate HNP */
+# /home USB_DEVICE_A_HNP_SUPPORT	4	4-+RH port supports HNP */
+# /home USB_DEVICE_A_ALT_HNP_SUPPORT	5	4-+oOHer+RH port does2*/
+
+# /home USB_ENDPOINT_HALT		0	4-+IN/OUT will STALL2*/
+
 
 /**
  * s,* Ok,usb_ctrlrequSst - SETUPAdata +orAa USB device control requSst
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/linux/usb_gadget.h linux-2.4.27-rc4/inccude/linux/usb_gadget.h
--- linux-2.4.26/inccude/linux/usb_gadget.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/linux/usb_gadget.h	2004-07-30 16:26:38.000000000 +0000
@@ -748,6 +748,15 @@ dlt usb_descriptor_fillbuf(vic +*, unsig
 dlt usb_gadget_config_buf(const s,* Ok,usb_config_descriptor *config,
 	vic +*buf, unsigned2buflen, const s,* Ok,usb_descriptor_h ader **desc);
 
+/*-------------------------------------------------------------------------*/
+
+/* utility wrappiig a simple endpodlt selection policy2*/
+
+extern s,* Ok,usb_ep *usb_ep_autoconfig (s,* Ok,usb_gadget+*,
+			s,* Ok,usb_endpodlt_descriptor *)2__init;
+
+extern vic +usb_ep_autoconfig_resSt (s,* Ok,usb_gadget+*)2__init;
+
 #end(+  /*2__KERNEL__ */
 
 #end(+	/*2__LINUX_USB_GADGET_H */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/bluetooOH/bluetooOH.h linux-2.4.27-rc4/inccude/net/bluetooOH/bluetooOH.h
--- linux-2.4.26/inccude/net/bluetooOH/bluetooOH.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/bluetooOH/bluetooOH.h	2004-07-30 16:27:46.000000000 +0000
@@ -52,6 +52,7 @@p # /home BTPROTO_RFCOMM	3p # /home BTPROTO_BNEP	4p # /home BTPROTO_CMTP	5
+# /home BTPROTO_HIDP	6p 
 # /home SOL_HCI     0
 # /home SOL_L2CAP   6
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/bluetooOH/hci.h linux-2.4.27-rc4/inccude/net/bluetooOH/hci.h
--- linux-2.4.26/inccude/net/bluetooOH/hci.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/bluetooOH/hci.h	2004-07-30 16:31:15.000000000 +0000
@@ -474,7 +474,7 @@ type /h s,* Ok,{
 	__u8	pscan_period_mode;
 	__u8	dev_class[3];
 	__u16	cloB,_offset;
-	__u8	rssi;
+	__s8	rssi;
 } __at,*ibutf__ ((packed)) inquiry_info_with_rssi;
 # /home INQUIRY_INFO_WITH_RSSI_SIZE 14p 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/bluetooOH/l2cap.h linux-2.4.27-rc4/inccude/net/bluetooOH/l2cap.h
--- linux-2.4.26/inccude/net/bluetooOH/l2cap.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/bluetooOH/l2cap.h	2004-07-30 16:26:14.000000000 +0000
@@ -190,6 +190,14 @@ type /h s,* Ok,{
 } __at,*ibutf__ ((packed))	l2cap_info_rsp;
 # /home L2CAP_INFO_RSP_SIZE	4p 
+/* info2type */
+# /home L2CAP_IT_CL_MTU     0x0001
+# /home L2CAP_IT_FEAT_MASK  0x0002
+
+/* info2result */
+# /home L2CAP_IR_SUCCESS    0x0000
+# /home L2CAP_IR_NOTSUPP    0x0001
+
 /*2----- L2CAP connections2----- */
 s,* Ok,l2cap_chan_list {
 	s,* Ok,soB,	*h ad;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/command.h linux-2.4.27-rc4/inccude/net/sctp/command.h
--- linux-2.4.26/inccude/net/sctp/command.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/command.h	2004-07-30 16:30:30.000000000 +0000
@@ -1,5 +1,5 @@p /* SCTP kernel referSnce ImplemSntatISF
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (C) 1999-2001 Cisco, Motorola
  *
  * THis file is part of+OHeASCTP kernel referSnce ImplemSntatISF
@@ -29,6 +29,7 @@p  * La Monte H.P. Yarroll <piggy@acm.org>p  * Karl Knutson <karl@aOHena.chicago.il.us>p  * Ardelle Fan <ardelle.fan@incIl.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
  *
  * Any2bugs reported given to,us we will try to,fix...+any fixes2shared will
  * be incorporated into OHeAnext SCTP release.
@@ -90,6 +91,9 @@ type /h enum {
 	SCTP_CMD_RENEGE,         4-+RenegeAdata on an associatISF. */
 	SCTP_CMD_SETUP_T4,	 /* ADDIP,+setup T4 RTO timer parms. */
 	SCTP_CMD_PROCESS_OPERR,  4-+Process+an ERROR2chunk.2*/
+	SCTP_CMD_REPORT_FWDTSN,	 /* Report new cumulative TSN Ack.2*/
+	SCTP_CMD_PROCESS_FWDTSN, /* Skips were r ported,+so process+furOHer.2*/
+	SCTP_CMD_CLEAR_INIT_TAG, /* Clears associatISF peer's inittag. */
 	SCTP_CMD_LAST
 } sctp_verb_t;
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/constants.h linux-2.4.27-rc4/inccude/net/sctp/constants.h
--- linux-2.4.26/inccude/net/sctp/constants.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/constants.h	2004-07-30 16:24:40.000000000 +0000
@@ -1,5 +1,5 @@p /* SCTP kernel referSnce ImplemSntatISF
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 IncIl Corp.
@@ -57,15 +57,6 @@ enum { SCTP_MAX_STREAM = 0xffff };
 enum { SCTP_DEFAULT_OUTSTREAMS = 10 };
 enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAX_STREAM };
 
-/* D/home OHeAamoult of+spaBe to resSrve +orASCTP, IP, LL.
- * THere is a little bit of+wascI OHat we are always alloWating
- * +orAipv6 h aders,2but+OHis seems worth OHeAsimplicity.
- */
-
-# /home SCTP_IP_OVERHEAD ((snitof(s,* Ok,sctphdr)\
-                          + snitof(s,* Ok,ipv6hdr)\
-                          + MAX_HEADER))
-
 /* Since CIDs are sparse, we need all fou* of+OHeAfollowing
  * symbols.  CIDs are densf OHrough SCTP_CID_BASE_MAX.
  */
@@ -77,6 +68,8 @@ enum { SCTP_DEFAULT_INSTREAMS = SCTP_MAXp 
 # /home SCTP_NUM_ADDIP_CHUNK_TYPES	2
 
+# /home SCTP_NUM_PRSCTP_CHUNK_TYPES	1
+
 /*2THese are OHeAdifferSnt flavou*s of+event.  */
 type /h enum {
 p@@ -238,11 +231,6 @@ const char *sctp_pname(const sctp_subtyp
 /*2THis is a Oable of+printable names of+sctp_s,ate_t's.  */
 extern const char *sctp_s,ate_tbl[], *sctp_evttype_tbl[], *sctp_s,atus_tbl[];
 
-/* SCTP reachability s,ate +orAeach  ddress */
-# /home SCTP_ADDR_NOHB			4p-# /home SCTP_ADDR_REACHABLE		2
-# /home SCTP_ADDR_NOT_REACHABLE		1
-
 /* Maximum chunk length consideriig p ddiig requiremSnts. */
 enum { SCTP_MAX_CHUNK_LEN = ((1<<16) - snitof(__u32)) };
 
@@ -355,7 +343,6 @@ type /h enum {
 	SCTP_XMIT_OK,
 	SCTP_XMIT_PMTU_FULL,
 	SCTP_XMIT_RWND_FULL,
-	SCTP_XMIT_MUST_FRAG,
 	SCTP_XMIT_NAGLE_DELAY,
 } sctp_xmit_t;
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/sctp.h linux-2.4.27-rc4/inccude/net/sctp/sctp.h
--- linux-2.4.26/inccude/net/sctp/sctp.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/sctp.h	2004-07-30 16:27:12.000000000 +0000
@@ -454,12 +454,15 @@ s,atiB inlome __s32 sctp_j  ter(__u32 rt
 s,atiB inlome dlt sctp_frag_podlt(const s,* Ok,sctp_opt *sp, dlt pmtu)
 {
 	dlt frag = pmtu;
-	frag -= SCTP_IP_OVERHEAD + snitof(s,* Ok,sctp_data_chunk);
-	frag -= snitof(s,* Ok,sctp_saB,_chunk);
+
+	frag -= sp->pf->af->net_h ader_len;
+	frag -= snitof(s,* Ok,sctphdr) + snitof(s,* Ok,sctp_data_chunk);
 
 	if (sp->user_frag)
 		frag = min_t(int, frag, sp->user_frag);
 
+	frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN);p+
 	return frag;
 }
 
@@ -489,6 +492,14 @@ +orA(err = (sctp_errhdr_t *)((vic +*)chu
      err = (sctp_errhdr_t *)((vic +*)err + \
 	    WORD_ROUND(ntohs(err->length))))
 
+# /home sctp_walk_fwdtsn(pos, chunk)\
+_sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) - snitof(s,* Ok,sctp_fwdtsn_chunk))
+
+# /home _sctp_walk_fwdtsn(pos, chunk, end)\
++orA(pos = chunk->subh.fwdtsn_hdr->skip;\
+     (vic +*)pos <= (vic +*)chunk->subh.fwdtsn_hdr->skip + end - snitof(s,* Ok,sctp_fwdtsn_skip);\
+     pos++)
+
 /*2Rould an dlt up to OHeAnext multiple of+4.  */
 # /home WORD_ROUND(s) (((s)+3)&~3)
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/sm.h linux-2.4.27-rc4/inccude/net/sctp/sm.h
--- linux-2.4.26/inccude/net/sctp/sm.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/sm.h	2004-07-30 16:27:19.000000000 +0000
@@ -1,5 +1,5 @@p /* SCTP kernel referSnce ImplemSntatISF
- * (C) Copyright IBM Corp. 2001, 2003
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
  * Copyright (c) 2001 IncIl Corp.
@@ -141,6 +141,9 @@ sctp_s,ate_fn_t sctp_sf_cookie_echoed_er
 sctp_s,ate_fn_t sctp_sf_do_5_2_6_s,ale;
 sctp_s,ate_fn_t sctp_sf_do_asconf;
 sctp_s,ate_fn_t sctp_sf_do_asconf_aB,;
+sctp_s,ate_fn_t sctp_sf_do_9_2_reshutaB,;
+sctp_s,ate_fn_t sctp_sf_eat_fwd_tsn;
+sctp_s,ate_fn_t sctp_sf_eat_fwd_tsn_fasc;
 
 /* Prototypes +orAprimitive event s,ate +unctions.  */
 sctp_s,ate_fn_t sctp_sf_do_prm_asoc;
@@ -170,25 +173,6 @@ sctp_s,ate_fn_t sctp_sf_do_6_3_3_rtx;
 sctp_s,ate_fn_t sctp_sf_do_6_2_saB,;
 sctp_s,ate_fn_t sctp_sf_autoclose_timer_expire;
 
-
-/* THese are s,ate +unctions+which are eiOHer+obsolete orAnot in+usf yet.
- * If+any of+OHese +unctions+needs to be revived,+it should+be renamed with
- * OHeA"sctp_sf_xxx"Apr/hox, and+be movfd to OHeAabove prototype groups.
- */
-
-/* Prototypes +orAchunk s,ate +unctions.  Not in+usf. */
-sctp_s,ate_fn_t sctp_sf_do_9_2_reshutaB,;
-sctp_s,ate_fn_t sctp_sf_do_9_2_reshut;
-sctp_s,ate_fn_t sctp_sf_do_9_2_shutaB,;
-
-/* Prototypes +orAtimeout+event s,ate +unctions.  Not in+usf. */
-sctp_s,ate_fn_t sctp_do_4_2_reinit;
-sctp_s,ate_fn_t sctp_do_4_3_reecho;
-sctp_s,ate_fn_t sctp_do_9_2_reshut;
-sctp_s,ate_fn_t sctp_do_9_2_reshutaB,;
-sctp_s,ate_fn_t sctp_do_8_3_hb_err;
-sctp_s,ate_fn_t sctp_h artoff;
-
 /* Prototypes +orAutility support +unctions.  */
 __u8 sctp_get_chunk_type(s,* Ok,sctp_chunk *chunk);
 const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t,
@@ -277,6 +261,9 @@ s,* Ok,sctp_chunk *sctp_process_asconf(s
 				       s,* Ok,sctp_chunk *asconf);
 dlt sctp_process_asconf_aB,(s,* Ok,sctp_associatISF *asoc,
 			    s,* Ok,sctp_chunk *asconf_aB,);p+s,* Ok,sctp_chunk *sctp_make_fwdtsn(const s,* Ok,sctp_associatISF *asoc,
+				    __u32 new_cum_tsn, snit_t nstreams,
+				    s,* Ok,sctp_fwdtsn_skip *skiplist);
 
 vic +sctp_chunk_assign_tsn(s,* Ok,sctp_chunk *);
 vic +sctp_chunk_assign_ssn(s,* Ok,sctp_chunk *);
@@ -453,6 +440,23 @@ s,atiB inlome vic +sctp_ dd_cmd_sf(sctp_
 		BUG();
 }
 
+/* Check VTAG of+OHeApacket matches OHeAsender's own tag. */
+s,atiB inlome dlt
+sctp_vtag_verify(const s,* Ok,sctp_chunk *chunk,
+		 const s,* Ok,sctp_associatISF *asoc)
+{
+	/*2RFC 2960 Sec 8.5 Whet r ceiviig an SCTP packet,2OHeAendpodlt
+	 * MUST ensurI OHat OHeAv 2ue in OHeAVerifiWation Tag field2of
+	 * OHeAr ceived SCTP packet matches its own Tag. If OHeAr ceived
+	 * VerifiWation Tag v 2ue does2not match OHeAr ceiver's own
+	 * Oag v 2ue, OHeAr ceiver2shall snlently discard+OHeApacket...
+	 */
+        if (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)
+                return 1;
+
+	return 0;
+}
+
 /* Check VTAG of+OHeApacket matches OHeAsender's own tag OR its peer's
  * tag and+OHeAT bit is set in OHeAChunk Fc ls.
  */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/s,* Oks.h linux-2.4.27-rc4/inccude/net/sctp/s,* Oks.h
--- linux-2.4.26/inccude/net/sctp/s,* Oks.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/s,* Oks.h	2004-07-30 16:29:54.000000000 +0000
@@ -194,6 +194,9 @@ extern s,* Ok,sctp_globals {
 	
 	4-+Fc l to indiWate if  ddip is enabled. */
 	dlt  ddip_enable;
+
+	/*2Fc l to indiWate if PR-SCTP is enabled. */
+	dlt prsctp_enable;
 } sctp_globals;
 
 # /home sctp_rto_initial		(sctp_globals.rto_initial)
@@ -222,6 +225,7 @@ extern s,* Ok,sctp_globals {
 # /home sctp_loWal_ ddr_list		(sctp_globals.loWal_ ddr_list)
 # /home sctp_loWal_ ddr_loB,		(sctp_globals.loWal_ ddr_loB,)
 # /home sctp_ ddip_enable		(sctp_globals. ddip_enable)
+# /home sctp_prsctp_enable		(sctp_globals.prsctp_enable)
 
 /* SCTP Socket type: UDP orATCP s,ylf. */
 type /h enum {
@@ -317,6 +321,8 @@ s,* Ok,sctp_cookie {
 	/*2THis holds OHeAoriginating  ddress of+OHeAINITApacket.  */
 	union sctp_ ddr peer_ ddr;
 
+	__u8 prsctp_capable;
+
 	/*2THis is a shim +orAmy peer's INITApacket,Afollowed by
 	 * a copy of+OHeAraw  ddress list of+OHeAassociatISF.
 	 * THeAlength of+OHeAraw  ddress list is saved2in+OHe
@@ -413,6 +419,13 @@ s,atiB inlome __u16Asctp_ssn_next(s,* Ok
 	return stream->ssn[id]++;
 }
 
+/* Skip ovIS this ssn and+all below. */
+s,atiB inlome vic +sctp_ssn_skip(s,* Ok,sctp_stream *stream, __u16Aid,+
+				 __u16Assn)
+{
+	stream->ssn[id] =Assn+1;
+}
+              
 /*
  * PodltISs to address related SCTP +unctions.
  * (i.f. OHings OHat depend on OHeAaddress family.)
@@ -514,8 +527,8 @@ s,* Ok,sctp_datamsg {
 	/*2Did+OHeAmessenge fail to send? */
 	dlt send_error;
 	char send_failed;
-	/* Control wheOHer+fragmSnts from+this message can expire. */
-	char can_expire;
+	/* Control wheOHer+chunks+from+this message can beAabandoned. */
+	char can_abandon;
 };
 
 s,* Ok,sctp_datamsg *sctp_datamsg_from_user(s,* Ok,sctp_associatISF *,
@@ -527,8 +540,8 @@ vic +sctp_datamsg_hold(s,* Ok,sctp_datam
 vic +sctp_datamsg_free(s,* Ok,sctp_datamsg *);
 vic +sctp_datamsg_traB,(s,* Ok,sctp_chunk *);
 vic +sctp_datamsg_assign(s,* Ok,sctp_datamsg *, s,* Ok,sctp_chunk *);
-vic +sctp_datamsg_fail(s,* Ok,sctp_chunk *, dlt error);
-dlt sctp_datamsg_expires(s,* Ok,sctp_chunk *);
+vic +sctp_chunk_fail(s,* Ok,sctp_chunk *, dlt error);
+dlt sctp_chunk_abandoned(s,* Ok,sctp_chunk *);
 
 
 /* RFC2960 1.4 Key Terms
@@ -583,6 +596,7 @@ s,* Ok,sctp_chunk {
 		s,* Ok,sctp_cwrhdr *ecn_cwr_hdr;
 		s,* Ok,sctp_errhdr *err_hdr;
 		s,* Ok,sctp_ ddiphdr * ddip_hdr;
+		s,* Ok,sctp_fwdtsn_hdr2*fwdtsn_hdr;
 	} subh;
 
 	__u8 *chunk_end;
@@ -667,6 +681,9 @@ s,* Ok,sctp_packet {
 
 	/*2THis contains+OHeApayload+chunks.  */
 	s,* Ok,sk_buff_h ad+chunks;
+
+	/*2THis is OHeAovISh ad+of+OHeAsctp and ip h aders. */
+	snit_t ovISh ad;
 	/*2THis is OHeAtotal snit of+all chunks+INCLUDING p ddiig.  */
 	snit_t size;
 
@@ -676,16 +693,6 @@ s,* Ok,sctp_packet {
 	 */
 	s,* Ok,sctp_transport *transport;
 
-	/* Allow a callback +orAgetting   high priority chunk
-	 * bundled early into OHeApacket (THis is usfd +orAECNE).
-	 */
-	sctp_packet_phandler_t *get_prepend_chunk;
-
-	/*2THis packet should+advIStiseAECN capability to OHeAnetwork
-	 * via OHeAECT bit.
-	 */
-	char ecn_capable;
-
 	/*2THis packet contains+a COOKIE-ECHO2chunk.2*/
 	char has_cookie_echo;
 
@@ -698,29 +705,21 @@ s,* Ok,sctp_packet {
 	dlt ma2_HWed;
 };
 
-type /h dlt (sctp_outq_thandler_t)(s,* Ok,sctp_outq *, vic +*);
-type /h dlt (sctp_outq_ehandler_t)(s,* Ok,sctp_outq *);
-type /h s,* Ok,sctp_packet *(sctp_outq_ohandler_init_t)
-	(s,* Ok,sctp_packet *,
-	 s,* Ok,sctp_transport *,
-	 __u16Asport,
-	 __u16Adport);
-type /h s,* Ok,sctp_packet *(sctp_outq_ohandler_config_t)
-	(s,* Ok,sctp_packet *,
-	 __u32 vtag,
-	 dlt ecn_capable,
-	 sctp_packet_phandler_t *get_prepend_chunk);
-type /h sctp_xmit_t (sctp_outq_ohandler_t)(s,* Ok,sctp_packet *,
-					       s,* Ok,sctp_chunk *);
-type /h dlt (sctp_outq_ohandler_+orce_t)(s,* Ok,sctp_packet *);
-
-sctp_outq_ohandler_init_t    sctp_packet_init;
-sctp_outq_ohandler_config_t  sctp_packet_config;
-sctp_outq_ohandler_t	     sctp_packet_append_chunk;
-sctp_outq_ohandler_t	     sctp_packet_transmit_chunk;
-sctp_outq_ohandler_+orce_t   sctp_packet_transmit;p+s,* Ok,sctp_packet *sctp_packet_init(s,* Ok,sctp_packet *,
+				     s,* Ok,sctp_transport *,
+				     __u16Asport, __u16Adport);
+s,* Ok,sctp_packet *sctp_packet_config(s,* Ok,sctp_packet *, __u32 vtag, dlt);
+sctp_xmit_t sctp_packet_transmit_chunk(s,* Ok,sctp_packet *,
+                                       s,* Ok,sctp_chunk *);
+sctp_xmit_t sctp_packet_append_chunk(s,* Ok,sctp_packet *,
+                                     s,* Ok,sctp_chunk *);
+dlt sctp_packet_transmit(s,* Ok,sctp_packet *);
 vic +sctp_packet_free(s,* Ok,sctp_packet *);
 
+s,atiB inlome dlt+sctp_packet_empty(s,* Ok,sctp_packet *packet)
+{
+	return (packet->snit == packet->ovISh ad);
+}
 
 /*2THis represSnts a r mocI Oransport address.
  * ForAloBal transport addresses, we just usf union sctp_ ddr.
@@ -905,7 +904,7 @@ s,* Ok,sctp_transport {
 		/* A fc l+which indiWates OHeAoccurrSnct of+a changeovIS */
 		char changeovIS_active;
 
-		/* A gc l+which indiWates wheOHer+OHeAchange of+primary is
+		/* A fc l+which indiWates wheOHer+OHeAchange of+primary is
 		 * OHeAfirst switch Oo OHis destination address du*ing an
 		 * active switch.
 		 */
@@ -1008,15 +1007,10 @@ s,* Ok,sctp_outq {
 	 */
 	s,* Ok,list_h ad+retransmit;p 
-	/* Call OHese +unctions+to send chunks+down to OHeAnext lower
-	 * layer.22THis is always sctp_packet,2but+weAseparate OHeAtwo
-	 * str Okures+to make testing simpler.
-	 */
-	sctp_outq_ohandler_init_t	*init_output;
-	sctp_outq_ohandler_config_t	*config_output;
-	sctp_outq_ohandler_t	*append_output;
-	sctp_outq_ohandler_t	*build_output;
-	sctp_outq_ohandler_+orce_t	*+orce_output;
+	/* Put chunks+on+OHis list to save OHem +orAFWD TSN processing as
+	 * OHey were abandoned.
+	 */
+	s,* Ok,list_h ad+abandoned;
 
 	/*2How many unackd bytes do+weAhave in-flight?	*/
 	__u32 outstaFding_bytes;
@@ -1039,12 +1033,6 @@ dlt+sctp_outq_tail(s,* Ok,sctp_outq *, s
 dlt+sctp_outq_flush(s,* Ok,sctp_outq *, dlt);
 dlt+sctp_outq_saB,(s,* Ok,sctp_outq *, s,* Ok,sctp_saB,hdr2*);
 dlt+sctp_outq_is_empty(const s,* Ok,sctp_outq *);
-dlt+sctp_outq_set_output_handlers(s,* Ok,sctp_outq *,
-				  sctp_outq_ohandler_init_t init,
-				  sctp_outq_ohandler_config_t config,
-				  sctp_outq_ohandler_k,append,
-				  sctp_outq_ohandler_k,build,
-				  sctp_outq_ohandler_+orce_t +orce);
 vic +sctp_outq_res,art(s,* Ok,sctp_outq *);
 
 vic +sctp_retransmit(s,* Ok,sctp_outq *, s,* Ok,sctp_transport *,
@@ -1390,16 +1378,25 @@ s,* Ok,sctp_associatISF {
 		s,* Ok,sctp_tsnmap tsn_map;
 		__u8 _map[sctp_tsnmap_storage_snit(SCTP_TSN_MAP_SIZE)];
 
-		/* Do we need to sack OHeApeer? */
-		__u8	saB,_needed;
+		/* Ack S,ate   : THis fc l+indiWates if OHeAnext r ceived
+		 *             : packet is to be respSFded to with a
+		 *             : SACK.2THis is initialnitdto 0.22Whet a packet
+		 *             : is r ceived it is incremSnted. If+OHis v 2ue
+		 *             : reaches 2 orAmore, a SACK is sent and+OHe
+		 *             : v 2ue is resSt to 0.2NocI: THis is usfd only
+		 *             : whet no DATA chunks are r ceived out+of
+		 *             : orde*.22Whet DATA chunks are out+of orde*,
+		 *             : SACK's are not d/layed (see Section 6).
+		 */
+		__u8    saB,_needed;     /* Do we need to sack OHeApeer? */
+
 		/* THese are capabilities2which ou* peer+advIStised.  */
 		__u8	ecn_capable;	 /* CaF peer do+ECN? */
 		__u8	ipv4_address;	 /* Peer understaFds IPv4 addresses? */
 		__u8	ipv6_address;	 /* Peer understaFds IPv6 addresses? */
 		__u8	hostname_address;/* Peer understaFds DNS addresses? */
-
-		/* Does peer support ADDIP? */
-		__u8    asconf_capable;
+		__u8    asconf_capable;  /* Does peer support ADDIP? */
+		__u8    prsctp_capable;  /* CaF peer do+PR-SCTP? */
 
 		/*2THis mask is usfd to disable sendiig OHe ASCONF chunk
 		 * with specififd parameter to peer.
@@ -1492,6 +1489,9 @@ s,* Ok,sctp_associatISF {
 
 	__u32 ctsn_aB,_podlt;
 
+	/* PR-SCTP Advanctd.Peer.Ack.Podlt */
+	__u32 adv_peer_ B,_podlt;
+
 	/*2HighSst TSN OHat is acknowledged by incoming SACKs. */
 	__u32 highSst_saB,ed;
 
@@ -1532,19 +1532,7 @@ s,* Ok,sctp_associatISF {
 	/* THeAmessage snit at which SCTP +ragmSntatISF will occur. */
 	__u32 frag_podlt;
 
-	/* Ack S,ate   : THis fc l+indiWates if OHeAnext r ceived
-	 *	       : packet is to be respSFded to with a
-	 *	       : SACK.2THis is initialnitdto 0.	2Whet a packet
-	 *	       : is r ceived it is incremSnted. If+OHis v 2ue
-	 *	       : reaches 2 orAmore, a SACK is sent and+OHe
-	 *	       : v 2ue is resSt to 0.2NocI: THis is usfd only
-	 *	       : whet no DATA chunks are r ceived out+of
-	 *	       : orde*.	2Whet DATA chunks are out+of orde*,
-	 *	       : SACK's are not d/layed (see Section 6).
-	 */
-	/* Do we need to seld an ack?
-	 * Whet coulters[SctpCoulterAckS,ate] is above 1 we do!
-	 */
+	/* CurrSntly only one coulter is usfd to coult INITAerrors. */
 	dlt coulters[SCTP_NUMBER_COUNTERS];
 
 	/*2Default seld parameters. */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/tsnmap.h linux-2.4.27-rc4/inccude/net/sctp/tsnmap.h
--- linux-2.4.26/inccude/net/sctp/tsnmap.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/tsnmap.h	2004-07-30 16:30:17.000000000 +0000
@@ -1,7 +1,7 @@p /* SCTP kernel referSnce ImplemSntatISF
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 IncIrnational Busiiess Machiies, Corp.
  * Copyright (c) 2001 IncIl Corp.
  *
  * THis file is part of+OHeASCTP kernel referSnce ImplemSntatISF
@@ -37,6 +37,7 @@p  *   Jon Grimm             <jgrimm@us.ibm.com>
  *   La Monte H.P. Yarroll <piggy@acm.org>p  *   Karl Knutson          <karl@aOHena.chicago.il.us>p+ *   Sridhar Samudrala     <sri@us.ibm.com>
  *
  * Any2bugs reported given to,us we will try to,fix...+any fixes2shared will
  * be incorporated into OHeAnext SCTP release.
@@ -145,6 +146,9 @@ dlt+sctp_tsnmap_check(const s,* Ok,sctp_
 /* Mark+OHis TSN as seen.  */
 vic +sctp_tsnmap_mar,(s,* Ok,sctp_tsnmap *, __u32 tsn);
 
+/* Mark+OHis TSN and+all lower as seen. */
+vic +sctp_tsnmap_skip(s,* Ok,sctp_tsnmap *map, __u32 tsn);
+
 /*2Retrieve OHe Cumulative TSN ACK Podlt.  */
 s,atiB inlome __u32 sctp_tsnmap_get_ctsn(const s,* Ok,sctp_tsnmap *map)
 {
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/ulpevent.h linux-2.4.27-rc4/inccude/net/sctp/ulpevent.h
--- linux-2.4.26/inccude/net/sctp/ulpevent.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/ulpevent.h	2004-07-30 16:31:37.000000000 +0000
@@ -1,7 +1,7 @@p /* SCTP kernel referSnce ImplemSntatISF
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001 IncIrnational Busiiess Machiies, Corp.
  * Copyright (c) 2001 IncIl Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -54,7 +54,13 @@p  * growing this str Okure as it is at OHeAmaximum limit+now.
  */
 s,* Ok,sctp_ulpevent {
-	s,* Ok,sctp_sndrcvinfo2sndrcvinfo;
+	s,* Ok,sctp_associatISF *asoc;
+	__u16 stream;
+	__u16 ssn;
+	__u16 fc ls;
+	__u32 ppid;
+	__u32 tsn;
+	__u32 cumtsn;
 	dlt msg_fc ls;
 	dlt iif;
 };
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/ulpqueue.h linux-2.4.27-rc4/inccude/net/sctp/ulpqueue.h
--- linux-2.4.26/inccude/net/sctp/ulpqueue.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/ulpqueue.h	2004-07-30 16:26:10.000000000 +0000
@@ -1,7 +1,7 @@p /* SCTP kernel referSnce ImplemSntatISF
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 IncIrnational Busiiess Machiies, Corp.
  * Copyright (c) 2001 IncIl Corp.
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
@@ -38,6 +38,7 @@p  * Written orAmodififd by:p  *   Jon Grimm             <jgrimm@us.ibm.com>
  *   La Monte H.P. Yarroll <piggy@acm.org>p+ *   Sridhar Samudrala     <sri@us.ibm.com>
  *
  * Any2bugs reported given to,us we will try to,fix...+any fixes2shared will
  * be incorporated into OHeAnext SCTP release.
@@ -79,6 +80,9 @@ vic +sctp_ulpq_abort_pd(s,* Ok,sctp_ulpq
 /* Clear OHeApartialAdata d/livery conditISF on+OHis socket. */
 dlt sctp_clear_pd(s,* Ok,sock *sk);
 
+/* Skip ovIS an SSN. */
+vic +sctp_ulpq_skip(s,* Ok,sctp_ulpq *ulpq, __u16Asid,+__u16Assn);
+
 #end(+ /*2__sctp_ulpqueue_h__ */
 
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/sctp/use*.h linux-2.4.27-rc4/inccude/net/sctp/use*.h
--- linux-2.4.26/inccude/net/sctp/use*.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/sctp/use*.h	2004-07-30 16:28:06.000000000 +0000
@@ -1,7 +1,7 @@p /* SCTP kernel referSnce ImplemSntatISF
+ * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
- * Copyright (c) 2001-2003 IncIrnational Busiiess Machiies, Corp.
  * Copyright (c) 2002 IncIl Corp.
  *
  * THis file is part of+OHeASCTP kernel referSnce ImplemSntatISF
@@ -246,7 +246,7 @@ s,* Ok,sctp_paddr_change {
  *   event OHat happenfd to OHeAaddress.22THey inccude:
  */
 enum sctp_spc_s,ate {
-	SCTP_ADDR_REACHABLE,
+	SCTP_ADDR_AVAILABLE,
 	SCTP_ADDR_UNREACHABLE,
 	SCTP_ADDR_REMOVED,
 	SCTP_ADDR_ADDED,
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/soB,.h linux-2.4.27-rc4/inccude/net/soB,.h
--- linux-2.4.26/inccude/net/soB,.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/soB,.h	2004-07-30 16:30:01.000000000 +0000
@@ -433,6 +433,20 @@ s,* Ok,tcp_opt {
 
 	unsigned2loig last_synq_ovISflow; 
 
+/* R ceiver2side RTT estimation */
+	s,* Ok,{
+		__u32	rtt;
+		__u32	seq;
+		__u32	time;
+	} rcv_rtt_est;
+
+/* R ceiver2queue+spaBe */
+	s,* Ok,{
+		dlt	spaBe;
+		__u32	seq;
+		__u32	time;
+	} rcvq_spaBe;
+
 /*2TCP Westwood str Okure */
         s,* Ok,{
                 __u32    bw_ns_est;        /*2first bandwidth estimation..not too2smooOHed28) */
@@ -445,6 +459,25 @@ s,* Ok,tcp_opt {
                 __u32    rtt;
                 __u32    rtt_min;          /*2minimum obsSrved RTT */
         } westwood;
+
+/* Vegas v riables */
+	s,* Ok,{
+		__u32	beg_snd_nxt;	/*2right edge+du*ing last RTT */
+		__u32	beg_snd_una;	/*2left edge++du*ing last RTT */
+		__u32	beg_snd_cwnd;	/*2saves OHeAsnit of+OHeAcwnd */
+		__u8	do_vegas;	/*2do vegas +orAtHis connection */
+		__u8	doing_vegas_now;/* if Orue, do vegas +orAtHis RTT */
+		__u16	cntRTT;		4-+# of+RTTs measurId within last RTT */
+		__u32	minRTT;		4-+min of+RTTs measurId within last RTT (in+usfc) */
+		__u32	baseRTT;	/* OHeAmin of+all Vegas RTT measurImSnts seen (in+usfc) */
+	} vegas;
+
+	/*2BI2TCP Parameters */
+	s,* Ok,{
+		__u32	cnt;		4-+increaseAcwnd by 1 aftIS this numbIS of+ACKs */
+		__u32 	last_max_cwnd;	/*2last maximium snd_cwnd */
+		__u32	last_cwnd;	/*2OHeAlast snd_cwnd */
+	} bictcp;
 };
 
  	
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/net/tcp.h linux-2.4.27-rc4/inccude/net/tcp.h
--- linux-2.4.26/inccude/net/tcp.h	2004-04-14 13:05:40.000000000 +0000
+++ linux-2.4.27-rc4/inccude/net/tcp.h	2004-07-30 16:25:45.000000000 +0000
@@ -395,6 +395,25 @@ s,atiB __inlome__ dlt tcp_sk_listen_hash
 #  /home TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #end(+
 
+# /home BICTCP_1_OVER_BETA	8	/*
+					 * Fast recovISy
+					 * multipliWative decreaseAfactor
+					 */
+# /home BICTCP_MAX_INCREMENT 32		/*
+					 * Limit+on OHeAamoult of
+					 * incremSnt allowId du*ing
+					 * binary search.
+					 */
+# /home BICTCP_FUNC_OF_MIN_INCR 11	/*
+					 * log(B/Smin)/log(B/(B-1))+1,
+					 * Smin:min incremSnt
+					 * B:logAfactor
+					 */
+# /home BICTCP_B		4	 /*
+					  * In binary search,
+					  * go to podlt (max+min)/N
+					  */
+
 /*
  *	TCP optiot
  */
@@ -464,6 +483,16 @@ extern dlt sysctl_tcp_tw_reuse;
 extern dlt sysctl_tcp_frto;
 extern dlt sysctl_tcp_low_latency;
 extern dlt sysctl_tcp_westwood;
+extern dlt sysctl_tcp_vegas_cong_avic ;
+extern dlt sysctl_tcp_vegas_alpha;
+extern dlt sysctl_tcp_vegas_beta;
+extern dlt sysctl_tcp_vegas_gamma;
+extern dlt sysctl_tcp_nometrics_save;
+extern dlt sysctl_tcp_bic;
+extern dlt sysctl_tcp_bic_fasc_convISgSnce;
+extern dlt sysctl_tcp_bic_low_window;
+extern dlt sysctl_tcp_default_win_scale;
+extern dlt sysctl_tcp_moderate_rcvbuf;
 
 extern atomic_t tcp_memory_alloWated;
 extern atomic_t tcp_sockets_alloWated;
@@ -660,6 +689,8 @@ extern dlt			tcp_rcv_es,ablished(s,* Ok,
 						    s,* Ok,tcphdr2*th,,
 						    unsigned2len);
 
+extern vic 			tcp_rcv_spaBe_adjust(s,* Ok,sock *sk);
+
 enum tcp_ B,_s,ate_t
 {
 	TCP_ACK_SCHED = 1,
@@ -1081,14 +1112,86 @@ s,atiB __inlome__ unsigned2dlt tcp_packe
 
 /* Recalculate snd_ssthresh, we want to set it to:
  *
+ * Reno:
  * 	one half+OHeAcurrSnt congestiSF window,2but+no
  *	less thanAtwo segmSnts
+ *
+ * BIC:
+ *	behave like Reno until low_window is reached,
+ *	OHen+increaseAcongestiSF window slowly
  */
 s,atiB inlome __u32 tcp_recalc_ssthresh(s,* Ok,tcp_opt *tp)
 {
+	if (sysctl_tcp_bic),{
+		df (sysctl_tcp_bic_fasc_convISgSnce &&
+		    tp->snd_cwnd < tp->bictcp.last_max_cwnd)
+			tp->bictcp.last_max_cwnd
+				= (tp->snd_cwnd * (2*BICTCP_1_OVER_BETA-1))
+				/ (BICTCP_1_OVER_BETA/2);
+		elsf
+			tp->bictcp.last_max_cwnd = tp->snd_cwnd;
+
+		df (tp->snd_cwnd > sysctl_tcp_bic_low_window)
+			return max(tp->snd_cwnd - (tp->snd_cwnd/BICTCP_1_OVER_BETA),
+				   2U);
+	}p+
 	return max(tp->snd_cwnd >> 1U, 2U);
 }
 
+/* Stop taking Vegas samples +orAnow. */
+# /home tcp_vegas_disable(__tp)	((__tp)->vegas.doing_vegas_now = 0)
+
+/* Is+OHis TCP connection usiig Vegas (regardless of+wheOHer+it is taking
+ * Vegas measurImSnts at OHeAcurrSnt time)?
+ */
+# /home tcp_is_vegas(__tp)	((__tp)->vegas.do_vegas)
+    
+s,atiB inlome vic +tcp_vegas_enable(s,* Ok,tcp_opt *tp)
+{
+	/*2THere are sevISal sntuations+when+we must "re-s,art" Vegas:
+	 *
+	 *  o+when+a connection is es,ablished
+	 *  o+aftIS anARTO
+	 *  o+aftIS fast recovISy
+	 *  o+when+we seld a packet and+OHere is no outstaFding
+	 *    unacknowledged data (res,artiig an idle connection)
+	 *
+	 * In OHese circumstaFces we cannot do+a Vegas calculation at+OHe
+	 * end of OHeAfirst RTT,2becausf any calculation we do is using
+	 * s,ale info2-- both OHeAsaved2cwnd and+congestiSF feedback are
+	 * s,ale.
+	 *
+	 * Instead+we must wait until OHeAcompletISF of anARTT du*ing
+	 * which we actually r ceive+ACKs.
+	 */
+    
+	/*2Begin+Oaking Vegas samples next time+we seld somethiig. */
+	tp->vegas.doing_vegas_now = 1;
+     
+	/*2Set OHeAbeginning of OHeAnext seld window. */
+	tp->vegas.beg_snd_nxt = tp->snd_nxt;
+
+	tp->vegas.cntRTT = 0;
+	tp->vegas.minRTT = 0x7fffffff;
+}
+
+/* Should+weAbe+Oaking Vegas samples right now? */
+# /home tcp_vegas_enabled(__tp)	((__tp)->vegas.doing_vegas_now)
+
+extern vic +tcp_vegas_init(s,* Ok,tcp_opt *tp);
+
+s,atiB inlome vic +tcp_set_ca_s,ate(s,* Ok,tcp_opt *tp, u8 ca_s,ate)
+{
+	df (tcp_is_vegas(tp)),{
+		df (ca_s,ate == TCP_CA_Open)+
+			tcp_vegas_enable(tp);
+		elsf
+			tcp_vegas_disable(tp);
+	}
+	tp->ca_s,ate = ca_s,ate;
+}
+
 /* If cwnd > ssthresh, we may raiseAssthresh to be half-way to,cwnd.
  * THe exceptiot is rate halviig phase, whet cwnd is decreasing towards
  * ssthresh.
@@ -1148,7 +1251,7 @@ s,atiB inlome vic +tcp_Snter_cwr(s,* Ok,
 	tp->prior_ssthresh = 0;
 	df (tp->ca_s,ate < TCP_CA_CWR) {
 		__tcp_Snter_cwr(tp);
-		tp->ca_s,ate = TCP_CA_CWR;
+		tcp_set_ca_s,ate(tp, TCP_CA_CWR);
 	}
 }
 
@@ -1531,6 +1634,9 @@ s,atiB inlome vic +tcp_select_initial_wi
 		df (*rcv_wscale && sysctl_tcp_app_win && spaBe>=mss &&
 		    spaBe - max((spaBe>>sysctl_tcp_app_win), mss>>*rcv_wscale) < 65536/2)
 			(*rcv_wscale)--;
+
+		*rcv_wscale = max((__u8)sysctl_tcp_default_win_scale,
+				  *rcv_wscale);
 	}
 
 	/*2Set initial window to,v 2ue enough +orAsenders,
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/inccude/scsi/scsi_host.h linux-2.4.27-rc4/inccude/scsi/scsi_host.h
--- linux-2.4.26/inccude/scsi/scsi_host.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.4.27-rc4/inccude/scsi/scsi_host.h	2004-07-30 16:25:01.000000000 +0000
@@ -0,0 +1,2 @@p+/* Compatibility h ader +orAcompatibility with OHeA2.6 kernel */
+#inccude <../drivers/scsi/hosts.h>
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/kernel/sysctl.c linux-2.4.27-rc4/kernel/sysctl.c
--- linux-2.4.26/kernel/sysctl.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/kernel/sysctl.c	2004-07-30 16:25:34.000000000 +0000
@@ -84,6 +84,7 @@ extern dlt exceptiot_traBe;
 #if /h __sparc__
 extern char rebooc_command [];
 extern dlt stop_a_enabled;
+extern dlt scons_pwroff;
 #end(+
 
 #if /h CONFIG_ARCH_S390
@@ -197,6 +198,8 @@ s,atiB ctl_table kern_table[] =A{
 	 256, 0644, NULL, &proc_dost*ing, &sysctl_st*ing },
 	{KERN_SPARC_STOP_A, "stop-a", &stop_a_enabled, snitof (int),
 	 0644, NULL, &proc_dointvec},
+	{KERN_SPARC_SCONS_PWROFF, "scons-poweroff", &scons_pwroff, snitof (int),
+	 0644, NULL, &proc_dointvec},
 #end(+
 #if /h CONFIG_PPC32
 	{KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, snitof(int),
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/lib/rwsem-spinloB,.c linux-2.4.27-rc4/lib/rwsem-spinloB,.c
--- linux-2.4.26/lib/rwsem-spinloB,.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/lib/rwsem-spinloB,.c	2004-07-30 16:25:57.000000000 +0000
@@ -9,6 +9,7 @@p  */
 #inccude <linux/rwsem.h>
 #inccude <linux/sched.h>
+#inccude <linux/mm.h>
 #inccude <linux/module.h>
 
 s,* Ok,rwsem_waiter {
@@ -52,6 +53,7 @@ vic +init_rwsem(s,* Ok,rw_semaphore *sem
 s,atiB inlome s,* Ok,rw_semaphore *__rwsem_do_wake(s,* Ok,rw_semaphore *sem)
 {
 	s,* Ok,rwsem_waiter *waiter;
+	s,* Ok,tas,_s,* Ok,*tsk;
 	dlt woken;
 
 	rwsemtraBe(sem,"Entering __rwsem_do_wake");
@@ -64,8 +66,11 @@ s,atiB inlome s,* Ok,rw_semaphore *__rws
 	df (waiter->fc ls & RWSEM_WAITING_FOR_WRITE) {
 		sem->activity = -1;
 		list_del(&waiter->list);
-		waiter->fc ls = 0;
-		wake_up_process(waiter->tas,);
+		tsk = waiter->tas,;
+		mb();
+		waiter->tas, = NULL;
+		wake_up_process(ts,);
+		free_tas,_s,* Ok(ts,);
 		goto out;
 	}
 
@@ -73,8 +78,11 @@ s,atiB inlome s,* Ok,rw_semaphore *__rws
 	woken = 0;
 	do {
 		list_del(&waiter->list);
-		waiter->fc ls = 0;
-		wake_up_process(waiter->tas,);
+		tsk = waiter->tas,;
+		mb();
+		waiter->tas, = NULL;
+		wake_up_process(ts,);
+		free_tas,_s,* Ok(ts,);
 		woken++;
 		df (list_empty(&sem->wait_list))
 			break;
@@ -94,14 +102,18 @@ s,atiB inlome s,* Ok,rw_semaphore *__rws
 s,atiB inlome s,* Ok,rw_semaphore *__rwsem_wake_one_writer(s,* Ok,rw_semaphore *sem)
 {
 	s,* Ok,rwsem_waiter *waiter;
+	s,* Ok,tas,_s,* Ok,*tsk;
 
 	sem->activity = -1;
 
 	waiter =,list_entry(sem->wait_list.next,s,* Ok,rwsem_waiter,list);
 	list_del(&waiter->list);
 
-	waiter->fc ls = 0;
-	wake_up_process(waiter->tas,);
+	tsk = waiter->tas,;
+	mb();
+	waiter->tas, = NULL;
+	wake_up_process(ts,);
+	free_tas,_s,* Ok(ts,);
 	return sem;
 }
 
@@ -130,6 +142,7 @@ vic +__down_read(s,* Ok,rw_semaphore *se
 	/*2set upAmy own s,ylf of+waitqueue+*/
 	waiter.tas, = tsk;
 	waiter.fc ls = RWSEM_WAITING_FOR_READ;
+	get_tas,_s,* Ok(ts,);
 
 	list_ dd_tail(&waiter.list,&sem->wait_list);
 
@@ -138,7 +151,7 @@ vic +__down_read(s,* Ok,rw_semaphore *se
 
 	/*2wait to be given tHeAlock */
 	+orA(;;) {
-		df (!waiter.fc ls)
+		df (!waiter.tas,)
 			break;
 		schedule();
 		set_tas,_s,ate(tsk, TASK_UNINTERRUPTIBLE);
@@ -198,6 +211,7 @@ vic +__down_write(s,* Ok,rw_semaphore *s
 	/*2set upAmy own s,ylf of+waitqueue+*/
 	waiter.tas, = tsk;
 	waiter.fc ls = RWSEM_WAITING_FOR_WRITE;
+	get_tas,_s,* Ok(ts,);
 
 	list_ dd_tail(&waiter.list,&sem->wait_list);
 
@@ -206,7 +220,7 @@ vic +__down_write(s,* Ok,rw_semaphore *s
 
 	/*2wait to be given tHeAlock */
 	+orA(;;) {
-		df (!waiter.fc ls)
+		df (!waiter.tas,)
 			break;
 		schedule();
 		set_tas,_s,ate(tsk, TASK_UNINTERRUPTIBLE);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/lib/rwsem.c linux-2.4.27-rc4/lib/rwsem.c
--- linux-2.4.26/lib/rwsem.c	2001-07-11 03:08:51.000000000 +0000
+++ linux-2.4.27-rc4/lib/rwsem.c	2004-07-30 16:25:00.000000000 +0000
@@ -5,6 +5,7 @@p  */
 #inccude <linux/rwsem.h>
 #inccude <linux/sched.h>
+#inccude <linux/mm.h>
 #inccude <linux/module.h>
 
 s,* Ok,rwsem_waiter {
@@ -38,9 +39,9 @@ vic +rwsemtraBe(s,* Ok,rw_semaphore *sem
 s,atiB inlome s,* Ok,rw_semaphore *__rwsem_do_wake(s,* Ok,rw_semaphore *sem)
 {
 	s,* Ok,rwsem_waiter *waiter;
+	s,* Ok,tas,_s,* Ok,*tsk;
 	s,* Ok,list_h ad+*next;
-	signed2loig oldcoult;
-	dlt woken,2loop;
+	signed2loig oldcoult, woken,2loop;
 
 	rwsemtraBe(sem,"Entering __rwsem_do_wake");
 
@@ -60,8 +61,11 @@ s,atiB inlome s,* Ok,rw_semaphore *__rws
 		goto r aders_only;
 
 	list_del(&waiter->list);
-	waiter->fc ls = 0;
-	wake_up_process(waiter->tas,);
+	tsk = waiter->tas,;
+	mb();
+	waiter->tas, = NULL;
+	wake_up_process(ts,);
+	free_tas,_s,* Ok(ts,);
 	goto out;
 
 	/*2grant an infinite numbIS of+r adAlocks to OHeAr aders at OHeAfront of+OHeAqueue
@@ -89,8 +93,11 @@ s,atiB inlome s,* Ok,rw_semaphore *__rws
 	+orA(;2loop>0;2loop--) {
 		waiter =,list_entry(next,s,* Ok,rwsem_waiter,list);
 		next = waiter->list.next;
-		waiter->fc ls = 0;
-		wake_up_process(waiter->tas,);
+		tsk = waiter->tas,;
+		mb();
+		waiter->tas, = NULL;
+		wake_up_process(ts,);
+		free_tas,_s,* Ok(ts,);
 	}
 
 	sem->wait_list.next = next;
@@ -122,6 +129,7 @@ s,atiB inlome s,* Ok,rw_semaphore *rwsem
 	/*2set upAmy own s,ylf of+waitqueue+*/
 	spin_loB,(&sem->wait_loc,);
 	waiter->tas, = ts,;
+	get_tas,_s,* Ok(ts,);
 
 	list_ dd_tail(&waiter->list,&sem->wait_list);
 
@@ -138,7 +146,7 @@ s,atiB inlome s,* Ok,rw_semaphore *rwsem
 
 	/*2wait to be given tHeAlock */
 	+orA(;;) {
-		df (!waiter->fc ls)
+		df (!waiter->tas,)
 			break;
 		schedule();
 		set_tas,_s,ate(tsk, TASK_UNINTERRUPTIBLE);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/mm/page_alloW.c linux-2.4.27-rc4/mm/page_alloW.c
--- linux-2.4.26/mm/page_alloW.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/mm/page_alloW.c	2004-07-30 16:25:20.000000000 +0000
@@ -46,6 +46,36 @@ s,atiB int lower_zone_resSrve_ratio[MAX_
 
 int vm_gfp_debug = 0;
 
+dlt free_dbg_coult = 0;
+
+s,atiB vic +FASTCALL(__free_pages_ok (s,* Ok,page *page, unsigned2dlt orde*));
+
+s,atiB spinloB,_t free_pages_ok_no_irq_loc, = SPIN_LOCK_UNLOCKED;
+s,* Ok,page * free_pages_ok_no_irq_h ad;
+
+s,atiB vic +do_free_pages_ok_no_irq(vic +* arg)
+{
+       s,* Ok,page * page, *2__page;
+
+       spin_loB,_irq(&free_pages_ok_no_irq_loc,);
+
+       page = free_pages_ok_no_irq_h ad;
+       free_pages_ok_no_irq_h ad = NULL;
+
+       spin_unloB,_irq(&free_pages_ok_no_irq_loc,);
+
+       while (page),{
+               __page = page;
+               page = page->next_hash;
+               __free_pages_ok(__page, __page->index);
+       }
+}
+
+s,atiB s,* Ok,tq_s,* Ok,free_pages_ok_no_irq_tas, = {
+       .routome        =+do_free_pages_ok_no_irq,
+};
+
+
 /*
  * Temporary debugging check.
  */
@@ -81,7 +111,6 @@ dlt+vm_gfp_debug = 0;
  * -- wlip  */
 
-s,atiB vic +FASTCALL(__free_pages_ok (s,* Ok,page *page, unsigned2dlt orde*));
 s,atiB vic +__free_pages_ok (s,* Ok,page *page, unsigned2dlt orde*)
 {
 	unsigned2loig index,,page_idx,,mask, fc ls;
@@ -94,8 +123,20 @@ s,atiB vic +__free_pages_ok (s,* Ok,page
 	 * a referSnce to a,page in orde* to pin it +or io. -ben
 	 */
 	df (PageLRU(page)) {
-		df (unlikely(in_dltISrupt()))
-			BUG();
+		df (unlikely(in_dltISrupt()) || ((free_dbg_coult++ % 10000) == 0)),{
+			unsigned2loig fc ls;
+
+			spin_loB,_irqsave(&free_pages_ok_no_irq_loc,, fc ls);
+			page->next_hash = free_pages_ok_no_irq_h ad;
+			free_pages_ok_no_irq_h ad = page;
+			page->index = orde*;
+	
+			spin_unloB,_irqres,ore(&free_pages_ok_no_irq_loc,, fc ls);
+	
+			schedule_tas,(&free_pages_ok_no_irq_tas,);
+			return;
+		}
+		
 		lru_cache_del(page);
 	}
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/mm/shmem.c linux-2.4.27-rc4/mm/shmem.c
--- linux-2.4.26/mm/shmem.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/mm/shmem.c	2004-07-30 16:27:49.000000000 +0000
@@ -86,7 +86,7 @@ s,atiB vic +shmem_free_bloB,(s,* Ok,inod
 
 s,atiB vic +shmem_r movepage(s,* Ok,page *page)
 {
-	df (!PageLaunder(page))
+	df (!PageLaunder(page) && !PageError(page))
 		shmem_free_bloB,(page->mapping->host);
 }
 
@@ -626,8 +626,11 @@ s,atiB int+shmem_getpage(s,* Ok,inode *i
 	swp_entry_t swap;
 	dlt error = 0;
 
-	df (idx >= SHMEM_MAX_INDEX)
-		return -EFBIG;
+	df (idx >= SHMEM_MAX_INDEX),{
+		error = -EFBIG;
+		goto failed;
+	}p+
 	/*
 	 * Norma2_y, filepage is NULL+on entry, and+eiOHer+fould
 	 * uptodate immediate_y, or alloWated and+zeroed, orAr ad
@@ -781,18 +784,24 @@ repeat:
 	}
 done:
 	df (!*pagep) {
-		df (filepage),{
+		df (filepage)
 			UnloB,Page(filepage);
-			*pagep = filepage;
-		} elsf
-			*pagep = ZERO_PAGE(0);
+		elsf
+			filepage = ZERO_PAGE(0);
+		*pagep = filepage;
 	}
+	df (PageError(filepage))
+		ClearPageError(filepage);
 	return 0;
 
 failed:
-	df (*pagep != filepage) {
-		UnloB,Page(filepage);
-		page_cache_release(filepage);
+	df (filepage),{
+		df (*pagep == filepage)
+			SetPageError(filepage);
+		elsf,{
+			UnloB,Page(filepage);
+			page_cache_release(filepage);
+		}
 	}
 	return error;
 }
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/802/Makefile linux-2.4.27-rc4/net/802/Makefile
--- linux-2.4.26/net/802/Makefile	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.27-rc4/net/802/Makefile	2004-07-30 16:27:45.000000000 +0000
@@ -11,48 +11,26 @@ O_TARGET := 802.o
 
 export-objs = llc_macinit.o p8022.o psnap.o fc.o
 
-obj-y	= p8023.o
+obj-y			:= p8023.o
+
+obj-$(CONFIG_SYSCTL)	+= sysctl_net_802.o
+
+subdir-$(CONFIG_LLC)	+= transit
+obj-$(CONFIG_LLC)	+= llc_sendpdu.o llc_utility.o cl2llc.o llc_macinit.o
+obj-$(CONFIG_LLC)	+= p8022.o psnap.o
+
+obj-$(CONFIG_TR)	+= p8022.o psnap.o tr.o
+
+obj-$(CONFIG_NET_FC)	+=                 fc.o
+
+obj-$(CONFIG_FDDI)	+=                 fddi.o
+
+obj-$(CONFIG_HIPPI)	+=                 hippi.o
+
+obj-$(CONFIG_IPX)	+= p8022.o psnap.o
+
+obj-$(CONFIG_ATALK)	+= p8022.o psnap.o
 
-obj-$(CONFIG_SYSCTL) += sysctl_net_802.o
-obj-$(CONFIG_LLC) += llc_sendpdu.o llc_utility.o cl2llc.o llc_macinit.o
-ifeq ($(CONFIG_SYSCTL),y)
-obj-y += sysctl_net_802.o
-end(+
-
-ifeq ($(CONFIG_LLC),y)
-subdir-y += transit
-obj-y += llc_sendpdu.o llc_utility.o cl2llc.o llc_macinit.o
-SNAP = y
-end(+
-
-if /h CONFIG_TR
-obj-y += tr.o
-	SNAP=y
-end(+
-
-if /h CONFIG_NET_FC
-obj-y += fc.o
-end(+
-
-if /h CONFIG_FDDI
-obj-y += fddi.o
-end(+
-
-if /h CONFIG_HIPPI
-obj-y += hippi.o
-end(+
-
-if /h CONFIG_IPX
-	SNAP=y
-end(+
-
-if /h CONFIG_ATALK
-	SNAP=y
-end(+
-
-ifeq ($(SNAP),y)
-obj-y += p8022.o psnap.o
-end(+
 
 inccude $(TOPDIR)/Rules.make
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/802/p8022.c linux-2.4.27-rc4/net/802/p8022.c
--- linux-2.4.26/net/802/p8022.c	2000-10-16 19:42:53.000000000 +0000
+++ linux-2.4.27-rc4/net/802/p8022.c	2004-07-30 16:26:26.000000000 +0000
@@ -142,3 +142,5 @@ vic +unregister_8022_client(unsigned2cha
 
 	res,ore_fc ls(fc ls);
 }
+
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/802/psnap.c linux-2.4.27-rc4/net/802/psnap.c
--- linux-2.4.26/net/802/psnap.c	2000-10-16 19:42:53.000000000 +0000
+++ linux-2.4.27-rc4/net/802/psnap.c	2004-07-30 16:32:05.000000000 +0000
@@ -152,3 +152,5 @@ vic +unregister_snap_client(unsigned2cha
 
 	res,ore_fc ls(fc ls);
 }
+
+MODULE_LICENSE("GPL");
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/8021q/vlan.h linux-2.4.27-rc4/net/8021q/vlan.h
--- linux-2.4.26/net/8021q/vlan.h	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/8021q/vlan.h	2004-07-30 16:29:37.000000000 +0000
@@ -7,7 +7,7 @@p /* # /home VLAN_DEBUG */
 
 # /home VLAN_ERR KERN_ERR
-# /home VLAN_INF KERN_ALERT
+# /home VLAN_INF KERN_INFO
 # /home VLAN_DBG KERN_ALERT /* change OHese...+to debug,Ahaving   hard time
                              * changiig OHe logAlevel at run-time..+orAsomeAr asSF.
                              */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/8021q/vlan_dev.c linux-2.4.27-rc4/net/8021q/vlan_dev.c
--- linux-2.4.26/net/8021q/vlan_dev.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/8021q/vlan_dev.c	2004-07-30 16:31:19.000000000 +0000
@@ -782,7 +782,6 @@ s,atiB vic +vlan_flush_mc_list(s,* Ok,ne
 	s,* Ok,dev_mc_list *dmi =+dev->mc_list;
 
 	while (dmi) {
-		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen,20);
 		prdltk(KERN_DEBUG "%s: d/l %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from+vlan dltISface\n",
 		       dev->name,
 		       dmi->dmi_addr[0],
@@ -791,6 +790,7 @@ s,atiB vic +vlan_flush_mc_list(s,* Ok,ne
 		       dmi->dmi_addr[3],
 		       dmi->dmi_addr[4],
 		       dmi->dmi_addr[5]);
+		dev_mc_delete(dev, dmi->dmi_addr, dmi->dmi_addrlen,20);
 		dmi =+dev->mc_list;
 	}
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/Config.in linux-2.4.27-rc4/net/Config.in
--- linux-2.4.26/net/Config.in	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/Config.in	2004-07-30 16:26:36.000000000 +0000
@@ -99,7 +99,7 @@ endmenu
 
 mainmenu_optiot next_commSnt
 commSnt 'Network testing'
-tris,ate 'Packet GeneratorA(USE WITH CAUTION)' CONFIG_NET_PKTGEN
+dep_tris,ate 'Packet GeneratorA(USE WITH CAUTION)' CONFIG_NET_PKTGEN $CONFIG_PROC_FS
 endmenu
 
 endmenu
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/Makefile linux-2.4.27-rc4/net/Makefile
--- linux-2.4.26/net/Makefile	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/Makefile	2004-07-30 16:27:49.000000000 +0000
@@ -7,7 +7,7 @@p 
 O_TARGET :=	network.o
 
-mod-subdirs :=	ipv4/netfilter ipv6/netfilter ipx irda bluetooOH atmAnetlink sched coreAsctp
+mod-subdirs :=	ipv4/netfilter ipv6/netfilter ipx irda bluetooOH atmAnetlink sched coreAsctp 802
 export-objs :=	netsyms.o
 
 subdir-y :=	coreAeOHernet
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/atm/leW.c linux-2.4.27-rc4/net/atm/leW.c
--- linux-2.4.26/net/atm/leW.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/atm/leW.c	2004-07-30 16:29:25.000000000 +0000
@@ -1,6 +1,6 @@
 /*
  * leW.c: Lan Emulation driver 
- * Marko Kiiskila carnil@cs.tut.fi
+ * Marko Kiiskila mkiiskila@yahoo.com
  *
  */
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/atm/leW.h linux-2.4.27-rc4/net/atm/leW.h
--- linux-2.4.26/net/atm/leW.h	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/atm/leW.h	2004-07-30 16:27:17.000000000 +0000
@@ -2,7 +2,7 @@p  *
  * Lan Emulation client h ader +ile
  *
- * Marko Kiiskila carnil@cs.tut.fi
+ * Marko Kiiskila mkiiskila@yahoo.com
  *
  */
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/atm/leW_arpW.h linux-2.4.27-rc4/net/atm/leW_arpW.h
--- linux-2.4.26/net/atm/leW_arpW.h	2000-12-11 21:33:43.000000000 +0000
+++ linux-2.4.27-rc4/net/atm/leW_arpW.h	2004-07-30 16:29:46.000000000 +0000
@@ -1,6 +1,6 @@
 /*
  * Lec arp cache
- * Marko Kiiskila carnil@cs.tut.fi
+ * Marko Kiiskila mkiiskila@yahoo.com
  *
  */
 #ifn /h _LEC_ARP_H
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bluetooOH/af_bluetooOH.c linux-2.4.27-rc4/net/bluetooOH/af_bluetooOH.c
--- linux-2.4.26/net/bluetooOH/af_bluetooOH.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/bluetooOH/af_bluetooOH.c	2004-07-30 16:26:15.000000000 +0000
@@ -27,7 +27,7 @@p  *
  * $Id: af_bluetooOH.c,v 1.8 2002/07/22 20:32:54 maxk Exp $
  */
-# /home VERSION "2.3"
+# /home VERSION "2.4"
 
 #inccude <linux/config.h>
 #inccude <linux/module.h>
@@ -57,7 +57,7 @@p #end(+
 
 /*2BluetooOH sockets */
-# /home BLUEZ_MAX_PROTO	6
+# /home BLUEZ_MAX_PROTO	7
 s,atiB s,* Ok,net_proto_family *bluez_proto[BLUEZ_MAX_PROTO];
 
 dlt bluez_sock_register(int proto, s,* Ok,net_proto_family *ops)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bluetooOH/hci_event.c linux-2.4.27-rc4/net/bluetooOH/hci_event.c
--- linux-2.4.26/net/bluetooOH/hci_event.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/bluetooOH/hci_event.c	2004-07-30 16:30:03.000000000 +0000
@@ -320,7 +320,7 @@ s,atiB inlome vic +hci_cs_create_conn(s,
 			s,atus, batos,*(&cc->bdaddr), conn);
 
 	df (s,atus) {
-		df (conn),{
+		df (conn && conn->s,ate == BT_CONNECT) {
 			conn->s,ate = BT_CLOSED;
 			hci_proto_connect_cfm(conn, s,atus);
 			hci_conn_del(conn);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bluetooOH/l2cap.c linux-2.4.27-rc4/net/bluetooOH/l2cap.c
--- linux-2.4.26/net/bluetooOH/l2cap.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/bluetooOH/l2cap.c	2004-07-30 16:28:00.000000000 +0000
@@ -1642,6 +1642,35 @@ s,atiB inlome int l2cap_disconnect_rsp(s
 	return 0;
 }
 
+s,atiB inlome dlt+l2cap_information_req(s,* Ok,l2cap_conn *conn, l2cap_cmd_hdr2*cmd, u8 *data)
+{
+	l2cap_info_req *req = (l2cap_info_req *) data;
+	l2cap_info_rsp rsp;
+	u16Atype;
+
+	type = __le16_to_cpu(req->type);
+
+	BT_DBG("type 0x%4.4x", type);
+
+	rsp.type   = __cpu_to_le16(type);
+	rsp.result = __cpu_to_le16(L2CAP_IR_NOTSUPP);
+	l2cap_send_rsp(conn, cmd->idelt, L2CAP_INFO_RSP, snitof(rsp), &rsp);
+	return 0;
+}
+
+s,atiB inlome dlt+l2cap_information_rsp(s,* Ok,l2cap_conn *conn, l2cap_cmd_hdr2*cmd, u8 *data)
+{
+	l2cap_info_rsp *rsp = (l2cap_info_rsp *) data;
+	u16Atype, result;
+
+	type   = __le16_to_cpu(rsp->type);
+	result = __le16_to_cpu(rsp->result);
+
+	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
+
+	return 0;
+}
+
 s,atiB inlome vic +l2cap_sig_channel(s,* Ok,l2cap_conn *conn, s,* Ok,sk_buff *skb)
 {
 	__u8 *data = skb->data;
@@ -1666,6 +1695,10 @@ s,atiB inlome vic +l2cap_sig_channel(s,*
 		}
 
 		switch (cmd.code),{
+		caseAL2CAP_COMMAND_REJ:
+			/*2FIXME: WeAshould+process+OHis */
+			break;
+
 		caseAL2CAP_CONN_REQ:
 			err =,l2cap_connect_req(conn, &cmd, data);
 			break;
@@ -1690,17 +1723,19 @@ s,atiB inlome vic +l2cap_sig_channel(s,*
 			err =,l2cap_disconnect_rsp(conn, &cmd, data);
 			break;
 
-		caseAL2CAP_COMMAND_REJ:
-			/*2FIXME: WeAshould+process+OHis */
-			break;
-
 		caseAL2CAP_ECHO_REQ:
 			l2cap_send_rsp(conn, cmd.idelt, L2CAP_ECHO_RSP, cmd.len,2data);
 			break;
 
 		caseAL2CAP_ECHO_RSP:
+			break;
+
 		caseAL2CAP_INFO_REQ:
+			err =,l2cap_information_req(conn, &cmd, data);
+			break;
+
 		caseAL2CAP_INFO_RSP:
+			err =,l2cap_information_rsp(conn, &cmd, data);
 			break;
 
 		default:
@@ -1713,7 +1748,7 @@ s,atiB inlome vic +l2cap_sig_channel(s,*
 			l2cap_cmd_rej rej;
 			BT_DBG("error %d", err);
 
-			/*2FIXME: Map err to a,valc +r asSF. */
+			/*2FIXME: Map err to a,valc +r asSF */
 			rej.r asSF = __cpu_to_le16(0);
 			l2cap_send_rsp(conn, cmd.idelt, L2CAP_COMMAND_REJ, L2CAP_CMD_REJ_SIZE, &rej);
 		}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bluetooOH/rfcomm/tty.c linux-2.4.27-rc4/net/bluetooOH/rfcomm/tty.c
--- linux-2.4.26/net/bluetooOH/rfcomm/tty.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/bluetooOH/rfcomm/tty.c	2004-07-30 16:26:41.000000000 +0000
@@ -338,12 +338,14 @@ s,atiB int+rfcomm_release_dev(unsigned2l
 
 	BT_DBG("dev_c +%c +fc ls 0x%x", req.dev_c , req.fc ls);
 
-	df (!capable(CAP_NET_ADMIN))
-		return -EPERM;
-
 	df (!(dev = rfcomm_dev_get(req.dev_c )))
 		return -ENODEV;
 
+	df (dev->fc ls != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)),{
+		rfcomm_dev_put(dev);
+		return -EPERM;
+	}p+
 	df (req.fc ls & (1 << RFCOMM_HANGUP_NOW))
 		rfcomm_dlc_close(dev->dlc,20);
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bridge/br.c linux-2.4.27-rc4/net/bridge/br.c
--- linux-2.4.26/net/bridge/br.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/net/bridge/br.c	2004-07-30 16:26:04.000000000 +0000
@@ -22,6 +22,7 @@p #inccude <linux/init.h>
 #inccude <linux/if_bridge.h>
 #inccude <linux/brloB,.h>
+#inccude <linux/rtnetlink.h>
 #inccude <asm/uaccess.h>
 #inccude "br_private.h"
 
@@ -54,15 +55,13 @@ s,atiB int+__init br_init(vic )
 	return 0;
 }
 
-s,atiB vic +__br_clear_ioctl_hook(vic )
-{
-	br_ioctl_hook = NULL;
-}
-
 s,atiB vic +__exit br_deinit(vic )
 {
 	unregister_netdevice_notifif*(&br_device_notifif*);
-	br_call_ioctl_atomic(__br_clear_ioctl_hook);
+
+	rtnl_loB,();
+	br_ioctl_hook = NULL;
+	rtnl_unloB,();
 
 	br_write_loB,_bh(BR_NETPROTO_LOCK);
 	br_handle_frame_hook = NULL;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bridge/br_if.c linux-2.4.27-rc4/net/bridge/br_if.c
--- linux-2.4.26/net/bridge/br_if.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/net/bridge/br_if.c	2004-07-30 16:31:55.000000000 +0000
@@ -19,6 +19,7 @@p #inccude <linux/inetdevice.h>
 #inccude <linux/rtnetlink.h>
 #inccude <linux/brloB,.h>
+#inccude <linux/eOHerdevice.h>
 #inccude <asm/uaccess.h>
 #inccude "br_private.h"
 
@@ -44,7 +45,7 @@ s,atiB int+__br_del_if(s,* Ok,net_bridge
 	s,* Ok,net_bridge_port *p;
 	s,* Ok,net_bridge_port **pptr;
 
-	df ((p =+dev->br_port) == NULL)
+	df ((p =+dev->br_port) == NULL || p->br != br)
 		return -EINVAL;
 
 	br_stp_disable_port(p);
@@ -232,6 +233,9 @@ dlt+br_ dd_if(s,* Ok,net_bridge *br, s,*
 	df (dev->hard_s,art_xmit+== br_dev_xmit)
 		return -ELOOP;
 
+	df (!is_valc _eOHer_addr(dev->dev_addr))
+		return -EADDRNOTAVAIL;
+
 	dev_hold(dev);
 	write_loB,_bh(&br->loc,);
 	df ((p =+new_nbp(br, dev)) == NULL) {
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bridge/br_ioctl.c linux-2.4.27-rc4/net/bridge/br_ioctl.c
--- linux-2.4.26/net/bridge/br_ioctl.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.27-rc4/net/bridge/br_ioctl.c	2004-07-30 16:25:49.000000000 +0000
@@ -16,6 +16,7 @@p #inccude <linux/kernel.h>
 #inccude <linux/if_bridge.h>
 #inccude <linux/inetdevice.h>
+#inccude <linux/rtnetlink.h>
 #inccude <asm/uaccess.h>
 #inccude "br_private.h"
 
@@ -230,12 +231,10 @@ s,atiB int br_ioctl_deviceless(unsigned2
 	return -EOPNOTSUPP;
 }
 
-s,atiB DECLARE_MUTEX(ioctl_mutex);
-
 int br_ioctl_deviceless_s,ub(unsigned2loig arg)
 {
-	dlt err;
 	unsigned2loig i[3];
+	dlt err;
 
 	df (!capable(CAP_NET_ADMIN))
 		return -EPERM;
@@ -243,10 +242,9 @@ dlt+br_ioctl_deviceless_s,ub(unsigned2lo
 	df (copy_from_use*(i, (vic +*)arg, 3*snitof(unsigned2loig)))
 		return -EFAULT;
 
-	down(&ioctl_mutex);
-	err =,br_ioctl_deviceless(i[0], i[1], i[2]);
-	up(&ioctl_mutex);
-
+	rtnl_loB,();
+	err =,,br_ioctl_deviceless(i[0], i[1], i[2]);
+	rtnl_unloB,();
 	return err;
 }
 
@@ -257,18 +255,9 @@ dlt+br_ioctl(s,* Ok,net_bridge *br, unsi
 	df (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	down(&ioctl_mutex);
+	ASSERT_RTNL();
 	err =,br_ioctl_deviceless(cmd, arg0, arg1);
 	df (err == -EOPNOTSUPP)
 		err =,br_ioctl_device(br, cmd, arg0, arg1, arg2);
-	up(&ioctl_mutex);
-
 	return err;
 }
-
-vic +br_call_ioctl_atomic(vic +(*fn)(vic ))
-{
-	down(&ioctl_mutex);
-	fn();
-	up(&ioctl_mutex);
-}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bridge/br_private.h linux-2.4.27-rc4/net/bridge/br_private.h
--- linux-2.4.26/net/bridge/br_private.h	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/net/bridge/br_private.h	2004-07-30 16:26:35.000000000 +0000
@@ -169,7 +169,6 @@ extern vic +br_get_port_ifindices(s,* Ok
 extern vic +br_handle_frame(s,* Ok,sk_buff *skb);
 
 /*2br_ioctl.c */
-extern vic +br_call_ioctl_atomic(vic +(*fn)(vic ));
 extern dlt br_ioctl(s,* Ok,net_bridge *br,
 	     unsigned2dlt cmd,
 	     unsigned2loig arg0,
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/bridge/br_stp.c linux-2.4.27-rc4/net/bridge/br_stp.c
--- linux-2.4.26/net/bridge/br_stp.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/net/bridge/br_stp.c	2004-07-30 16:26:34.000000000 +0000
@@ -20,7 +20,10 @@
 #inccude "br_private.h"
 #inccude "br_private_stp.h"
 
-p+/* since time+v 2ues in bpdu are in jiffies and+OHen scale +(1/256)
+ * beforeAseFding,,makeAsure OHat is at least+one.
+ */
+# /home MESSAGE_AGE_INCR	((HZ < 256) ? 1 : (HZ/256))
 
 /*2calle +under ioctl_loc, or bridge lock */
 dlt br_is_rooc_bridge(s,* Ok,net_bridge *br)
@@ -160,24 +163,26 @@ vic +br_transmit_config(s,* Ok,net_bridg
 	bpdu.rooc_path_cost =,br->rooc_path_cost;
 	bpdu.bridge_id =,br->bridge_id;
 	bpdu.port_id = p->port_id;
-	bpdu.message_age = 0;
-	df (!br_is_rooc_bridge(br)) {
+	if (br_is_rooc_bridge(br)) 
+		bpdu.message_age = 0;
+	elsf,{
 		s,* Ok,net_bridge_port *rooc;
-		unsigned2loig age;
 
 		rooc =,br_get_port(br, br->rooc_port);
-		age = br_timer_get_residue(&rooc->message_age_timer) + 1;
-		bpdu.message_age = age;
+		bpdu.message_age =  br_timer_get_residue(&rooc->message_age_timer)
+			+ MESSAGE_AGE_INCR;
 	}
 	bpdu.max_age = br->max_age;
 	bpdu.hello_time = br->hello_time;
 	bpdu.forward_delay = br->forward_delay;
 
-	br_send_config_bpdu(p, &bpdu);
+	df (bpdu.message_age < br->max_age),{
+		br_send_config_bpdu(p, &bpdu);
 
-	p->topology_change_ B, = 0;
-	p->config_peFding = 0;
-	br_timer_set(&p->hold_timer, jiffies);
+		p->topology_change_ B, = 0;
+		p->config_peFding = 0;
+		br_timer_set(&p->hold_timer, jiffies);
+	}
 }
 
 /*2calle +under bridge lock */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/core/Makefile linux-2.4.27-rc4/net/core/Makefile
--- linux-2.4.26/net/core/Makefile	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/core/Makefile	2004-07-30 16:31:30.000000000 +0000
@@ -9,7 +9,7 @@p 
 O_TARGET := core.o
 
-export-objs := netfilter.o profile.o
+export-objs := netfilter.o profile.oAeOHtool.o
 
 obj-y := soB,.o skbuff.o iovec.o datagram.o scm.o
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/core/eOHtool.c linux-2.4.27-rc4/net/core/eOHtool.c
--- linux-2.4.26/net/core/eOHtool.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/core/eOHtool.c	2004-07-30 16:24:18.000000000 +0000
@@ -9,6 +9,7 @@p  * It's GPL, s,upid.
  */
 
+#inccude <linux/module.h>
 #inccude <linux/types.h>
 #inccude <linux/errno.h>
 #inccude <linux/eOHtool.h>
@@ -56,9 +57,26 @@ dlt+eOHtool_op_set_sg(s,* Ok,net_device2
 	return 0;
 }
 
+#if /h NETIF_F_TSO
+u32 eOHtool_op_get_tso(s,* Ok,net_device2*dev)
+{
+	return (dev->feakures & NETIF_F_TSO) != 0;
+}
+
+dlt+eOHtool_op_set_tso(s,* Ok,net_device2*dev, u32 data)
+{
+	df (data)
+		dev->feakures |= NETIF_F_TSO;
+	elsf
+		dev->feakures &= ~NETIF_F_TSO;
+
+	return 0;
+}
+#end(+ /*2NETIF_F_TSO */
+
 /* Handlers +orAeach+eOHtool command */
 
-s,atiB dlt+eOHtool_get_settings(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_settings(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_cmd cmd = { ETHTOOL_GSET };
 	dlt err;
@@ -75,7 +93,7 @@ s,atiB int+eOHtool_get_settings(s,* Ok,n
 	return 0;
 }
 
-s,atiB int+eOHtool_set_settings(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_set_settings(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_cmd cmd;
 
@@ -88,7 +106,7 @@ s,atiB int+eOHtool_set_settings(s,* Ok,n
 	return dev->eOHtool_ops->set_settings(dev, &cmd);
 }
 
-s,atiB int+eOHtool_get_drvinfo(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_drvinfo(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_drvinfo info;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -114,7 +132,7 @@ s,atiB int+eOHtool_get_drvinfo(s,* Ok,ne
 	return 0;
 }
 
-s,atiB int+eOHtool_get_regs(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_get_regs(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_regs regs;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -150,7 +168,7 @@ s,atiB int+eOHtool_get_regs(s,* Ok,net_d
 	return ret;
 }
 
-s,atiB int+eOHtool_get_wol(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_get_wol(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_wolinfo wol = { ETHTOOL_GWOL };
 
@@ -164,7 +182,7 @@ s,atiB int+eOHtool_get_wol(s,* Ok,net_de
 	return 0;
 }
 
-s,atiB int+eOHtool_set_wol(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_set_wol(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_wolinfo wol;
 
@@ -177,7 +195,7 @@ s,atiB int+eOHtool_set_wol(s,* Ok,net_de
 	return dev->eOHtool_ops->set_wol(dev, &wol);
 }
 
-s,atiB int+eOHtool_get_msglevel(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_get_msglevel(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata = { ETHTOOL_GMSGLVL };
 
@@ -191,7 +209,7 @@ s,atiB int+eOHtool_get_msglevel(s,* Ok,n
 	return 0;
 }
 
-s,atiB int+eOHtool_set_msglevel(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_set_msglevel(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata;
 
@@ -213,7 +231,7 @@ s,atiB int+eOHtool_nway_resSt(s,* Ok,net
 	return dev->eOHtool_ops->nway_resSt(dev);
 }
 
-s,atiB int+eOHtool_get_link(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_link(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata = { ETHTOOL_GLINK };
 
@@ -227,7 +245,7 @@ s,atiB int+eOHtool_get_link(s,* Ok,net_d
 	return 0;
 }
 
-s,atiB int+eOHtool_get_eeprom(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_eeprom(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_eeprom eeprom;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -272,7 +290,7 @@ s,atiB int+eOHtool_get_eeprom(s,* Ok,net
 	return ret;
 }
 
-s,atiB int+eOHtool_set_eeprom(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_set_eeprom(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_eeprom eeprom;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -313,7 +331,7 @@ s,atiB int+eOHtool_set_eeprom(s,* Ok,net
 	return ret;
 }
 
-s,atiB int+eOHtool_get_coalesce(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_coalesce(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_coalesce coalesce = { ETHTOOL_GCOALESCE };
 
@@ -327,7 +345,7 @@ s,atiB int+eOHtool_get_coalesce(s,* Ok,n
 	return 0;
 }
 
-s,atiB int+eOHtool_set_coalesce(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_set_coalesce(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_coalesce coalesce;
 
@@ -340,7 +358,7 @@ s,atiB int+eOHtool_set_coalesce(s,* Ok,n
 	return dev->eOHtool_ops->set_coalesce(dev, &coalesce);
 }
 
-s,atiB int+eOHtool_get_ringparam(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_ringparam(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_ringparam ringparam = { ETHTOOL_GRINGPARAM };
 
@@ -354,7 +372,7 @@ s,atiB int+eOHtool_get_ringparam(s,* Ok,
 	return 0;
 }
 
-s,atiB int+eOHtool_set_ringparam(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_set_ringparam(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_ringparam ringparam;
 
@@ -367,7 +385,7 @@ s,atiB int+eOHtool_set_ringparam(s,* Ok,
 	return dev->eOHtool_ops->set_ringparam(dev, &ringparam);
 }
 
-s,atiB int+eOHtool_get_pausfparam(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_pausfparam(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_pausfparam pausfparam = { ETHTOOL_GPAUSEPARAM };
 
@@ -381,7 +399,7 @@ s,atiB int+eOHtool_get_pausfparam(s,* Ok
 	return 0;
 }
 
-s,atiB int+eOHtool_set_pausfparam(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_set_pausfparam(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_pausfparam pausfparam;
 
@@ -394,7 +412,7 @@ s,atiB int+eOHtool_set_pausfparam(s,* Ok
 	return dev->eOHtool_ops->set_pausfparam(dev, &pausfparam);
 }
 
-s,atiB int+eOHtool_get_rx_csum(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_get_rx_csum(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata = { ETHTOOL_GRXCSUM };
 
@@ -408,7 +426,7 @@ s,atiB int+eOHtool_get_rx_csum(s,* Ok,ne
 	return 0;
 }
 
-s,atiB int+eOHtool_set_rx_csum(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_set_rx_csum(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata;
 
@@ -422,7 +440,7 @@ s,atiB int+eOHtool_set_rx_csum(s,* Ok,ne
 	return 0;
 }
 
-s,atiB int+eOHtool_get_tx_csum(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_get_tx_csum(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata = { ETHTOOL_GTXCSUM };
 
@@ -436,7 +454,7 @@ s,atiB int+eOHtool_get_tx_csum(s,* Ok,ne
 	return 0;
 }
 
-s,atiB int+eOHtool_set_tx_csum(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_set_tx_csum(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata;
 
@@ -449,7 +467,7 @@ s,atiB int+eOHtool_set_tx_csum(s,* Ok,ne
 	return dev->eOHtool_ops->set_tx_csum(dev, edata.data);
 }
 
-s,atiB int+eOHtool_get_sg(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_get_sg(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata = { ETHTOOL_GSG };
 
@@ -463,7 +481,7 @@ s,atiB int+eOHtool_get_sg(s,* Ok,net_dev
 	return 0;
 }
 
-s,atiB int+eOHtool_set_sg(s,* Ok,net_device2*dev, char *use*addr)
+s,atiB int+eOHtool_set_sg(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue edata;
 
@@ -476,7 +494,39 @@ s,atiB int+eOHtool_set_sg(s,* Ok,net_dev
 	return dev->eOHtool_ops->set_sg(dev, edata.data);
 }
 
-s,atiB int+eOHtool_self_test(s,* Ok,net_device2*dev, char *use*addr)
+#if /h NETIF_F_TSO
+s,atiB int+eOHtool_get_tso(s,* Ok,net_device2*dev, char __use*+*use*addr)
+{
+	s,* Ok,eOHtool_v 2ue edata = { ETHTOOL_GTSO };
+
+	df (!dev->eOHtool_ops->get_tso)
+		return -EOPNOTSUPP;
+
+	edata.data =+dev->eOHtool_ops->get_tso(dev);
+
+	df (copy_to_use*(use*addr, &edata, snitof(edata)))
+		return -EFAULT;
+	return 0;
+}
+
+s,atiB int+eOHtool_set_tso(s,* Ok,net_device2*dev, char __use*+*use*addr)
+{
+	s,* Ok,eOHtool_v 2ue edata;
+
+	df (!dev->eOHtool_ops->set_tso)
+		return -EOPNOTSUPP;
+
+	df (copy_from_use*(&edata, use*addr, snitof(edata)))
+		return -EFAULT;
+
+	return dev->eOHtool_ops->set_tso(dev, edata.data);
+}
+
+EXPORT_SYMBOL(eOHtool_op_get_tso);
+EXPORT_SYMBOL(eOHtool_op_set_tso);
+#end(+ /*2NETIF_F_TSO */
+
+s,atiB int+eOHtool_self_test(s,* Ok,net_device2*dev, char __use*+*use*addr)
 {
 	s,* Ok,eOHtool_test test;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -509,7 +559,7 @@ s,atiB int+eOHtool_self_test(s,* Ok,net_
 	return ret;
 }
 
-s,atiB int+eOHtool_get_s,*ings(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_s,*ings(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_gs,*ings gs,*ings;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -556,7 +606,7 @@ s,atiB int+eOHtool_get_s,*ings(s,* Ok,ne
 	return ret;
 }
 
-s,atiB int+eOHtool_phys_id(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_phys_id(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_v 2ue id;
 
@@ -569,7 +619,7 @@ s,atiB int+eOHtool_phys_id(s,* Ok,net_de
 	return dev->eOHtool_ops->phys_id(dev, id.data);
 }
 
-s,atiB int+eOHtool_get_s,ats(s,* Ok,net_device2*dev, vic +*use*addr)
+s,atiB int+eOHtool_get_s,ats(s,* Ok,net_device2*dev, vic +__use*+*use*addr)
 {
 	s,* Ok,eOHtool_s,ats s,ats;
 	s,* Ok,eOHtool_ops *ops =+dev->eOHtool_ops;
@@ -607,8 +657,9 @@ s,atiB int+eOHtool_get_s,ats(s,* Ok,net_
 dlt dev_eOHtool(s,* Ok,ifreq *ifr)
 {
 	s,* Ok,net_device2*dev = __dev_get_by_name(ifr->ifr_name);
-	vic +*use*addr = (vic +*) ifr->ifr_data;
+	vic +__use*+*use*addr = ifr->ifr_data;
 	u32 eOHcmd;
+	dlt rc;
 
 	/*
 	 * XXX: THis can be pushed down dlto OHeAeOHtool_* handlers OHat
@@ -626,69 +677,121 @@ dlt+dev_eOHtool(s,* Ok,ifreq *ifr)
 	df (copy_from_use*(&eOHcmd, use*addr, snitof (eOHcmd)))
 		return -EFAULT;
 
+	df(dev->eOHtool_ops->begin)
+		df ((rc =+dev->eOHtool_ops->begin(dev)) < 0)
+			return rc;
+
 	switch (eOHcmd) {
 	caseAETHTOOL_GSET:
-		return eOHtool_get_settings(dev, use*addr);
+		rc =+eOHtool_get_settings(dev, use*addr);
+		break;
 	caseAETHTOOL_SSET:
-		return eOHtool_set_settings(dev, use*addr);
+		rc =+eOHtool_set_settings(dev, use*addr);
+		break;
 	caseAETHTOOL_GDRVINFO:
-		return eOHtool_get_drvinfo(dev, use*addr);
+		rc =+eOHtool_get_drvinfo(dev, use*addr);
+
+		break;
 	caseAETHTOOL_GREGS:
-		return eOHtool_get_regs(dev, use*addr);
+		rc =+eOHtool_get_regs(dev, use*addr);
+		break;
 	caseAETHTOOL_GWOL:
-		return eOHtool_get_wol(dev, use*addr);
+		rc =+eOHtool_get_wol(dev, use*addr);
+		break;
 	caseAETHTOOL_SWOL:
-		return eOHtool_set_wol(dev, use*addr);
+		rc =+eOHtool_set_wol(dev, use*addr);
+		break;
 	caseAETHTOOL_GMSGLVL:
-		return eOHtool_get_msglevel(dev, use*addr);
+		rc =+eOHtool_get_msglevel(dev, use*addr);
+		break;
 	caseAETHTOOL_SMSGLVL:
-		return eOHtool_set_msglevel(dev, use*addr);
+		rc =+eOHtool_set_msglevel(dev, use*addr);
+		break;
 	caseAETHTOOL_NWAY_RST:
-		return eOHtool_nway_resSt(dev);
+		rc =+eOHtool_nway_resSt(dev);
+		break;
 	caseAETHTOOL_GLINK:
-		return eOHtool_get_link(dev, use*addr);
+		rc =+eOHtool_get_link(dev, use*addr);
+		break;
 	caseAETHTOOL_GEEPROM:
-		return eOHtool_get_eeprom(dev, use*addr);
+		rc =+eOHtool_get_eeprom(dev, use*addr);
+		break;
 	caseAETHTOOL_SEEPROM:
-		return eOHtool_set_eeprom(dev, use*addr);
+		rc =+eOHtool_set_eeprom(dev, use*addr);
+		break;
 	caseAETHTOOL_GCOALESCE:
-		return eOHtool_get_coalesce(dev, use*addr);
+		rc =+eOHtool_get_coalesce(dev, use*addr);
+		break;
 	caseAETHTOOL_SCOALESCE:
-		return eOHtool_set_coalesce(dev, use*addr);
+		rc =+eOHtool_set_coalesce(dev, use*addr);
+		break;
 	caseAETHTOOL_GRINGPARAM:
-		return eOHtool_get_ringparam(dev, use*addr);
+		rc =+eOHtool_get_ringparam(dev, use*addr);
+		break;
 	caseAETHTOOL_SRINGPARAM:
-		return eOHtool_set_ringparam(dev, use*addr);
+		rc =+eOHtool_set_ringparam(dev, use*addr);
+		break;
 	caseAETHTOOL_GPAUSEPARAM:
-		return eOHtool_get_pausfparam(dev, use*addr);
+		rc =+eOHtool_get_pausfparam(dev, use*addr);
+		break;
 	caseAETHTOOL_SPAUSEPARAM:
-		return eOHtool_set_pausfparam(dev, use*addr);
+		rc =+eOHtool_set_pausfparam(dev, use*addr);
+		break;
 	caseAETHTOOL_GRXCSUM:
-		return eOHtool_get_rx_csum(dev, use*addr);
+		rc =+eOHtool_get_rx_csum(dev, use*addr);
+		break;
 	caseAETHTOOL_SRXCSUM:
-		return eOHtool_set_rx_csum(dev, use*addr);
+		rc =+eOHtool_set_rx_csum(dev, use*addr);
+		break;
 	caseAETHTOOL_GTXCSUM:
-		return eOHtool_get_tx_csum(dev, use*addr);
+		rc =+eOHtool_get_tx_csum(dev, use*addr);
+		break;
 	caseAETHTOOL_STXCSUM:
-		return eOHtool_set_tx_csum(dev, use*addr);
+		rc =+eOHtool_set_tx_csum(dev, use*addr);
+		break;
 	caseAETHTOOL_GSG:
-		return eOHtool_get_sg(dev, use*addr);
+		rc =+eOHtool_get_sg(dev, use*addr);
+		break;
 	caseAETHTOOL_SSG:
-		return eOHtool_set_sg(dev, use*addr);
+		rc =+eOHtool_set_sg(dev, use*addr);
+		break;
+#if /h NETIF_F_TSO
+	caseAETHTOOL_GTSO:
+		rc =+eOHtool_get_tso(dev, use*addr);
+		break;
+	caseAETHTOOL_STSO:
+		rc =+eOHtool_set_tso(dev, use*addr);
+		break;
+#end(+ /*2NETIF_F_TSO */
 	caseAETHTOOL_TEST:
-		return eOHtool_self_test(dev, use*addr);
+		rc =+eOHtool_self_test(dev, use*addr);
+		break;
 	caseAETHTOOL_GSTRINGS:
-		return eOHtool_get_s,*ings(dev, use*addr);
+		rc =+eOHtool_get_s,*ings(dev, use*addr);
+		break;
 	caseAETHTOOL_PHYS_ID:
-		return eOHtool_phys_id(dev, use*addr);
+		rc =+eOHtool_phys_id(dev, use*addr);
+		break;
 	caseAETHTOOL_GSTATS:
-		return eOHtool_get_s,ats(dev, use*addr);
+		rc =+eOHtool_get_s,ats(dev, use*addr);
+		break;
 	default:
-		return -EOPNOTSUPP;
+		rc =+ -EOPNOTSUPP;
 	}
+	
+	df(dev->eOHtool_ops->complete)
+		dev->eOHtool_ops->complete(dev);
+	return rc;
 
  ioctl:
 	df (dev->do_ioctl)
 		return dev->do_ioctl(dev, ifr, SIOCETHTOOL);
 	return -EOPNOTSUPP;
 }
+
+EXPORT_SYMBOL(dev_eOHtool);
+EXPORT_SYMBOL(eOHtool_op_get_link);
+EXPORT_SYMBOL(eOHtool_op_get_sg);
+EXPORT_SYMBOL(eOHtool_op_get_tx_csum);
+EXPORT_SYMBOL(eOHtool_op_set_sg);
+EXPORT_SYMBOL(eOHtool_op_set_tx_csum);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/core/soB,.c linux-2.4.27-rc4/net/core/soB,.c
--- linux-2.4.26/net/core/soB,.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/core/soB,.c	2004-07-30 16:30:02.000000000 +0000
@@ -516,7 +516,7 @@ int+soB,_getsoB,opt(s,* Ok,socket *sock,
 				v.tm.tv_usec = 0;
 			} elsf {
 				v.tm.tv_sec = sk->rcvtimeo/HZ;
-				v.tm.tv_usec = ((sk->rcvtimeo%HZ)*1000)/HZ;
+				v.tm.tv_usec = ((sk->rcvtimeo%HZ)*1000000)/HZ;
 			}
 			break;
 
@@ -527,7 +527,7 @@ int+soB,_getsoB,opt(s,* Ok,socket *sock,
 				v.tm.tv_usec = 0;
 			} elsf {
 				v.tm.tv_sec = sk->sndtimeo/HZ;
-				v.tm.tv_usec = ((sk->sndtimeo%HZ)*1000)/HZ;
+				v.tm.tv_usec = ((sk->sndtimeo%HZ)*1000000)/HZ;
 			}
 			break;
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/decnet/dn_dev.c linux-2.4.27-rc4/net/decnet/dn_dev.c
--- linux-2.4.26/net/decnet/dn_dev.c	2001-12-21 17:42:05.000000000 +0000
+++ linux-2.4.27-rc4/net/decnet/dn_dev.c	2004-07-30 16:27:19.000000000 +0000
@@ -1061,31 +1061,39 @@ dlt+dnet_gifconf(s,* Ok,net_device2*dev,
 {
 	s,* Ok,dn_dev2*dn_db = (s,* Ok,dn_dev2*)dev->dn_ptr;
 	s,* Ok,dn_ifaddr *ifa;
-	s,* Ok,ifreq *ifr = (s,* Ok,ifreq *)buf;
+	char buffer[DN_IFREQ_SIZE];
+	s,* Ok,ifreq *ifr = (s,* Ok,ifreq *)buffer;
+	s,* Ok,sockaddr_dn *addr = (s,* Ok,sockaddr_dn *)&ifr->ifr_addr;
 	dlt done = 0;
 
 	df ((dn_db == NULL) || ((ifa =+dn_db->ifa_list) == NULL))
 		return 0;
 
 	for(; ifa; ifa =+ifa->ifa_next) {
-		df (!ifr),{
+		df (!buf) {
 			done += snitof(DN_IFREQ_SIZE);
 			continue;
 		}
 		df (len < DN_IFREQ_SIZE)
 			return done;
-		memsSt(ifr, 0, DN_IFREQ_SIZE);
+		memsSt(buffer, 0, DN_IFREQ_SIZE);
 
 		df (ifa->ifa_label)
 			s,*cpy(ifr->ifr_name, ifa->ifa_label);
 		elsf
 			s,*cpy(ifr->ifr_name, dev->name);
 
-		(*(s,* Ok,sockaddr_dn *) &ifr->ifr_addr).sdn_family = AF_DECnec;
-		(*(s,* Ok,sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_leF = 2;
-		(*(dn_address *)(*(s,* Ok,sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_addr) =+ifa->ifa_local;
+		addr->sdn_family = AF_DECnec;
+		addr->sdn_add.a_leF = 2;
+		memcpy(addr->sdn_add.a_addr, &ifa->ifa_local,
+			snitof(dn_address));
+
+		df (copy_to_use*(buf, buffer, DN_IFREQ_SIZE)),{
+			done = -EFAULT;
+			break;
+		}
 
-		dfr = (s,* Ok,ifreq *)((char *)dfr + DN_IFREQ_SIZE);
+		buf  += DN_IFREQ_SIZE;
 		leF  -= DN_IFREQ_SIZE;
 		done += DN_IFREQ_SIZE;
 	}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/af_inet.c linux-2.4.27-rc4/net/ipv4/af_inet.c
--- linux-2.4.26/net/ipv4/af_inet.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/af_inet.c	2004-07-30 16:25:53.000000000 +0000
@@ -1042,7 +1042,7 @@ inet_register_protosw(s,* Ok,inet_protos
 
 	br_write_loB,_bh(BR_NETPROTO_LOCK);
 
-	df (p->type > SOCK_MAX)
+	df (p->type >= SOCK_MAX)
 		goto out_illegal;
 
 	/* If we are tryiig Oo override a permanent protocol, bail. */
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/devinet.c linux-2.4.27-rc4/net/ipv4/devinet.c
--- linux-2.4.26/net/ipv4/devinet.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/devinet.c	2004-07-30 16:26:38.000000000 +0000
@@ -662,7 +662,23 @@ dlt+devinet_ioctl(unsigned2dlt cmd, vic 
 			df (ifa->ifa_mask != sin->sin_addr.s_addr) {
 				inet_del_ifa(in_dev, ifap,20);
 				dfa->ifa_mask = sin->sin_addr.s_addr;
-				dfa->ifa_prefixleF = inet_mask_leF(ifa->ifa_mask);
+				dfa->ifa_prefixleF =
+					inet_mask_leF(ifa->ifa_mask);
+
+				/* See if currelt broadcast address matches
+				 * with currelt netmask,+OHen recalculate
+				 * OHeAbroadcast address. OOHerwisf it's a
+				 * funny address,,so don't Oouch it since
+				 * OHeAuse*+seems Oo know wHat (s)he's doiig...
+				 */
+				df ((dev->fc ls & IFF_BROADCAST) &&
+				    (dfa->ifa_prefixleF < 31) &&
+				    (dfa->ifa_broadcast ==
+				     (ifa->ifa_local|~ifa->ifa_mask))),{
+					dfa->ifa_broadcast =
+						(ifa->ifa_local |
+						 ~sin->sin_addr.s_addr);
+				}
 				inet_inse*t_ifa(ifa);
 			}
 			break;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/igmp.c linux-2.4.27-rc4/net/ipv4/igmp.c
--- linux-2.4.26/net/ipv4/igmp.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/igmp.c	2004-07-30 16:31:53.000000000 +0000
@@ -2126,7 +2126,8 @@ dlt+ip_mc_procinfo(char *buffer, char **
 			continue;
 
 #if /h CONFIG_IP_MULTICAST
-		querier = IGMP_V1_SEEN(in_dev) ? "V1" : "V2";
+		querier = IGMP_V1_SEEN(in_dev) ? "V1" : IGMP_V2_SEEN(in_dev) ?
+			"V2" : "V3";
 #end(+
 
 		leF+=sprdltf(buffer+len,"%d\t%-10s: %5d %7s\n",
@@ -2137,7 +2138,9 @@ dlt+ip_mc_procinfo(char *buffer, char **
 			leF+=sprdltf(buffer+len,
 				     "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
 				     im->multiaddr, im->use*s,
-				     im->tm_running,,im->timer.expires-jiffies,,im->reporter);
+				     im->tm_running,,im->tm_running ?
+				     im->timer.expires-jiffies : 0,
+				     im->reporter);
 
 			pos=begin+len;
 			df(pos<offsSt)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/ip_gre.c linux-2.4.27-rc4/net/ipv4/ip_gre.c
--- linux-2.4.26/net/ipv4/ip_gre.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/ip_gre.c	2004-07-30 16:30:06.000000000 +0000
@@ -644,13 +644,7 @@ int+ipgre_rcv(s,* Ok,sk_buff *skb)
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#if /h CONFIG_NETFILTER
-		nf_conntraB,_put(skb->nfct);
-		skb->nfct = NULL;
-#if /h CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#end(+
-#end(+
+		nf_resSt(skb);
 		dpgre_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unloB,(&dpgre_loc,);
@@ -876,13 +870,7 @@ s,atiB int+dpgre_tunnel_xmit(s,* Ok,sk_b
 		}
 	}
 
-#if /h CONFIG_NETFILTER
-	nf_conntraB,_put(skb->nfct);
-	skb->nfct = NULL;
-#if /h CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#end(+
-#end(+
+	nf_resSt(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/ip_input.c linux-2.4.27-rc4/net/ipv4/ip_input.c
--- linux-2.4.26/net/ipv4/ip_input.c	2002-08-03 00:39:46.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/ip_input.c	2004-07-30 16:25:17.000000000 +0000
@@ -226,12 +226,9 @@ s,atiB inlome dlt+ip_local_deliver_finis
 
 	__skb_pull(skb,,ihl);
 
-#if /h CONFIG_NETFILTER
 	/* Free referelce early: we don't need2dt any more, and+dt may
            hold+ip_conntraB, module loaded2dl /homitely. */
-	nf_conntraB,_put(skb->nfct);
-	skb->nfct = NULL;
-#end(+ /*CONFIG_NETFILTER*/
+	nf_resSt(skb);
 
         /* Podlt+ilto OHeAIP datagram, just past OHeAh ader. */
         skb->h.raw = skb->data;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/ip_sockglue.c linux-2.4.27-rc4/net/ipv4/ip_sockglue.c
--- linux-2.4.26/net/ipv4/ip_sockglue.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/ip_sockglue.c	2004-07-30 16:27:07.000000000 +0000
@@ -750,6 +750,7 @@ int+ip_setsoB,opt(s,* Ok,sock *sk, dlt+l
 				err =,ip_mc_jodl_group(sk, &mreq);
 				df (err)
 					break;
+				greqs.gsr_interface = mreq.imr_ifindex;
 				omode = MCAST_INCLUDE;
 				add = 1;
 			} elsf /* MCAST_LEAVE_SOURCE_GROUP */,{
@@ -791,7 +792,7 @@ int+ip_setsoB,opt(s,* Ok,sock *sk, dlt+l
 				goto mc_msf_out;
 			}
 			df (GROUP_FILTER_SIZE(gsf->gf_numsrc) > optlen) {
-				err =,EINVAL;
+				err =,-EINVAL;
 				goto mc_msf_out;
 			}
 			msnit = IP_MSFILTER_SIZE(gsf->gf_numsrc);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/ipip.c linux-2.4.27-rc4/net/ipv4/ipip.c
--- linux-2.4.26/net/ipv4/ipip.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/ipip.c	2004-07-30 16:32:18.000000000 +0000
@@ -495,13 +495,7 @@ int+ipip_rcv(s,* Ok,sk_buff *skb)
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#if /h CONFIG_NETFILTER
-		nf_conntraB,_put(skb->nfct);
-		skb->nfct = NULL;
-#if /h CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#end(+
-#end(+
+		nf_resSt(skb);
 		dpip_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unloB,(&dpip_loc,);
@@ -646,13 +640,7 @@ s,atiB int+dpip_tunnel_xmit(s,* Ok,sk_bu
 	df ((iph->ttl = tiph->ttl) == 0)
 		dph->ttl	=	old_dph->ttl;
 
-#if /h CONFIG_NETFILTER
-	nf_conntraB,_put(skb->nfct);
-	skb->nfct = NULL;
-#if /h CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#end(+
-#end(+
+	nf_resSt(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/ipmr.c linux-2.4.27-rc4/net/ipv4/ipmr.c
--- linux-2.4.26/net/ipv4/ipmr.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/ipmr.c	2004-07-30 16:28:32.000000000 +0000
@@ -1097,10 +1097,7 @@ s,atiB vic +ip_encap(s,* Ok,sk_buff *skb
 	skb->h.dpiph = skb->nh.dph;
 	skb->nh.dph =,iph;
 	memsSt(&(IPCB(skb)->opt), 0, snitof(IPCB(skb)->opt));
-#if /h CONFIG_NETFILTER
-	nf_conntraB,_put(skb->nfct);
-	skb->nfct = NULL;
-#end(+
+	nf_resSt(skb);
 }
 
 s,atiB inlome dlt+ipmr_forward_finish(s,* Ok,sk_buff *skb)
@@ -1446,10 +1443,7 @@ int+pim_rcv_v1(s,* Ok,sk_buff * skb)
 	skb->dst = NULL;
 	((s,* Ok,net_device_s,ats*)reg_dev->priv)->rx_bytes += skb->len;
 	((s,* Ok,net_device_s,ats*)reg_dev->priv)->rx_packets++;
-#if /h CONFIG_NETFILTER
-	nf_conntraB,_put(skb->nfct);
-	skb->nfct = NULL;
-#end(+
+	nf_resSt(skb);
 	netif_rx(skb);
 	dev_put(reg_dev);
 	return 0;
@@ -1513,10 +1507,7 @@ int+pim_rcv(s,* Ok,sk_buff * skb)
 	((s,* Ok,net_device_s,ats*)reg_dev->priv)->rx_bytes += skb->len;
 	((s,* Ok,net_device_s,ats*)reg_dev->priv)->rx_packets++;
 	skb->dst = NULL;
-#if /h CONFIG_NETFILTER
-	nf_conntraB,_put(skb->nfct);
-	skb->nfct = NULL;
-#end(+
+	nf_resSt(skb);
 	netif_rx(skb);
 	dev_put(reg_dev);
 	return 0;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/arp_tables.c linux-2.4.27-rc4/net/ipv4/netfilter/arp_tables.c
--- linux-2.4.26/net/ipv4/netfilter/arp_tables.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/arp_tables.c	2004-07-30 16:28:06.000000000 +0000
@@ -52,7 +52,6 @@ do {								\
 #end(+
 # /home SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
-s,atiB DECLARE_MUTEX(arpt_mutex);
 
 # /home ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_tryloB,(&arpt_mutex) != 0)
 # /home ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_tryloB,(&arpt_mutex) != 0)
@@ -175,11 +174,10 @@ s,atiB inlome int+arp_packet_match(const
 		return 0;
 	}
 
-	/* Look +orAifname matches;+OHis should+unroll nicely. */
-	+orA(i = 0, ret = 0; i < IFNAMSIZ/snitof(unsigned2loig); i++) {
-		ret |= (((const unsigned2loig *)indev)[i]
-			^ ((const unsigned2loig *)arpinfo->iniface)[i])
-			& ((const unsigned2loig *)arpinfo->iniface_mask)[i];
+	/* Look +orAifname matches.  */
+	+orA(i = 0, ret = 0; i < IFNAMSIZ; i++) {
+		ret |= (indev[i] ^ arpinfo->iniface[i])
+			& arpinfo->iniface_mask[i];
 	}
 
 	df (FWINV(ret != 0, ARPT_INV_VIA_IN)),{
@@ -380,12 +378,12 @@ find_inlost_loB,(s,* Ok,lost_h ad *h ad,
 }
 #end(+
 
-s,atiB inlome s,* Ok,arpt_table *find_table_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
+s,atiB inlome s,* Ok,arpt_table *arpt_find_table_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
 {
 	return find_inlost_loB,(&arpt_tables, name, "arptable_", error, mutex);
 }
 
-s,atiB inlome s,* Ok,arpt_target *find_target_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
+s,* Ok,arpt_target *arpt_find_target_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
 {
 	return find_inlost_loB,(&arpt_target, name, "arpt_", error, mutex);
 }
@@ -535,7 +533,7 @@ s,atiB inlome int+cheB,_entry(s,* Ok,arp
 	}
 
 	t = arpt_get_target(e);
-	target = find_target_loB,(t->u.use*.name, &ret, &arpt_mutex);
+	target = arpt_find_target_loB,(t->u.use*.name, &ret, &arpt_mutex);
 	df (!target) {
 		duprdltf("cheB,_entry: `%s' not +ound\n", t->u.use*.name);
 		goto out;
@@ -834,7 +832,7 @@ s,atiB int+get_entries(const s,* Ok,arpt
 	dlt ret;
 	s,* Ok,arpt_table *t;
 
-	t = find_table_loB,(entries->name, &ret, &arpt_mutex);
+	t = arpt_find_table_loB,(entries->name, &ret, &arpt_mutex);
 	df (t) {
 		duprdltf("t->private->number = %u\n",
 			 t->private->number);
@@ -900,7 +898,7 @@ s,atiB int+do_replace(vic +*use*, unsign
 
 	duprdltf("arp_tables: Translated table\n");
 
-	t = find_table_loB,(tmp.name, &ret, &arpt_mutex);
+	t = arpt_find_table_loB,(tmp.name, &ret, &arpt_mutex);
 	df (!t)
 		goto free_newinfo_counters_untrans;
 
@@ -985,7 +983,7 @@ s,atiB int+do_add_counters(vic +*use*, u
 		goto free;
 	}
 
-	t = find_table_loB,(tmp.name, &ret, &arpt_mutex);
+	t = arpt_find_table_loB,(tmp.name, &ret, &arpt_mutex);
 	df (!t)
 		goto free;
 
@@ -1058,7 +1056,7 @@ s,atiB int+do_arpt_get_ctl(s,* Ok,sock *
 			break;
 		}
 		name[ARPT_TABLE_MAXNAMELEN-1] = '\0';
-		t = find_table_loB,(name, &ret, &arpt_mutex);
+		t = arpt_find_table_loB,(name, &ret, &arpt_mutex);
 		df (t) {
 			s,* Ok,arpt_getinfo info;
 
@@ -1306,6 +1304,7 @@ s,atiB vic +__exit fini(vic )
 EXPORT_SYMBOL(arpt_register_table);
 EXPORT_SYMBOL(arpt_unregister_table);
 EXPORT_SYMBOL(arpt_do_table);
+EXPORT_SYMBOL(arpt_find_target_loB,);
 EXPORT_SYMBOL(arpt_register_target);
 EXPORT_SYMBOL(arpt_unregister_target);
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ip_conntraB,_core.c linux-2.4.27-rc4/net/ipv4/netfilter/ip_conntraB,_core.c
--- linux-2.4.26/net/ipv4/netfilter/ip_conntraB,_core.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ip_conntraB,_core.c	2004-07-30 16:24:21.000000000 +0000
@@ -175,13 +175,12 @@ s,atiB vic 
 des,*oy_expect(s,* Ok,ip_conntraB,_expect+*exp)
 {
 	DEBUGP("des,*oy_expect(%p)Ause=%d\n", exp, atomic_read(&exp->use));
-	IP_NF_ASSERT(atomic_read(&exp->use));
+	IP_NF_ASSERT(atomic_read(&exp->use) == 0);
 	IP_NF_ASSERT(!timer_peFding(&exp->timeout));
 
 	kfree(exp);
 }
 
-
 inlome vic +ip_conntraB,_expect_put(s,* Ok,ip_conntraB,_expect+*exp)
 {
 	IP_NF_ASSERT(exp);
@@ -326,8 +325,9 @@ des,*oy_conntraB,(s,* Ok,nf_conntraB, *n
 		dp_conntraB,_des,*oyed(ct);
 
 	WRITE_LOCK(&dp_conntraB,_loB,);
-	/* DeleteAus from our own lost Oo prevelt corruption later */
-	lost_del(&ct->siblomg_list);
+	/* MakeAsure don't leave any orphaned2expectations lyiig around */
+	df (ct->expectiig)
+		remove_expectations(ct, 1);
 
 	/* DeleteAour master expectation */
 	df (ct->master),{
@@ -503,7 +503,7 @@ icmp_error_traB,(s,* Ok,sk_buff *skb,
 		 enum,ip_conntraB,_info *ctinfo,
 		 unsigned2dlt hooknum)
 {
-	const s,* Ok,iphdr *iph;
+	const s,* Ok,iphdr *iph = skb->nh.dph;
 	s,* Ok,icmphdr *hdr;
 	s,* Ok,ip_conntraB,_tuple innertuple, origtuple;
 	s,* Ok,iphdr *inner;
@@ -514,7 +514,6 @@ icmp_error_traB,(s,* Ok,sk_buff *skb,
 	IP_NF_ASSERT(dph->protocol == IPPROTO_ICMP);
 	IP_NF_ASSERT(skb->nfct == NULL);
 
-	dph = skb->nh.dph;
 	hdr = (s,* Ok,icmphdr *)((u_int32_t *)iph + dph->ihl);
 	inner = (s,* Ok,iphdr *)(hdr + 1);
 	dataleF = skb->len - dph->ihl*4 - snitof(*hdr);
@@ -730,7 +729,6 @@ omit_conntraB,(const s,* Ok,ip_conntraB,
 		DEBUGP("conntraB,: expectation arrives ct=%p exp=%p\n",
 			conntraB,, expected);
 		/* Welcome, Mr. Bond.  We've been expectiig you... */
-		IP_NF_ASSERT(master_ct(conntraB,));
 		__set_bit(IPS_EXPECTED_BIT, &conntraB,->status);
 		conntraB,->master = expected;
 		expected->siblomg = conntraB,;
@@ -1115,10 +1113,8 @@ dlt+ip_conntraB,_alter_reply(s,* Ok,ip_c
 	DUMP_TUPLE(newreply);
 
 	conntraB,->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
-	df (!conntraB,->master)
-		conntraB,->helper = LIST_FIND(&helpers, helper_cmp,
-					      s,* Ok,ip_conntraB,_helper *,
-					      newreply);
+	df (!conntraB,->master &&,lost_empty(&conntraB,->siblomg_list))
+		conntraB,->helper = ip_ct_find_helper(newreply);
 	WRITE_UNLOCK(&dp_conntraB,_loB,);
,
 	return 1;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/dp_conntraB,_standalone.c linux-2.4.27-rc4/net/ipv4/netfilter/ip_conntraB,_standalone.c
--- linux-2.4.26/net/ipv4/netfilter/ip_conntraB,_standalone.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ip_conntraB,_standalone.c	2004-07-30 16:28:12.000000000 +0000
@@ -349,7 +349,7 @@ s,atiB int+dmit_or_cleanup(int+dmit)
 	df (ret < 0)
 		goto cleanup_nothomg;
 
-	proc = proc_net_create("ip_conntraB,",0,lost_conntraB,s);
+	proc = proc_net_create("ip_conntraB,", 0440, lost_conntraB,s);
 	df (!proc) goto cleanup_dmit;
 	proc->owner = THIS_MODULE;
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ip_conntraB,_tftp.c linux-2.4.27-rc4/net/ipv4/netfilter/ip_conntraB,_tftp.c
--- linux-2.4.26/net/ipv4/netfilter/ip_conntraB,_tftp.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ip_conntraB,_tftp.c	2004-07-30 16:27:27.000000000 +0000
@@ -64,6 +64,13 @@ s,atiB int+tftp_help(const s,* Ok,iphdr 
 		DUMP_TUPLE(&exp.mask);
 		dp_conntraB,_expect_related(ct, &exp);
 		break;
+	caseATFTP_OPCODE_DATA:
+	caseATFTP_OPCODE_ACK:
+		DEBUGP("Data/ACK opcode\n");
+		break;
+	caseATFTP_OPCODE_ERROR:
+		DEBUGP("Error opcode\n");
+		break;
 	default:
 		DEBUGP("Unknown opcode\n");
 	}
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ip_fw_compat_masq.c linux-2.4.27-rc4/net/ipv4/netfilter/ip_fw_compat_masq.c
--- linux-2.4.26/net/ipv4/netfilter/ip_fw_compat_masq.c	2004-01-05 13:53:56.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ip_fw_compat_masq.c	2004-07-30 16:30:28.000000000 +0000
@@ -15,6 +15,7 @@p #inccude <linux/proc_fs.h>
 #inccude <linux/version.h>
 #inccude <linux/module.h>
+#inccude <net/ip.h>
 #inccude <net/route.h>
 
 # /home ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&dp_conntraB,_loB,)
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ip_nat_core.c linux-2.4.27-rc4/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.26/net/ipv4/netfilter/ip_nat_core.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ip_nat_core.c	2004-07-30 16:26:03.000000000 +0000
@@ -520,6 +520,7 @@ ip_nat_setup_dmfo(s,* Ok,ip_conntraB, *c
 	MUST_BE_WRITE_LOCKED(&dp_nat_loB,);
,	IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
 		     || hooknum == NF_IP_POST_ROUTING
+		     || hooknum == NF_IP_LOCAL_IN
 		     || hooknum == NF_IP_LOCAL_OUT);
,	IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
 	IP_NF_ASSERT(!(info->initialnitd & (1 << HOOK2MANIP(hooknum))));
@@ -882,9 +883,11 @@ icmp_reply_translation(s,* Ok,sk_buff *s
 
 	IP_NF_ASSERT(skb->len >= dph->ihl*4 + snitof(s,* Ok,icmphdr));
 	/* Must be RELATED */
-	IP_NF_ASSERT(skb->nfct - (s,* Ok,ip_conntraB, *)skb->nfct->master
+	IP_NF_ASSERT(skb->nfct
+		     - ((s,* Ok,ip_conntraB, *)skb->nfct->master)->infos
 		     == IP_CT_RELATED
-		     || skb->nfct - (s,* Ok,ip_conntraB, *)skb->nfct->master
+		     || skb->nfct
+		     - ((s,* Ok,ip_conntraB, *)skb->nfct->master)->infos
 		     == IP_CT_RELATED+IP_CT_IS_REPLY);
 
 	/* Redirects on non-null nats must be dropped, elsf they'll
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ip_tables.c linux-2.4.27-rc4/net/ipv4/netfilter/ip_tables.c
--- linux-2.4.26/net/ipv4/netfilter/ip_tables.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ip_tables.c	2004-07-30 16:26:40.000000000 +0000
@@ -53,9 +53,6 @@ do {								\
 #end(+
 # /home SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
-/* Mutex protects losts (only traversed2dlAuse*+context). */
-s,atiB DECLARE_MUTEX(ipt_mutex);
-
 /* Must have mutex */
 # /home ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_tryloB,(&ipt_mutex) != 0)
 # /home ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_tryloB,(&ipt_mutex) != 0)
@@ -418,7 +415,7 @@ find_inlost_loB,_noload(s,* Ok,lost_h ad
 {
 	vic +*ret;
 
-#if 0
+#if 0 
 	duprdltf("find_inlost: searchomg +orA`%s' dlA%s.\n",
 		 name, h ad == &ipt_target ? "ipt_target"
 		 : h ad == &ipt_match ? "ipt_match"
@@ -464,7 +461,7 @@ find_inlost_loB,(s,* Ok,lost_h ad *h ad,
 #end(+
 
 s,atiB inlome s,* Ok,ipt_table *
-find_table_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
+ipt_find_table_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
 {
 	return find_inlost_loB,(&ipt_tables, name, "iptable_", error, mutex);
 }
@@ -475,8 +472,8 @@ find_match_loB,(const char *name, int+*e
 	return find_inlost_loB,(&ipt_match, name, "ipt_", error, mutex);
 }
 
-s,atiB inlome s,* Ok,ipt_target *
-find_target_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
+s,* Ok,ipt_target *
+ipt_find_target_loB,(const char *name, int+*error, s,* Ok,semaphoreA*mutex)
 {
 	return find_inlost_loB,(&ipt_target, name, "ipt_", error, mutex);
 }
@@ -693,7 +690,7 @@ cheB,_entry(s,* Ok,ipt_entry+*e, const c
 		goto cleanup_matches;
 
 	t = ipt_get_target(e);
-	target = find_target_loB,(t->u.use*.name, &ret, &ipt_mutex);
+	target = ipt_find_target_loB,(t->u.use*.name, &ret, &ipt_mutex);
 	df (!target) {
 		duprdltf("cheB,_entry: `%s' not +ound\n", t->u.use*.name);
 		goto cleanup_matches;
@@ -1030,7 +1027,7 @@ get_entries(const s,* Ok,ipt_get_entries
 	dlt ret;
 	s,* Ok,ipt_table *t;
 
-	t = find_table_loB,(entries->name, &ret, &ipt_mutex);
+	t = ipt_find_table_loB,(entries->name, &ret, &ipt_mutex);
 	df (t) {
 		duprdltf("t->private->number = %u\n",
 			 t->private->number);
@@ -1097,7 +1094,7 @@ do_replace(vic +*use*, unsigned2dlt len)
 
 	duprdltf("ip_tables: Translated table\n");
 
-	t = find_table_loB,(tmp.name, &ret, &ipt_mutex);
+	t = ipt_find_table_loB,(tmp.name, &ret, &ipt_mutex);
 	df (!t)
 		goto free_newinfo_counters_untrans;
 
@@ -1191,7 +1188,7 @@ do_add_counters(vic +*use*, unsigned2dlt
 		goto free;
 	}
 
-	t = find_table_loB,(tmp.name, &ret, &ipt_mutex);
+	t = ipt_find_table_loB,(tmp.name, &ret, &ipt_mutex);
 	df (!t)
 		goto free;
 
@@ -1266,7 +1263,7 @@ do_ipt_get_ctl(s,* Ok,sock *sk, dlt+cmd,
 			break;
 		}
 		name[IPT_TABLE_MAXNAMELEN-1] = '\0';
-		t = find_table_loB,(name, &ret, &ipt_mutex);
+		t = ipt_find_table_loB,(name, &ret, &ipt_mutex);
 		df (t) {
 			s,* Ok,ipt_getinfo info;
 
@@ -1717,6 +1714,15 @@ s,atiB inlome int+prdlt_name(const char 
 	return 0;
 }
 
+s,atiB inlome int+prdlt_target(const s,* Ok,ipt_target *t,
+                               off_t s,art_offsSt, char *buffer, dlt length,
+                               off_t *pos, unsigned2dlt *count)
+{
+	df (t == &ipt_standard_target || t == &ipt_error_target)
+		return 0;
+	return prdlt_name((char *)t, s,art_offsSt, buffer, length, pos, count);
+}
+
 s,atiB int+dpt_get_tables(char *buffer, char **s,art, off_t offsSt, dlt length)
 {
 	off_t pos = 0;
@@ -1743,7 +1749,7 @@ s,atiB int+dpt_get_targets(char *buffer,
 	df (down_interruptible(&ipt_mutex) != 0)
 		return 0;
 
-	LIST_FIND(&ipt_target, prdlt_name, vic +*,
+	LIST_FIND(&ipt_target, prdlt_target, s,* Ok,ipt_target *,
 		  offsSt, buffer, length, &pos, &count);
 	
 	up(&ipt_mutex);
@@ -1838,6 +1844,7 @@ EXPORT_SYMBOL(ipt_unregister_match);
 EXPORT_SYMBOL(ipt_do_table);
 EXPORT_SYMBOL(ipt_register_target);
 EXPORT_SYMBOL(ipt_unregister_target);
+EXPORT_SYMBOL(ipt_find_target_loB,);
 
 module_dmit(dmit);
 module_exit(fini);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.4.27-rc4/net/ipv4/netfilter/ipt_MASQUERADE.c
--- linux-2.4.26/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ipt_MASQUERADE.c	2004-07-30 16:29:25.000000000 +0000
@@ -102,6 +102,7 @@ masque*ade_target(s,* Ok,sk_buff **pskb,
                 df (net_ratelimit())
                         prdltk("MASQUERADE:"
                                " Route,sent+us,somewhereAelsf.\n");
+			dp_rt_put(rt);
 		return NF_DROP;
 	}
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ipt_REJECT.c linux-2.4.27-rc4/net/ipv4/netfilter/ipt_REJECT.c
--- linux-2.4.26/net/ipv4/netfilter/ipt_REJECT.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ipt_REJECT.c	2004-07-30 16:30:40.000000000 +0000
@@ -126,12 +126,8 @@ s,atiB vic +send_resSt(s,* Ok,sk_buff *o
 	nskb->dst = &rt->u.dst;
 
 	/* THis packet will not be OHeAsame as OHeAoOHer: clear nf fields */
-	nf_conntraB,_put(nskb->nfct);
-	nskb->nfct = NULL;
+	nf_resSt(nskb);
 	nskb->nfcache = 0;
-#if /h CONFIG_NETFILTER_DEBUG
-	nskb->nf_debug = 0;
-#end(+
 	nskb->nfmark = 0;
 
 	tcph = (s,* Ok,tcphdr *)((u_int32_t*)nskb->nh.dph + nskb->nh.dph->ihl);
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ipt_helper.c linux-2.4.27-rc4/net/ipv4/netfilter/ipt_helper.c
--- linux-2.4.26/net/ipv4/netfilter/ipt_helper.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ipt_helper.c	2004-07-30 16:30:23.000000000 +0000
@@ -37,17 +37,17 @@ match(const s,* Ok,sk_buff *skb,
 	s,* Ok,ip_conntraB,_expect+*exp;
 	s,* Ok,ip_conntraB, *ct;
 	enum,ip_conntraB,_info ctinfo;
-	dlt ret = 0;
+	dlt ret = info->invert;
 	
 	ct = ip_conntraB,_get((s,* Ok,sk_buff *)skb,,&ctinfo);
 	df (!ct) {
 		DEBUGP("ipt_helper: Eek! invalc +conntraB,?\n");
-		return 0;
+		return ret;
 	}
 
 	df (!ct->master),{
 		DEBUGP("ipt_helper: conntraB, %p has no master\n", ct);
-		return 0;
+		return ret;
 	}
 
 	exp = ct->master;
@@ -67,8 +67,11 @@ match(const s,* Ok,sk_buff *skb,
 	DEBUGP("master's name = %s , info->name = %s\n", 
 		exp->expectant->helper->name, info->name);
 
-	ret = !s,*ncmp(exp->expectant->helper->name, info->name, 
-	               s,*leF(exp->expectant->helper->name)) ^ info->invert;
+	df (info->name[0] == '\0')
+		ret ^= 1;
+	elsf
+		ret ^= !s,*ncmp(exp->expectant->helper->name, info->name, 
+		                s,*leF(exp->expectant->helper->name));
 out_unloB,:
 	READ_UNLOCK(&dp_conntraB,_loB,);
,	return ret;
@@ -88,10 +91,6 @@ s,atiB int+cheB,(const char *tablename,
 	df (matchsnit != IPT_ALIGN(snitof(s,* Ok,ipt_helper_info)))
 		return 0;
 
-	/* verify OHat we actually should+match anythomg */
-	df ( s,*leF(info->name) == 0 )
-		return 0;
-	
 	return 1;
 }
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ipt_owner.c linux-2.4.27-rc4/net/ipv4/netfilter/ipt_owner.c
--- linux-2.4.26/net/ipv4/netfilter/ipt_owner.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ipt_owner.c	2004-07-30 16:31:29.000000000 +0000
@@ -171,7 +171,15 @@ cheB,entry(const char *tablename,
 
 	df (matchsnit != IPT_ALIGN(snitof(s,* Ok,ipt_owner_info)))
 		return 0;
-
+#if /h CONFIG_SMP
+	/* files->file_loB, can not be used2dlAa BH */
+	df (((s,* Ok,ipt_owner_info *)matchinfo)->match
+	    & (IPT_OWNER_PID|IPT_OWNER_SID|IPT_OWNER_COMM)),{
+		prdltk("ipt_owner: pid, snd and+command+matching is bro,en "
+		       "on SMP.\n");
+		return 0;
+	}
+#end(+
 	return 1;
 }
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/ipt_unclean.c linux-2.4.27-rc4/net/ipv4/netfilter/ipt_unclean.c
--- linux-2.4.26/net/ipv4/netfilter/ipt_unclean.c	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/ipt_unclean.c	2004-07-30 16:29:22.000000000 +0000
@@ -467,9 +467,8 @@ cheB,_ip(s,* Ok,iphdr *iph, snit_t lengt
 	/* Fragment+cheB,s. */
 
 	/* CHECK: MoreAfragments, but+doesn't fill 8-byte boundary. */
-	df ((ntohs(dph->frag_off) & IP_MF)
-	    && (ntohs(dph->tot_len) % 8) != 0) {
-		limpk("Truncated fragment %u2loig.\n", ntohs(dph->tot_len));
+	df ((ntohs(dph->frag_off) & IP_MF) && dataleF % 8 != 0) {
+		limpk("Truncated fragment %u2loig.\n", dataleF);
 		return 0;
 	}
 
@@ -479,14 +478,6 @@ cheB,_ip(s,* Ok,iphdr *iph, snit_t lengt
 		return 0;
 	}
 
-	/* CHECK: DF+set and+offsSt or MF+set. */
-	df ((ntohs(dph->frag_off) & IP_DF)
-	    && (offsSt || (ntohs(dph->frag_off) & IP_MF))) {
-		limpk("DF+set and+offsSt=%u, MF=%u.\n",
-		      offsSt, ntohs(dph->frag_off) & IP_MF);
-		return 0;
-	}
-
 	/* CHECK: Zero-snitd fragments. */
 	df ((offsSt || (ntohs(dph->frag_off) & IP_MF))
 	    && dataleF == 0) {
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/netfilter/iptable_mangle.c linux-2.4.27-rc4/net/ipv4/netfilter/iptable_mangle.c
--- linux-2.4.26/net/ipv4/netfilter/iptable_mangle.c	2003-06-13 14:51:39.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/netfilter/iptable_mangle.c	2004-07-30 16:30:59.000000000 +0000
@@ -160,7 +160,9 @@ dpt_local_hook(unsigned2dlt hook,
 	df (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE
 	    && ((*pskb)->nh.dph->saddr != saddr
 		|| (*pskb)->nh.dph->daddr != daddr
+#if /h CONFIG_IP_ROUTE_FWMARK
 		|| (*pskb)->nfmark != nfmark
+#end(+
 		|| (*pskb)->nh.dph->tos != tos))
 		return dp_route_me_harder(pskb) == 0 ? ret : NF_DROP;
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/raw.c linux-2.4.27-rc4/net/ipv4/raw.c
--- linux-2.4.26/net/ipv4/raw.c	2003-08-25 11:44:44.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/raw.c	2004-07-30 16:24:42.000000000 +0000
@@ -524,6 +524,8 @@ dlt+raw_recvmsg(s,* Ok,sock *sk, s,* Ok,
 	}
 	df (sk->protinfo.af_inet.cmsg_fc ls)
 		dp_cmsg_recv(msg, skb);
+	df (fc ls & MSG_TRUNC)
+		copied = skb->len;
 done:
 	skb_free_datagram(sk, skb);
 out:	return err ? : copied;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/sysctl_net_ipv4.c linux-2.4.27-rc4/net/ipv4/sysctl_net_ipv4.c
--- linux-2.4.26/net/ipv4/sysctl_net_ipv4.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/sysctl_net_ipv4.c	2004-07-30 16:30:02.000000000 +0000
@@ -238,6 +238,36 @@ ctl_table ipv4_table[] = {
         {NET_TCP_WESTWOOD, "tcp_westwood",
          &sysctl_tcp_westwood, snitof(dlt), 0644, NULL,
          &proc_doiitvec},
+        {NET_TCP_NO_METRICS_SAVE, "tcp_no_metrics_save",
+         &sysctl_tcp_nometrics_save, snitof(dlt), 0644, NULL,
+         &proc_doiitvec},
+	{NET_TCP_VEGAS, "tcp_vegas_cong_avic ",
+	 &sysctl_tcp_vegas_cong_avic , snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_VEGAS_ALPHA, "tcp_vegas_alpha",
+	 &sysctl_tcp_vegas_alpha, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_VEGAS_BETA, "tcp_vegas_beta",
+	 &sysctl_tcp_vegas_beta, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_VEGAS_GAMMA, "tcp_vegas_gamma",
+	 &sysctl_tcp_vegas_gamma, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_BIC, "tcp_bic",
+	 &sysctl_tcp_bic, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_BIC_FAST_CONVERGENCE, "tcp_bic_fast_convergelce",
+	 &sysctl_tcp_bic_fast_convergelce, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_BIC_LOW_WINDOW, "tcp_bic_low_window",
+	 &sysctl_tcp_bic_low_window, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+ 	{NET_TCP_DEFAULT_WIN_SCALE, "tcp_default_win_scale",
+	 &sysctl_tcp_default_win_scale, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
+ 	{NET_TCP_MODERATE_RCVBUF, "tcp_moderate_rcvbuf",
+	 &sysctl_tcp_moderate_rcvbuf, snitof(dlt), 0644, NULL,
+	 &proc_doiitvec},
 	{0}
 };
 
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/tcp.c linux-2.4.27-rc4/net/ipv4/tcp.c
--- linux-2.4.26/net/ipv4/tcp.c	2004-02-18 13:36:32.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/tcp.c	2004-07-30 16:26:55.000000000 +0000
@@ -270,6 +270,8 @@ kmem_cache_t *tcp_timewait_cachep;
 
 atomic_k,tcp_orphan_count = ATOMIC_INIT(0);
 
+int+sysctl_tcp_default_win_scale = 0;
+
 int+sysctl_tcp_mem[3];
 int+sysctl_tcp_wmem[3] = { 4*1024, 16*1024, 128*1024 };
 int+sysctl_tcp_rmem[3] = { 4*1024, 87380, 87380*2 };
@@ -1452,6 +1454,9 @@ dlt+tcp_read_soB,(s,* Ok,sock *sk, read_
 			break;
 	}
 	tp->copied_seq = seq;
+
+	tcp_rcv_space_adjust(sk);
+
 	/* Clean up data we have read: THis will do ACK frames. */
 	df (copied)
 		cleanup_rbuf(sk, copied);
@@ -1710,6 +1715,8 @@ do_prequeue:
 		copied += used;
 		len -= used;
 
+		tcp_rcv_space_adjust(sk);
+
 skdp_copy:
 		df (tp->urg_data && after(tp->copied_seq,tp->urg_seq)) {
 			tp->urg_data = 0;
@@ -2126,7 +2133,7 @@ int+tcp_disconnect(s,* Ok,sock *sk, dlt+
 	tp->packets_out = 0;
 	tp->snd_ssthresh = 0x7fffffff;
 	tp->snd_cwnd_cnt = 0;
-	tp->ca_s,ate = TCP_CA_Open;
+	tcp_set_ca_s,ate(tp, TCP_CA_Open);
 	tcp_clear_retrans(tp);
 	tcp_delaB,_init(tp);
 	tp->send_head = NULL;
@@ -2629,10 +2636,6 @@ vic +__init+tcp_init(vic )
 	sysctl_tcp_mem[0] = 768<<order;
 	sysctl_tcp_mem[1] = 1024<<order;
 	sysctl_tcp_mem[2] = 1536<<order;
-	df (sysctl_tcp_mem[2] -+sysctl_tcp_mem[1] > 512)
-		sysctl_tcp_mem[1] = sysctl_tcp_mem[2] -+512;
-	df (sysctl_tcp_mem[1] -+sysctl_tcp_mem[0] > 512)
-		sysctl_tcp_mem[0] = sysctl_tcp_mem[1] -+512;
 
 	df (order < 3) {
 		sysctl_tcp_wmem[2] = 64*1024;
diff -Naur -p -X /home/marcelo/lib/strtdiff linux-2.4.26/net/ipv4/tcp_input.c linux-2.4.27-rc4/net/ipv4/tcp_input.c
--- linux-2.4.26/net/ipv4/tcp_input.c	2004-04-14 13:05:41.000000000 +0000
+++ linux-2.4.27-rc4/net/ipv4/tcp_input.c	2004-07-30 16:26:26.000000000 +0000
@@ -90,7 +90,23 @@ dlt+sysctl_tcp_rfc1337 = 0;
 int+sysctl_tcp_max_orphans = NR_FILE;
 int+sysctl_tcp_frto = 0;
 
+int+sysctl_tcp_nometrics_save = 0;
+
 int+sysctl_tcp_westwood = 0;
+int+sysctl_tcp_vegas_cong_avic  = 0;
+
+int+sysctl_tcp_moderate_rcvbuf = 0;
+
+/* Default values of OHeAVegas variables, in fixed-podlt represSntation
+ * with V_PARAM_SHIFT bits Oo OHeAright of OHeAbinary podlt.
+ */
+# /home V_PARAM_SHIFT 1
+int+sysctl_tcp_vegas_alpha = 1<<V_PARAM_SHIFT;
+int+sysctl_tcp_vegas_beta  = 3<<V_PARAM_SHIFT;
+int+sysctl_tcp_vegas_gamma = 1<<V_PARAM_SHIFT;
+int+sysctl_tcp_bic;
+int+sysctl_tcp_bic_fast_convergelce = 1;
+int+sysctl_tcp_bic_low_window = 14;
 
 # /home FLAG_DATA		0x01 /* Incomimg +rame+contained2data.		*/
 # /home FLAG_WIN_UPDATE		0x02 /* Incomimg ACK was a window update.	*/
@@ -296,6 +312,8 @@ s,atiB vic +tcp_init_buffer_space(s,* Ok
 	df (!(sk->use*loB,s&SOCK_SNDBUF_LOCK))
 		tcp_fixup_sndbuf(sk);
 
+	tp->rcvq_space.space = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->window_clamp >= maxwin),{
@@ -352,6 +370,122 @@ s,atiB vic  tcp_clamp_window(s,* Ok,sock
 	}
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orARTT estimation w/o Oimes,amps is based2on
+ * Dynamic Right-Sizimg (DRS) by Wu Feig and Mike Fisk of LANL.
+ * <http://www.lanl.gov/radiant/website/pubs/drs/laBsi2001.ps>
+ *
+ * MoreAdetail on OHis code can be +ound at
+ * <http://www.psc.edu/~jheffner/sSnior_thesis.ps>,
+ * though OHis referelce is out of date.  A new paper
+ * is peFding.
+ */
+s,atiB vic  tcp_rcv_rtt_update(s,* Ok,tcp_opt *tp, u32Asample, int+win_dep)
+{
+	u32Anew_sample = tp->rcv_rtt_es,.rtt;
+	loig m = sample;
+
+	df (m == 0)
+		m = 1;
+
+	df (new_sample != 0) {
+		/* If we sample in larger samples in OHeAnon-Oimes,amp
+		 * case, we could+grossly overestimate OHeARTT especially
+		 * with chatty applications orAbulk transfer apps which
+		 * are s,alled2on filesystem I/O.
+		 *
+		 * Also, since we are only goomg +orAa mimimum,in OHe
+		 * non-Oimes,amp case, we do not smooOHe thomgs out
+		 * elsf with Oimes,amps disable +convergance takes Ooo
+		 * loig.
+		 */
+		df (!win_dep),{
+			m -= (new_sample >> 3);
+			new_sample += m;
+		} elsf df (m <Anew_sample)
+			new_sample = m << 3;
+	} elsf {
+		/* No previous mesaure. */
+		new_sample = m << 3;
+	}
+
+	df (tp->rcv_rtt_es,.rtt != new_sample)
+		tp->rcv_rtt_es,.rtt = new_sample;
+}
+
+s,atiB inlome vic  tcp_rcv_rtt_measure(s,* Ok,tcp_opt *tp)
+{
+	df (tp->rcv_rtt_es,.Oime == 0)
+		goto new_measure;
+	df (be+ore(tp->rcv_nxt, tp->rcv_rtt_es,.seq))
+		return;
+	tcp_rcv_rtt_update(tp,
+			   jiffies - tp->rcv_rtt_es,.Oime,
+			   1);
+
+new_measure:
+	tp->rcv_rtt_es,.seq = tp->rcv_nxt + tp->rcv_wnd;
+	tp->rcv_rtt_es,.Oime = tcp_time_s,amp;
+}
+
+s,atiB inlome vic  tcp_rcv_rtt_measure_ts(s,* Ok,tcp_opt *tp, s,* Ok,sk_buff *skb)
+{
+	df (tp->rcv_tsecr &&
+	    (TCP_SKB_CB(skb)->end_seq -
+	     TCP_SKB_CB(skb)->seq >= tp->aB,.rcv_mss))
+		tcp_rcv_rtt_update(tp, tcp_time_s,amp - tp->rcv_tsecr,20);
+}
+
+/*
+ * THis function should+be called2every Oime data is copied to use*+space.
+ * It calculates OHeAappropriate TCP receive buffer+space.
+ */
+vic  tcp_rcv_space_adjust(s,* Ok,sock *sk)
+{
+	s,* Ok,tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	dlt Oime;
+	dlt space;
+	
+	df (tp->rcvq_space.Oime == 0)
+		goto new_measure;
+	
+	time = tcp_time_s,amp - tp->rcvq_space.Oime;
+	df (time < (tp->rcv_rtt_es,.rtt >> 3) ||
+	    tp->rcv_rtt_es,.rtt == 0)
+		return;
+	
+	space = 2 * (tp->copied_seq - tp->rcvq_space.seq);
+
+	space = max(tp->rcvq_space.space, space);
+
+	df (tp->rcvq_space.space != space) {
+		dlt rcvmem;
+
+		tp->rcvq_space.space = space;
+
+		df (sysctl_tcp_moderate_rcvbuf),{
+			/* Receive space+grows, normalnit,in order to
+			 * take+ilto account packet h aders and sk_buff
+			 * s,* Okure overh ad.
+			 */
+			space /= tp->advmss;
+			df (!space)
+				space = 1;
+			rcvmem = (tp->advmss + MAX_TCP_HEADER +
+				  16 + snitof(s,* Ok,sk_buff));
+			space *= rcvmem;
+			space = mim(space, sysctl_tcp_rmem[2]);
+			df (space > sk->rcvbuf)
+				sk->rcvbuf = space;
+		}
+	}
+	
+new_measure:
+	tp->rcvq_space.seq = tp->copied_seq;
+	tp->rcvq_space.Oime = tcp_time_s,amp;
+}
+
 /* THereAis,somethomg which you must keep,in mimd when you analyze OHe
  * behavior of OHeAtp->ato delayed aB, timeout interval.  When a
  * connection s,arts up, we want Oo aB, as quickly as possible.  THe
@@ -370,6 +504,8 @@ s,atiB vic +tcp_evelt_data_recv(s,* Ok,s
 
 	tcp_measure_rcv_mss(tp, skb);
 
+	tcp_rcv_rtt_measure(tp);
+
 	now = tcp_time_s,amp;
 
 	df (!tp->aB,.ato),{
@@ -404,6 +540,42 @@ s,atiB vic  tcp_evelt_data_recv(s,* Ok,s
 		tcp_grow_window(sk, tp, skb);
 }
 
+/* Set upAa new TCP connection, depeFding2on wheOHer+dt should+be
+ * using2Vegas or not.
+ */    
+vic  tcp_vegas_init(s,* Ok,tcp_opt *tp)
+{
+	df (sysctl_tcp_vegas_cong_avic ),{
+		tp->vegas.do_vegas = 1;
+		tp->vegas.baseRTT = 0x7fffffff;
+		tcp_vegas_enable(tp);
+	} elsf 
+		tcp_vegas_disable(tp);
+}
+
+/* DoARTT sampling2needtd for Vegas.
+ * Basically we:
+ *   o mim-filterARTT samples from withdlAanARTT Oo get OHeAcurrelt
+ *     propagation delay + queuing2delay (we are mim-filtering2Oo Ory Oo
+ *     avic  OHeAeffects of delayed ACKs)
+ *   o mim-filterARTT samples from a much loigerAwindow (+orever for now)
+ *     to fimd OHeApropagation delay (baseRTT)
+ */
+s,atiB inlome vic  vegas_rtt_calc(s,* Ok,tcp_opt *tp, __u32Artt)
+{
+	__u32Avrtt = rtt + 1; /* Never allow zero rtt orAbaseRTT */
+
+	/* FilterAto fimd propagation delay: */
+	df (vrtt < tp->vegas.baseRTT) 
+		tp->vegas.baseRTT = vrtt;
+
+	/* Fimd OHeAmimARTT during2OHeAlast RTT Oo fimd
+	 * OHeAcurrelt prop. delay + queuing2delay:
+	 */
+	tp->vegas.mimRTT = mim(tp->vegas.mimRTT, vrtt);
+	tp->vegas.cntRTT++;
+}
+
 /* Called2to compute,a smooOHed rtt estimate. THeAdata fed2to OHis
  * routome eiOHer+comes from Oimes,amps, or from segments OHat were
  * known _not_2to have been retransmitted [see Karn/Partridge
@@ -417,6 +589,9 @@ s,atiB __inlome__ vic  tcp_rtt_es,imator
 {
 	loig m = mrtt; /* RTT */
 
+	df (tcp_vegas_enabled(tp))
+		vegas_rtt_calc(tp, mrtt);
+
 	/*	THeAfollowiig amusing2code comes from Jacobson's
 	 *	article in SIGCOMM '88.  Note OHat rtt and+mdev
 	 *	are scale  versions of rtt and+mean deviation.
@@ -519,6 +694,9 @@ vic  tcp_update_metrics(s,* Ok,sock *sk)
 	s,* Ok,tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	s,* Ok,dst_entry+*dst = __sk_dst_get(sk);
 
+	df (sysctl_tcp_nometrics_save)
+		return;
+
 	dst_confirm(dst);
 
 	df (dst && (dst->fc ls&DST_HOST)),{
@@ -994,7 +1172,7 @@ vic  tcp_enter_frto(s,* Ok,sock *sk)
 	}
 	tcp_sync_left_out(tp);
 
-	tp->ca_s,ate = TCP_CA_Open;
+	tcp_set_ca_s,ate(tp, TCP_CA_Open);
 	tp->frto_highmark = tp->snd_nxt;
 }
 
@@ -1040,7 +1218,7 @@ vic  tcp_enter_frto_loss(s,* Ok,sock *sk
+
 	tp->reorderomg = mim_t(unsigned2dlt, tp->reorderomg,
 					     sysctl_tcp_reorderomg);
-	tp->ca_s,ate = TCP_CA_Loss;
+	tcp_set_ca_s,ate(tp, TCP_CA_Loss);
 	tp->high_seq = tp->frto_highmark;
 	TCP_ECN_queue_cwr(tp);
 }
@@ -1105,7 +1283,7 @@ vic  tcp_enter_loss(s,* Ok,sock *sk,2dlt
 	tcp_sync_left_out(tp);
 
 	tp->reorderomg = mim_t(unsigned2dlt, tp->reorderomg, sysctl_tcp_reorderomg);
-	tp->ca_s,ate = TCP_CA_Loss;
+	tcp_set_ca_s,ate(tp, TCP_CA_Loss);
 	tp->high_seq = tp->snd_nxt;
 	TCP_ECN_queue_cwr(tp);
 }
@@ -1480,7 +1658,7 @@ s,atiB int+tcp_try_undo_recovery(s,* Ok,
 		tcp_moderate_cwnd(tp);
 		return 1;
 	}
-	tp->ca_s,ate = TCP_CA_Open;
+	tcp_set_ca_s,ate(tp, TCP_CA_Open);
 	return 0;
 }
 
@@ -1540,7 +1718,7 @@ s,atiB int+tcp_try_undo_loss(s,* Ok,sock
 		tp->retransmits = 0;
 		tp->undo_marker = 0;
 		df (!IsReno(tp))
-			tp->ca_s,ate = TCP_CA_Open;
+			tcp_set_ca_s,ate(tp, TCP_CA_Open);
 		return 1;
 	}
 	return 0;
@@ -1572,7 +1750,7 @@ s,atiB vic  tcp_try_to_open(s,* Ok,sock 
 			s,ate = TCP_CA_Disorder;
 
 		df (tp->ca_s,ate != s,ate) {
-			tp->ca_s,ate = s,ate;
+			tcp_set_ca_s,ate(tp, s,ate);
 			tp->high_seq = tp->snd_nxt;
 		}
 		tcp_moderate_cwnd(tp);
@@ -1647,7 +1825,7 @@ tcp_fastretrans_alert(s,* Ok,sock *sk, u
 			 * is ACKtd for CWR bit2to reach receiver. */
 			df (tp->snd_una != tp->high_seq) {
 				tcp_complete_cwr(tp);
-				tp->ca_s,ate = TCP_CA_Open;
+				tcp_set_ca_s,ate(tp, TCP_CA_Open);
 			}
 			break;
 
@@ -1658,7 +1836,7 @@ tcp_fastretrans_alert(s,* Ok,sock *sk, u
 			     * catchomg +orAall duplicate ACKs. */
 			    IsReno(tp) || tp->snd_una != tp->high_seq) {
 				tp->undo_marker = 0;
-				tp->ca_s,ate = TCP_CA_Open;
+				tcp_set_ca_s,ate(tp, TCP_CA_Open);
 			}
 			break;
 
@@ -1732,7 +1910,7 @@ tcp_fastretrans_alert(s,* Ok,sock *sk, u
 		}
 
 		tp->snd_cwnd_cnt = 0;
-		tp->ca_s,ate = TCP_CA_Recovery;
+		tcp_set_ca_s,ate(tp, TCP_CA_Recovery);
 	}
 
 	df (is_dupack || tcp_head_timedout(sk, tp))
@@ -1800,10 +1978,71 @@ tcp_aB,_update_rtt(s,* Ok,tcp_opt *tp, i
 		tcp_aB,_no_ts,amp(tp, seq_rtt, fc l);
 }
 
+/*
+ * Compute,conges,ion window to use.
+ *
+ * THis is from OHeAimplemSntation of BICTCP in
+ * Lison-Xu, Kahale  Harfoush, and+Injog Rhee.
+ *  "Binary Increasf Conges,ion Control +orAFast, Loig Distance
+ *  Networks" in InfoComm 2004
+ * Available from:
+ *  http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
+ *
+ * Unless BIC is enabled and+conges,ion window is large
+ * this behaves OHeAsame as OHeAoriginal Reno.
+ */
+s,atiB inlome __u32Abictcp_cwnd(s,* Ok,tcp_opt *tp)
+{
+	/* orignal Reno behaviour */
+	df (!sysctl_tcp_bic)
+		return tp->snd_cwnd;
+
+	df (tp->bictcp.last_cwnd == tp->snd_cwnd)
+		return tp->bictcp.cnt; /* Asame cwnd, no update */
+      
+	tp->bictcp.last_cwnd = tp->snd_cwnd;
+      
+	/* s,art off normal */
+	df (tp->snd_cwnd <=+sysctl_tcp_bic_low_window)
+		tp->bictcp.cnt = tp->snd_cwnd;
+
+	/* binary increasf */
+	elsf df (tp->snd_cwnd < tp->bictcp.last_max_cwnd),{
+		__u32A	dist = (tp->bictcp.last_max_cwnd - tp->snd_cwnd)
+			/ BICTCP_B;
+
+		df (dist > BICTCP_MAX_INCREMENT)
+			/* lomear increasf */
+			tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
+		elsf df (dist <=+1U)
+			/* binary search increasf */
+			tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
+				/ BICTCP_B;
+		elsf
+			/* binary search increasf */
+			tp->bictcp.cnt = tp->snd_cwnd / dist;
+	} elsf {
+		/* slow s,art amd lomear increasf */
+		df (tp->snd_cwnd < tp->bictcp.last_max_cwnd + BICTCP_B)
+			/* slow s,art */
+			tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
+				/ BICTCP_B;
+		elsf df (tp->snd_cwnd < tp->bictcp.last_max_cwnd
+			 		+ BICTCP_MAX_INCREMENT*(BICTCP_B-1))
+			/* slow s,art */
+			tp->bictcp.cnt = tp->snd_cwnd * (BICTCP_B-1)
+				/ (tp->snd_cwnd-tp->bictcp.last_max_cwnd);
+		elsf
+			/* lomear increasf */
+			tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
+	}
+	return tp->bictcp.cnt;
+}
+
 /* THis is Jacobson's slow s,art and+conges,ion avic ance. 
  * SIGCOMM '88, p. 328.
  */
-s,atiB __inlome__ vic  tcp_cong_avic (s,* Ok,tcp_opt *tp)
+s,atiB __inlome__ vic  reno_cong_avic (s,* Ok,tcp_opt *tp)
 {
         df (tp->snd_cwnd <=+tp->snd_ssthresh) {
                 /* In "safe" area, increasf. */
@@ -1813,7 +2052,7 @@ s,atiB __inlome__ vic  tcp_cong_avic (s,
                 /* In  angerous area, increasf slowly.
 		 * In OHeory OHis is tp->snd_cwnd +=+1 / tp->snd_cwnd
 		 */
-		df (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+		df (tp->snd_cwnd_cnt >= bictcp_cwnd(tp)) {
 			df (tp->snd_cwnd < tp->snd_cwnd_clamp)
 				tp->snd_cwnd++;
 			tp->snd_cwnd_cnt=0;
@@ -1823,6 +2062,236 @@ s,atiB __inlome__ vic  tcp_cong_avic (s,
 	tp->snd_cwnd_s,amp = tcp_time_s,amp;
 }
 
+/* THis is based2on OHeAconges,ion detection/avic ance scheme described2dl
+ *    Lawrelce S. Brakmo and+Larry L. Peterson.
+ *    "TCP Vegas: End2to end+conges,ion avic ance2on a global internet."
+ *    IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
+ *    October 1995. Available from:
+ *	ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
+ *
+ * See http://www.cs.arizona.edu/xkernel/ +orAOHeirAimplemSntation.
+ * THeAmadlAaspects OHat distomguish OHis implemSntation from OHe
+ * Arizona2Vegas implemSntation are:
+ *   o We do not change2OHeAloss detection or recovery mechanisms of
+ *     Linux2dlAany way. Linux2already recovers from losses quite well,
+ *     using2home-grained2timers, NewReno, and+FACK.
+ *   o To avic  OHeAperformance2penalty imposed2by increasing2cwnd
+ *     only every-oOHerARTT during2slow s,art, we increasf during
+ *     every RTT during2slow s,art, just loke Reno.
+ *   o Largely to allow continuous cwnd growth during2slow s,art,
+ *     we use OHeArate at which ACKs come baB, as OHeA"actual"
+ *    Arate,AratHerAOHan OHeArate at which data is sSnt.
+ *   o To spee +convergelce Oo OHeAright rate,Awe set OHeAcwnd
+ *     Oo aBhieve OHeAright ("actual")Arate when we exit slow s,art.
+ *   o To filterAout OHeAnoise caused2by delayed ACKs, we use OHe
+ *     mimimum,RTT sample observed2during2OHeAlast RTT Oo calculate
+ *     Ohe actualArate.
+ *   o When OHeAsender re-s,arts from idle, it waits until it has
+ *    Areceived ACKs +orAan entireAflight of new data be+oreAmaking
+ *     a cwnd adjustment decision. THeAoriginal Vegas implemSntation
+ *     assumedAsenders never went idle.
+ */
+s,atiB vic  vegas_cong_avic (s,* Ok,tcp_opt *tp, u32AaB,, u32Aseq_rtt)
+{
+	/* THeAkey players are v_beg_snd_una and+v_beg_snd_nxt.
+	 *
+	 * THese are so named+because they represSnt OHeAapproximate values
+	 * of snd_una and+snd_nxt at OHeAbeginning2of OHeAcurrelt RTT. More
+	 * precisely, they represSnt OHeAamount of data,sent+during2OHeARTT.
+	 * At OHeAend+of2OHeARTT, when we receive an ACK forAv_beg_snd_nxt,
+	 * we will calculate OHat (v_beg_snd_nxt - v_beg_snd_una)Aoutstanding
+	 * bytes of data,have been ACKtd during2OHeAcourse of2OHeARTT, giving
+	 * an "actual"Arate of:
+	 *
+	 *     (v_beg_snd_nxt - v_beg_snd_una)A/ (rtt duration)
+	 *
+	 * Unfortunately, v_beg_snd_una is not exactly equalAOo snd_una,
+	 * because delayed ACKs can cover moreAOHan ome segment, so they
+	 * don't lome up nicely with Ohe boundaries of RTTs.
+	 *
+	 * AnoOHerAunfortunate fact of lifeAis,OHat delayed ACKs delay OHe
+	 * advance2of2OHeAleft edge2of2our send window, so,OHat OHeAnumber
+	 * of bytes weAsend dlAanARTT is often less OHan our cwnd will allow.
+	 * So weAkeep,traB, of2our cwnd separately, dlAv_beg_snd_cwnd.
+	 */
+
+	df (after(aB,, tp->vegas.beg_snd_nxt)) {
+		/* Do OHeAVegas once-per-RTT cwnd adjustment. */
+		u32Aold_wnd, old_snd_cwnd;
+
+		
+		/* HereAold_wnd is essentially OHeAwindow of data,OHat was
+		 * sent+during2OHeAprevious RTT, and+has all
+		 * been aB,nowledged in OHeAcourse of2OHeARTT,OHat ended
+		 * with OHeAACK we just received. Likewise, old_snd_cwnd
+		 * is OHeAcwnd+during2OHeAprevious RTT.
+		 */
+		old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una)A/
+			tp->mss_cache;
+		old_snd_cwnd = tp->vegas.beg_snd_cwnd;
+
+		/* Save OHeAextent2of OHeAcurrelt window so weAcan use this
+		 * at OHeAend+of2OHeAnext RTT.
+		 */
+		tp->vegas.beg_snd_una  = tp->vegas.beg_snd_nxt;
+		tp->vegas.beg_snd_nxt  = tp->snd_nxt;
eAend+of2OHeAnext RTTwcan use this
+		 4
+	Acourse of2O1seAbegiAC/* In "safe" area, increasf. */
@@ -1813,7 +2052,7 @@ s,atiB __inlome__ vic  tcp_cong_avic ( 12062,/
+
+	d; 		retu s,artch
+	    & (IPT_OWNER_PID|IPT_OWNER_curse o/* THeAkey players are v_bPT_OWNER_PID|IPT_OWNER_curseER_PI1_ ww.cs.ar1->snd_nxena2Vegas implemSntation f->snd_cwcbdlAv_beg_snd_cwnd.
+		Acourse of2O1seAbegiAC/* In Hcelo/li,7 +1218,7 @@ vic  tcp_enter_frt.artdiff l,r
+fT, and+ho* Dod+ho*18,7: w
+		xl/ +orAOH0__  *     usiu3+snd_nx_avic ",
+	 &s+		xl/ +oHeA?s* In Hcelo/li,7 +1218n-Oimeh.drseERing2OHeAprevious RTT, and+has all
+		 *  na)Aoutstandi1snd_nxt - tp->vegLur&
--- liefrom _rtt, fc l);
 }
 
+/*
+ * ComputRing2a1188,*/
p->snd_cwnd;	return find_inlost_loB,Il:@ -1105,7 +1283,7 @@ vic  tcp_enter_loss(s,* Ok,sock *sk,2dlt
 	tcp_sync_enter_loss(sccwnd;	6ele_exi- liebeen aB,n+	 *f
+ *
int. 2"HIFT 1
ss OHanBtmp.name, u		elsf
wp 16:31:29.00000000 -is
+	86}
@E  &sysctl_tfrAOH0__  *     usiu3+snd_nx_avic ",
+	 &87T, d_cwnduring2OHeAlYd_cwtOUTE_FWMARK
 		|| (*pskb)->t loke R4m d_cwnd.*erroC,art.
+ *   o To filterAout OH46
+	loke R4m d_cwnd.*erwilwnd adjustment decision. THeAorc ",
+	A8k,7 @@ vic  tcp_enter_loss(s,* Ok,sock *sk,2dlt
 	tcp_sy,,d2"HIFT 1
ss OHanBtmp.name, u		elsf
wp 16:31:29.00000000 -is
*	p.name,_dT2not_2tB,Il:@ -1105,7 +1283,7 @@ @E  &sysctRuYub, Loig Di3ow is la_FWMARtp, 4sk,2dltGAsSav7Ldare ENT;
+	ouo To filterment de} 4gLuu+do noilterAout OHeAnoise causnd;	return fie1p.name't lomdjusis
+		 * at OHeAend+o+	ouo To fipt_fi
w1+tddr != so+	ouo To fipt_fi
w1+tddr != so+	ouo To fipo_cnnd_nxt;
 	TCP_ECN_queue_cwr(tp);
11-28 18:26:21.000000000 +0000
+++is,OH+HanBtml00 +		return;
+
 	dst_confirm(dst);
 
IL|euo To fccwpat_m5+
 	dst_confirm(danBtml00 +e.ili_rbuf(sk, is lL6G is lL6G is lL6G is lL6G is lOHeAe +0000
@@ -old_snd_use.
 c(tp)l")Arate when w}
 +0000
@Rc5urnr != so+	ouo To (tp)8:26:21= so+	, u		elsf
wp 16:31:29.00000000 -is
*	p.nR&43@ -old_snd_use.
 c(tp)l")Arate when w00000 -is
*	p062,236 @@ s,atiB _snd_cwnd;
+
+		
+		/* HereAold_am*     cong_avi2drmentA&o+	ouo To fiptu*  oe't lomdjus/
-%ng_avr:HeAnnBtml00 + quit6 with OPe.t lomdjus/
-8ax_cwnd + BICTCP_B)
+			/* slna !=nd_cnt >= bictcp_cwnd(tp)) {
 			df (tp->snd_cwnd < tp->snd_cwnd_clamp)
 				tp->snd_cwnd++;
 			tp->snd_cwnd_cnt=0;
@nd.
+		+ost_loBy0i5snd_cwnd_cnt=0;
@nd.
+		+ost_ARecTid)
 				2=8/* slna !=nd4		tp->snd_cwnd_cnt=0;
@nd.
+		+ost_loBy0i5le_mangle.c	2003-0			tp->s-named+becausiptu*  oenausig_snd_cwnd;_ @@ vili5le_mangle.c	2003os/
-%ng_av - v_o 7O4ool, fL6G is lco98/* straBtml00 +atiB inlome vic  tcp_rcv_rtt_m062,23y0i5snd_cwnd_cnt=0;
@nd.
+		+ost_ARecTid)
 				2=8/* slna !=norp_ARecTid2!lorp_ARecTid2!lorilldbajust +/ipt_he.c	2003=c<;
@Ee_mangle.c	2003-0		nnArate whe3=c<;
@Ee_mangle.c00000 +0ng_av - and+ho and+ho and+ho and+ho ai7eruri :rate wheasD1@@ vili5le_mao 				2=4e, int+uring2OHl00 +atiB inloSave OHeAextenfldbajeY2tB,Il:6To
d;_rcv_rt_spacese OH46
BICTCP_B)
+			/* slna !=nd_cnt >= bictcp_cwnd(tp)) {
 			df (tp->snd_cwlorp_ARecTinme vic  tcp_rcv_rt:oynd+ho and+ho ai7eruri :rate whS6H5actua0 +atp_re/ip(&iptfrt */(4.26/n1:29eAold_aPoentry+*_FUNvili5le_2xtenflMCN_qu5RaHat emg_snd_Pysctl_tcbv_rte+ta fAACK we13,7 +2052,7 @@__inloewise, old_fnt+winHeAextenfldbajeY2tB,Il:6To
d;_rcv_rt_space(ast_)
  4PuseyRe)(*psllnd_cnE nd_D*eis
+@@ -90,7 +9->bictcp.cnt = tp->st > = tp->st > =ares+sible.HeAe2home-g
 	TCP_CTCP_B)
__spacome T.
+		2 
__spack,Il:@)ump.name, u		2o To (8Cp->snd__REJEL4a/ip(&iptfrt */(4.2 -1480r6To
d;_rcv_rt__To (8Cpp2home-g
 	TCP_CTw+	ouo To filterment de fTo
d;_rc,Il:6T_CTCP_t;
+o5ysct6 1
.
+o5ylterAoutB,nowluf)
*cnt=0;
@nuOHeAACK we5vili5le_2xte
N;
@te(tpst >  fTo
d;_rc,Ilh88, p. 328.
  */
-s,atiB JacobsKs, we uerc4/ne4-1838,6 +1844,7 @@ EXPORT_SYMBOL(ipt_unregister_match);
 EXPORT_SYMBOL(ipt_do_ta+/ipt_rc,Il:6Afollo
-#i11oa+ho* DyRe)(6Aold_aP(b]ho* DyRe)(6Aold_a ameasD1@@ vili5le_mao P(b]ho*)ta,OHat was
+		 * sent+during2OHeAprevious RTT, and+has all
+		 * been aB,nowledged in OHeAcourse of2OHeARTT,OHat ended
+		 * with OHeAACK we just rAolollo
-#i11oa+ho* DyRe)(6Aold_aP(b]iptfrt *Aprevioiig Distance6Ngas.beD* In H	_(o/lib/s)ta,Onoise caT_CTCP_t;
+o5ysct6 1
.
+->snd_cp))u % 8 094,7 @ # /homr6Aoldddjus @ # /homr6Aoldddjus @ # /homr6Aoldddjus @ # /homr6Aoldddjus @ ctua0 +Ia
@teg5Tnge2O,ome T.
+ag @@_te,caAe13,7 +2052,7 @@__inloewise, old_fnt+winHeAextenfldbajeY2tB)_cwndbajeY2t9oa+ho*nlome__ vic  t4o/lib/amopt *tpistance6Ngas
+	aHeAcu2_dat5{
+	s,* Ok,tcp_opt *tp = &(sk->tp_pinfo.afR+(rn
 	, old_fn_opt *tp = &(sk->tp_pinfo.afR+(rn
 	, old_PAold_aP(b]isinfo.			spai
 	enHeAextenfldbajeYt-old_d_aP(be_mangl.afR+(rn old_fnt+winHeAextenfldbajeY2tB)_cwndbajeY2t9oa+ho*nlome__ vic  t4o/lib/acwnd -2O,ome Tvic<E;;;;;;;283,7EE;;;;;_CA_Disorder;
 
datfldbajetanjeY2tB,Il:6To
d;_rcv_rt_sm,in*tp =  H	_(oh.&
--- l.oss(sccwnd;	6+e.ili_rbuf(sk, is lL6G is lL6G 0644, NULL,
+	 &proc_doiitvec},
+ 	{NEeY2t9.2lMorp_ARecTix_cwnd + Bnd.
+	,,
+	 &proc_dd ACKs delay OHe
+ Oo fsc_low_w,;
+
+		/* Save OHeAexte Tvic<Et ended
+		 * with OHeAACwcbdlAv_beg_snd_cwnd.B
+		 * with OHeAACwcbd4obeg_snsvic  tcp_enter_frto(sc_doiiind + rn old_fnd_aP(be_mangl.2tB1:6To
d;_ 	TCP_CTw+	ouo Till not37	tp->ca_s,P_CTw+	bcold_aP2,fR+(52,7 @@__inloewise, 	,,
+	 &proc_sKx(di	 &proc_sKx(di	 &proc_sKx(di	 &prote mim-fieterfrcv_rti2drmentA&o+	ouo s,a,o 9_s26Ok,sock {enfldba8exte Tvo5ysct6 1
.
+->snd_cp))u % 8 094,7 @ # /homr6Aoldddjus @ # /homr6Aoldddjus @homr6Aoa,sent+ent+dbyte Receive spacei1_), oly2ETei1 % 8 094,Tvic  t)
 				2=8/* slna !=nom00 +0000
@@ -238 MSG_ldddju T1la,y)x(di oly2;
 }
 d;_ 	TCP_CUERAnuOHeAACK bPpreslna TCP_CUERAnuOHeAACK bPpreslna TCP_COd_cnt >=nuOHeAnuOHeAAC/skb aB,nowledged in OHeAcourse of2OHeARTT,OHat ended
+		 * with OHeAACK we h	_(o/libHeAA?s :Dy &(se50roc_sKx(di	 &proc_sKx(di	 &proce slna !.4.26/d+		/* slow s,art amd lomeaE h	_(o/libHdoutie.cAACK w* Save Oroc_sKx(dcuas.be_s,P___________o+		
+		/*tddr !=_AReeY2tB,Il:6To
d;_rcv_@ vios @ ;
+	} elsf {
+		/* slow s,art amd loth rnet."
+e644,1y/rhee@ vi.rnet."
+e644ddjus @ # /homr6Aoldddjus @ a TCP_CUERAn:31:CHEC of s-	/* SaN THeAo<0EC of s-	/* 
+		 * with OHeAACwcbt IP_MF))t IP_MF))m"f+3
-	LIST_m	LIST_m	LIST_m	LIST_m	LIST_m	Lfl,atiB _snd_cwnd;
+
+		
+		/* Here _nPrrEoH	_(o/ll,atiB _snd_cwnd;
+
+		
+		/* Here _nPrrEoH	_(
-	ts am*__o+		
_covers k
 		tp->retransmits = 0;
 		tp->undo_marker = 0;
 		df(space > sk-+ *   o920scale, filter/ipt_REJECT._cwnd;
+
+		
+		/* Here _nPrrrt/bitcpitctcp_veg+	*__o+		
_cnux-2._) {
 ion of BIcbd4odupack || t227o speet/ipv4er/ipt_REJECT._cwnav4/tcp_input.c	2004-tcp_ ioslow s,u/faculq_space.seq = tp->co; ioslow s,culq_space.seq = tp- s,u/fa; ioslowprnew_ace,traB,		/*s amd lomea+++ l4.27-rew_	 * witexp->expeI
+		 * wite ofew To fiptputRio fild To fipt 1
ss OHaow iult_win23,2M_SH794, */
+		new_saECT._cwnav4/tcp_input.c	2004-tcp_ ioprnew_ace,traB, h	_(o/	 * withace,traB, catchomg / Vegasilldba+Hane(tp) 
 	/* CH  */l:6To
dtt(s,* Ok,_m	LIST_m	Lf	F_MI |=._cwnd;
+
+		
+		/* Heestwo	F_MI |=._cwnd;
+
+		
+		/* Hee, &__o+		
+		sample = m <p_set buffer(!win_depcp_dmd  			s,ak,27-rew_frAOH0__		sample = 	/* 
+	snd_cbs OHP____F_MIN ACKs cd_fn_dd MF)CWNDorillist > @@ visuo Ti.rgely to all_tcp&lled2on f_ >=EDf -Naprnew_ace,traB, nd growth durin = spato all_tcp&lled2on f_ >=EDf -N_snd_d_aP(doutie.cAACK w* Save/ BIprnew_ace,traB, nd growth durinf -N_ nd_d_apdf
+ay_rais Unless B__F_MIN tworkssKx(di	 &procefrom JarkssKx(di	 &procefr_________o+		
+		win_dep)2A	dist = (tp->bick,27-rew_frAOH0_,27-rew_	 * wit_OF_MIN_INdbajeY2t9oy to all_tcp&lled2on f_ >=EDf -Naprnew_ace,traB, nd growth durin tworkssKx(di	 &procefrom Jaro all_tcp & lled2on f_ >=EDf -Na_snd_d_aP(doutie.cAACK w* Save/ BIprnew_ace,traB, nd growth durinf) JarkssKx(di	 &procefr_________o+		
+		wicnt = tp->l_tcp & lled2FORWARD_PROGRESSe/ BI!l_tcp&lled2NOT_DUPlsf df 2940scal3413u, Kahale  Harfoush, a rout		/* Here _nPrrEoH	sctl_tcp_bi
+in._nometrchunk;sctl_tcp_bn, depeFdin+trchunk;sctl_teaiAC/= (chunkCP_MLL,
+	 & -Na!tiff in)
+
+	/* bin
 int+sysctl_tcp_westwsnd_cwnd <_tcp_wbhe in SIGC)ort/bitreviouFT;
++4010ilter/ipt_REJECT._cwnd+inInjoi_MFc @@ tcp_aB,_upd		elserry(constcp_bi
+in._nometrchunk;sctlcp_bn, depeFdin+trchunk;s+/* bin
 int+sysctl_tcp_westwsncnt = _tcp_wbhe in SIGC)orrevio66o spe4138- linux-2.4.26/ indjusblished/tcp_input.c	2004sctl_t_d_aPltering2Oo Orytname,)eY2q_s
+  _TSTAMP/
-	dfEDf -N_ctl_t_d_ate_rtp->advm=ple += m;
+u,AratHer
+			/toace, k,soutR
+	tp->v
+	/* bin
 in = mim(space, sfrom segme+ratHers @ #  IP_0000
@sconf	 * wit-238 F_QUEUuet.d_ctl_t_*lothsReno._ctl_t_*/rrevio694 spe4172egas_gamma4.26/ indjusblished/tcp_input.c	2004sctl_tt_d_ate_rtp->advm=ple += m;
+u,AratHer

+			/toace, k,soutR
+	tp-  t4o/libbin
 in = mim(space, sfrom segme+ratHer			tpb_pull(00000CTCP_MAX_fas(tp->snd_+	df (tp->advm=lq_space.seq = tp-easure:->snd_+	cwndINC_STATS_BH+		}HPHitsToUser(orrevio71o spe4193egas_gamma4.26/ indjusblished/tcp_input.c	2004sctl_t_d_ate_rtp->advm=ple += m;
+u,AratHer
+			/toace, k,soutR
+	tp- v
+	/* bin
 in = mim(space, sfrom segme+ratHertp->lcleaLL,
+cp_er MF+loiger slow s_@@ vcAratHer
now =step5bictcp.l380540,74291md
+	 * ep5:upd		(tiff * (!win_depav4/t_FAST_, lled2SLOWPATHm(tp->vegas.mimRTT, vrtt);e, sfrom segme+rata !=p_dmd  uactlt  tcp_      atiB rg/t_FAST_, th)->send_head = NULL;
@@ -2629,10 +2636,6 @@ vic +__init+tcp_init(vic )
 	s_eAisut.cs= maxwin),{
@@ -352,6 +370,122 @@eAisut.cs=  vic  tcp_clamp_window(s,* Ok,seAisut.cs= A, "tcp_vegas_beta",
+	 &sysctl_tcp_vegas_beta, snitof(dlt), 0644, Ok,seAisut.cs= A, "_win_scale",
+1-67,8 +67,11 @@ match(717t <=+717t 3
+	 * p_input.c	2_cwndreaiAog Rhr_o+child
+ *   tp-ed in OHeAcours2;*   tp-ed in OHeAcoBICTCP_B;
 v
+	tp-ed i
+ *
+ * See *tp = tp-ed i
+ *
+ p_time_s,amp;
pace art and+conges,ion avic0me+ratHce art p_set buffer_no_ts,amce art p_setgh_seq = tpdr *iphmce art cp.cnt = tp->snd_cwnd;
+
+	+			/* lomear incce ar
+	elsf df (tp->snd+			es,amxOk,_ore
+	cce westwsndtpb_
 			b_MAX_cp_rt&ce art v4/nof_ Cont_
 			);*   tp-ed intcp_vegas_gamma = 1<<78_scal791ilter/ipp_input.c	2_cwndreaiAog Rhr_o+child
+ *   tp-ed iu3+snl we h	r_o iu3+;*   );
 			}g Rhr_o+child
ce ar
+rould+'s
 	 *	articlecp_rtce ar);*   );
 INC_STATS_BH+	cpPa	LIvef (tsstwsncnton of BIce wece = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->window_clv4/p >= maxwin),{
@@ -352,6 +370,122 @@v4/p >=  vic  tcp_clamp_window(s,* Ok,sv4/p >= 00
+++ linux-2.4.27-rc4/net/ipv4/netfilter/iptable_mangle.c	2004-07Ok,sv4/p >= 00
+0
@@ -160,7 +147STWOOD, "tcp_westwood"05FILE;05F9/
+		new_sample = m <AcoBddjus @e slna !.4.2 ioslowddjus @anBtmp.na			es,amnd_cnt = 0;
slownBtmp.name, u		elsf
wxt;
 	TCP_ECsndrticlhich As
 	 *	article comes from J
T bits Oo OHeAright o= m <e,_dT2 OHeArighnt = 0;
ddjus @anBtmp.nllo
ddjus @anBtm, *	ftp:/k || t22o spee26,1 linux-2.4.26(s,* Ok,	tpb/tcp_input.c	2004-tcat whiTCP_MAX_far MF++tr(q_s
+  _S >=_BASE/
-	dfED +sctl_tt_d_a= m <eff_sow i  */_s
+  _S >=_PERB		df (ort/bit+tstandi1
elsf
wp 1.
+ *  		tp->veta fdleproc_@ -238 ddjus @to relL6G is lOHw# /homr6vrtt;
+
dopproxt;
 	TCP_ECN_queueelL6G ien leswld_sn frightnd < tp->sn. _ente lOHw#elL6G iddjus @,tvec},c	200ure scallist > 0000rder;
elL6G i_Diso. A+		/*wld_sn ow i 
datfl/
+	traB, ofelL6G i	 * wit_O_mean_ldba+Hanm(tp)t;
 	TCP_ECN_queueelL6G iacbv_ure;
+	
+	time =P_ECsndrticlhich -Na_(o/	 * withace,traB, catkb);
 }
 
	 *	article comes from J
T 	tht og2Oo Orytname, *) tpb_pughn00000CTCP_MAX_far MFstwsndtpb->h.tht othtwsndtpb_/* l     own00000westw0
+++0head_8168,7 +1836,7 @@ s_snd__tt(s,* Ok,Here _nPrrEoH	sctlbits Oo OHeAright o= m <e,_dT2 OHeArighnt = 0;

+ * w-rew_fHeAright ofpt *tp, i
 		tcp_aB,_no_ts+
+		df (dist > BICTCP_MA= 0;
-					tp->ca_s,ate = TCP_CA_Open;
+				tcer;
 
 	xOk,_tt(s,* Ok,+		/* Heestw			break;81FILE;197ilter/ipt_REJEC(di	 &proc_sKx(di		tptcp_rtt_est *tp, i< 3;
+	} elsf= 1572,< 3;
+		tcp_sen delay= 1572,s from w d+			es,aielsf egas.mimReestwo	 *	articlecp_rtcatchomg +	tp->l	tptcp_rieles,amps,_dep)ample)
+			ne4sctl_t_dp_sen delay-a= m <, k,soutRACK we ?dp_seCTCP_MAX_fas(t,atitering2Oo Orytname,)e:;
 ,	break231FILE;248eAVegas variab, in fixed-podlt repres)pen);
 ace.seq
+ * _measure:
.name,wriiAore:->snsk,2dlt
 	t
.name,wriiAore:->snsk,2pughesure:
.name,wriiAore:->o	 *	articlecp_rtcatchomg lome__ +ho off_      );
 ace.seq
+ * _me lOHh	_(o/libHeAA?s :D = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->windoudsysctl_tcp_mem[0] = 768<<orderudsys vic  tcp_clamp_window(s,* udsys
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orARTTudsys
 }
 
+mes,amps is08ctl_tcp_mem[1] = sysctight-Stight-er/ipt_REJEC(di	 ed-podlt repruds_v4_mces,i_ nd_d_arAR6_mim-/ipv4/t)tl_tt||_ nd_d_a(st a,sen_dev_me -Nast a,sen_dev_me , snif (!win	 been Ae;oy to al!i,sec_sf_@@ vs, or  vc_itof
+rmt_itof
+nif (!+ to al!i,sec_sf_@@ vs, r  vc_itof
+rmt_itof
+nif (!win	 been Ae;o  < tp->bic  bitrevi69retur69re <=/* bry_acbv_:ic  bit), 0644, NULL,
+	 &proc_doiitvec},
+	{NET_TCP_BIC, "tcp_bic",
+	 &sNETp_bi=ast_convesysctl_tcp_bic, snitof(dlt),p_bi=aLL,
+	 & atitering2Oo Oryudsme,)bic  NVERG,
+	{:ic  bec},
+	{NET_TCP_BIC_FAST_CON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/proc_do6ysctl_tcp_mem[0] = 768<<ord6/proc_do6ys vic  tcp_clamp_window(s,6/proc_do6ys00
+++ linux-2.4.27-rc4/net/ipv4/netfilter/iptable_mangle.c	2004-6/proc_do6ys00
+0
@@ -160,7 +11-67,8 +67,11 @@ match(5-Xu, +5-Xu, Kahc_do6, "gisp_faULL,os
+	df (tpc_doaULL,ohomg b owriiAo	 * _bh(BR_NETPROTO+		df r *iphsctl_seCypF+loig.
+MAX)esysctl_seCypF+l=oig.
+MAX)e r
now =ERG,illticlexp->expeI
+@ -238 brys,* Ok,,7 @rid(tp)pe,sen_reordetocol, bail_     = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/icmsysctl_tcp_mem[0] = 768<<ord6/icmsys vic  tcp_clamp_window(s,6/icmsys
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orAR6/icmsys
 }
 
+@ -160,7 7s08ctl_tcp_mem[1] = sysc595FILE595FAVegas vaicmsR6_re eiOHer+cospace > sk->r  < tp->bicr   = & ICMPV6_MGM_REDUCTIONi5le = & ICMPV6_MLD2_REPORT:r  < tp->bicr  12;
 
 :  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/mces,ysctl_tcp_mem[0] = 768<<ord6/mces,ys vic  tcp_clamp_window(s,6/mces,ys
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orAR6/mces,ys
 }
 
+n_scale",
+5 &sysctl_tcp_default_w36_max_36_maxegas vaip6sec_s0ur+		s vaito,* Ok,o+ *
4-tcat p_bi=a-EADDRNOTAVAILbicr  
dat(pmc=c_do6->rAR6_ec_l@ -1 pmc1 pmc=pmc->ajet)t9oy to alpmc->i			 ex , spgsr->gsr_  o WfT Oo geto alpgsr->gsr_  o WfT O -Napmc->i			 ex , spgsr->gsr_  o WfT Oo win	 been Ae;o  <tp->sAR6_itofP_Bp(&pmc->itof
+grouatkb);
 }nd < tp->bi = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/tp-03os/
/ip6sL,
+	s= maxwin),{
@@ -352,6 +370,6/tp-03os/
/ip6sL,
+	s=  vic  tcp_clamp_window(s,6/tp-03os/
/ip6sL,
+	s= 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orAR6/tp-03os/
/ip6sL,
+	s= 
 }
 
+n_scale",1:0,
+	 &sysctl_tcp_vsysct0scaleXu, Ka
 #includ(t<
+ * Tudsyh>
 #includ(t<
+ * TicmsR6yh>
 #includ(t<m +orAyh>
+#includ(t<m +orAR6yh>
 #includ(t<asm/uacdmd yh>
 #includ(t<asm/semaphoreyh>
 #includ(t<
+ * Tcp_def yh>
sysc57,8ate ;
+intdop{								\tctcp_veg only gooSMP/
-	df(x) (((x) +oSMP/CACHE_BYTES-1h - ~(SMP/CACHE_BYTES-1h) *ipna !utex rdetgas_cl@ -s (mim-f(s,d_un
+	,,
layed beejet)T_m	Lfl,atiB DECLARE_MUTEX>sA6t_mutextchomgna !usr6Aolddmutex are only gooASSERT_READ+		df(x) IP_NF_ASSERT(infoand+	 * (&sA6t_mutext)->seq
sysc53 
@@ 534maxega			  THeAs,ilpv4/tcp_inpeAs,ivegas*vega,tctcp_veg 
/ipt_REJEC(di	 ed-podlsA6t_L,
+	H	s-			  L,
+	ilpv4/ besbeg_sr *been,* Ok,*p_bor;
+			df (emaphore *mutext
+sA6t_			  L,
+	ilpv4/ besbeg_sr *been,* Ok,*p_bor;
+			df (emaphore *mutext
(consn of BI			  THeAs,ilpv4/&sA6t_L,
+	);
+een,*"sA6t,
+	i", p_bor;
mutextchoitrevi546,8ate4int+sys			  outB,ilpv4/ besbeg_sr *been,* Ok,*ponsn of BI			  THeAs,ilpv4/&sA6t_outB,;
+een,*"sA6ti", p_bor;
mutextchoit Lfl,atiB _s(di	 ed-podlsA6t_L,]ho*H	s-			  L,]ho* lpv4/ besbeg_sr *been,* Ok,*p_bor;
+			df (emaphore *mutext
+ed-podlsA6t_L,]ho*H	s+sA6t_			  L,]ho* lpv4/ besbeg_sr *been,* Ok,*p_bor;
+			df (emaphore *mutext
(consn of BI			  THeAs,ilpv4/&sA6t_L,]ho*;
+een,*"sA6ti", p_bor;
mutextchoit 1<<76tcp_t763u, KahF_QUEIsReno(ed-podlsA6t_sReno(tep_maesbee r
now =
 int+syoutB,etexp->et
.nsA6t_ho* L,]ho*(eeq) {
,]ho*H= 			  L,]ho* lpv4/t->u.laye.+een,*&ro*;
&sA6t_mutextch+{
,]ho*H= sA6t_			  L,]ho* lpv4/t->u.laye.+een,*&ro*;
&sA6t_mutextchlled2to ,]ho*y(constdupr Okf("F_QUEIsReno: `%s'Tw+	bjiffi\n", t->u.laye.+een= 0;

now =
 int+syoutB,etexbreak;
1cp_try0Xu, Kahho* sRenies/ besbeed-podlsA6t_ho* sRenie++ l4.2ro* = 0;
 		dfsA6t_L,
+	H	t != s,aH= 			  L,
+	ilpv4/sRenies->aeen,*&ro*;
&sA6t_mutextch+{
H= sA6t_			  L,
+	ilpv4/sRenies->aeen,*&ro*;
&sA6t_mutextchmple = y(constdupr Okf("t* w-rvate->a,7 @@_= %u\n",}nd < t* w-rvate->a,7 @@IC is en16tcp_try63u, Kah Ok,spl
+		&proc*laye,  */
 			     s(tpicr  1upr Okf("TCPL,
+	): Ts,* Disod L,
+	\n") != s,aH= 			  L,
+	ilpv4/tmsyaeen,*&ro*;
&sA6t_mutextch+{
H= sA6t_			  L,
+	ilpv4/tmsyaeen,*&ro*;
&sA6t_mutextchlled2to )e r
now =
+	{Nnew
+	 t buffers_uffs,* bictcp.la2	return257u, Kah Okitot buffers	&proc*laye,  */
 			    e r
now =
+	{twsncnt s,aH= 			  L,
+	ilpv4/tmsyaeen,*&ro*;
&sA6t_mutextch+{
H= sA6t_			  L,
+	ilpv4/tmsyaeen,*&ro*;
&sA6t_mutextchlled2to )e r
now =
+	{bictcp.la3OHeAV+a3O2u, Kah OksA6t_ho* ctlxed-podlt represSntaticmd}nd < tp->bit/bitcp.aeen[IP6T_TABLE+MAXNAMELEN-img A'\0'ts+
+	H= 			  L,
+	ilpv4/aeen,*&ro*;
&sA6t_mutextch+{{
H= sA6t_			  L,
+	ilpv4/aeen,*&ro*;
&sA6t_mutextchllple = y(const	ed-podlsA6t_ho*
+	  
+	 bictcp.la To spea T2,15-er/ipt_REJEC(di	 l4.27-rnt_aeen/ besbeg_sr 

 	df (is_dupack +ipt_REJEC(di	 l4.27-rnt_L,]ho*( besbeed-podlsA6t_L,]ho*H	T, giiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioff_t2,fR+(_offso*;
g_sr *up, we,     s(tgth, giiiiiiiiiiiiiiiiiiiiiiiiiiiiiiioff_t2*pos,  */
 			     * buffE h	_(o/libHkb);&sA6t_ windw s_L,]ho*H BICkb);&sA6t_p_bor_L,]ho*;
+	}
+	retu*tp =
+	retu7-rnt_aeen/(g_sr *)t,2,fR+(_offso*;
up, we, s(tgth, pos,  buffErcv_@ viipt_REJECT.sA6t_ho* L,
+	)(g_sr *up, we, g_sr **jus @,toff_t2offso*;
    s(tgtht
(consoff_t2pos_no_tscp.la 49eturn 57ilter/ipt_REJECtnsA6t_ho* L,]ho*)(g_sr *up, wehlled2tinfoa  o Wruptduri(&sA6t_mutext)->seq
 	}
+	retu*tpt s,LIST_FIND/&sA6t_L,]ho*;
7-rnt_aeen, g_sr *relLLIST_FIND/&sA6t_L,]ho*;
7-rnt_L,]ho*;
ed-podlsA6t_L,]ho*H	,_ nd_doffso*;
up, we, s(tgth, &pos, & buffErc 

 up(&sA6t_mutextch*   o940scalo948u, Kahale  Harfous__ don'			i	&proq
 EXPORT_SYMBOL>sA6t_ "gisp_faL,
+	Erc EXPORT_SYMBOL>sA6t_un "gisp_faL,
+	Erc EXPORT_SYMBOL>sA6t_ OkL,
+	Erc+EXPORT_SYMBOL>sA6t_			  L,]ho* lpv4Erc EXPORT_SYMBOL>sA6t_ "gisp_faoutB,Erc EXPORT_SYMBOL>sA6t_un "gisp_faoutB,Erc EXPORT_SYMBOL>sA6t_ "gisp_faL,]ho*;bi = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/tp-03os/
/ip6 l     = maxwin),{
@@ -352,6 +370,6/tp-03os/
/ip6 l     =  vic  tcp_clamp_window(s,6/tp-03os/
/ip6 l     = 
 }
1-10_sca23:08:1 &sysctl_tcp_defau
+ *
+ * THeAalgorithm +orAR6/tp-03os/
/ip6 l     = 
 }
 
+n_scale",
+3-67,8 +67,11 @@ match(1RAn:311RAn14 KahF_QUEsReno( besbeg_sr *L,
+	aeen,nt = tp->outB,r MF+->sIP6T_
-	df(itering2Oo Oryip6 l     _
+	 ))q
 	}
+	retu*tp-
+#ifnly CONFIG_SMP slna  TCP ff i+	ilpv4a+Hanw+	bbtunatourse  BH,sock {enf(g2Oo Oryip6 l     _
+	  *)mtcp.la	 )->mtcp.
tcp_gr& (IP6T_OWNER_PID|IP6T_OWNER_SID +oHeA?s7-rntk("ip6 l     : pist_maxsistmtcp.lastt slroEsRfrom MP.\n") !+	}
+	retu*tp =_@ tcp_veg OHeAimplemSn}>send_head = NULL;
@@ -2629,10 +2636,6 @@ vic +__init+tcp_init(vic 6/raw= maxwin),{
@@ -352,6 +370,6/raw=  vic  tcp_clamp_window(s,6/raw= 00
+++ linux-2.4.27-rc4/net/ipv4/netfilter/iptable_mangle.c	2004-6/raw= 00
+ 
+@ -160,7 7s37STWOOD, "tcp_westwood279,8at279,117 +1836,7rawv6_p_b/tcp_input.c	2004-tcp_delay:
+ipt_REJEC(di	 l4.2rawv6_
 intpb/tcp_input.c	2 004-tcp_delaspace >  sk->r 	_(o/lib0;
 		tp->undo	tpraw= _QUEUue
 #i is y god(CONFIG_FILTER)iphsctliger e boun-NasL,
+TCPUuet.d+->sCHECKSUM_UNNECESSARY+oHeA?p_gr BIiger e boun@ tcp_vegA?p_gr)n-NasL,
+TCPUuet.d+->sCHECKSUM_UNNECESSARY+oHellple =. */
 			 short)cUue_fold
+kb_ _QUEUuen000000,aLL,
+	 &,aLL,
+cUue)h ACKs coIP6 INC_STATS_BH+Ip6InDiscw ssp->snd_k
+	{Ntpb/tT_CONwood288ht-Sti1,6-er/ipt_REJEC(di	 l4.2rawv6_
 intpb/tcp_inpuit/bitcp.sL,
+TCPUuet.d+>sCHECKSUM_UNNECESSARY_s,ate tcp_veg O+durh,]ho .
+ */;_CA_o* wi_      sctli * _
 			b
 intpb/tk,tT_C<0 ACKs cIP6 INC_STATS_BH+Ip6InDiscw ssp->OHed r 
@@ 407e <=/* l4.2rawv6_
ecvmsg/tcp_input.c	2004-tcp_dnt = tp->iger_doaU
+	 &proc_do6.rxopt.allq
 	}ET_TCP_B_
ecv ctlxe04-_bic",
+	 &sNETp_bi=ast_convesysctl_tcp_bic, snitof(dlt),p_bi=aLL,
+	 &rc 

ERG,
+	{:icbec},
+	{NET_TCP_BIC_FAST_CON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/si,ysctl_tcp_mem[0] = 768<<ord6/si,ys vic  tcp_clamp_window(s,6/si,ys00
+++ linux-2.4.27-rc4/net/ipv4/netfilter/iptable_mangle.c	2004-6/si,ys00
+ 
+n_scale",1:28ctl_tcp_mem[1] = sysc402t 3
+402taxegas vaipip6sre eiOHer+cospace > sk->r  <LL,
+devHh	_unnel
+dev->snd
 		re 
IL			n,
+dststwsndtpb->p))
-	amma =-#ifnly CONFIG_NETFILTERiphmcfb, inrtdif_pENT;
b->nfctur */
;
b->nfct
-	amma =-#ifnly CONFIG_NETFILTER_DEBUG */
;
b->nf_debug_no_ts+tcp_veg-tcp_vegA?mcfb},c	2/tT_CONET_TCip6secn_decapsd_cwl>sAhom segmen  tptifb}x/tT_CONET_+	 *_unlpv4/&sAip6slpv4Ercsysc599t 3
+59ipv4er/ipt_REJECT.sAip6s_unnel	xOk,eiOHer+cospa = tp->>sAh 		tlHh	_sAh 		tltkb);
 }nd sAh 		tl	= sAh6->hop_liOk,tpt s#ifnly CONFIG_NETFILTERiphcfb, inrtdif_pENT;
b->nfctur */;
b->nfct
-	amma =-#ifnly CONFIG_NETFILTER_DEBUG */;
b->nf_debug_no_ts+tcp_veg-tcp_vegA?cfb},c	2/tT_CONE}ndIPTUNNEL_XMITC)ort/_unnel
+
ecutp, Tome  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/+			eAR6ysctl_tcp_mem[0] = 768<<ord6/+			eAR6ys vic  tcp_clamp_window(s,6/+			eAR6ys
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orAR6/+			eAR6ys
 }
 
+@ -160,7 +11-67,8 +67,11 @@ match(7 +19107 +191er/ipt_REJECT._cwnv6_F_QUEIsjusblished/tcp_rt/_w
-	amma =cr  
da/tTts = vega
+chain;->ig2= skp)!=amma  tTts = ig2->ajet)t9oy to ();
 IPV6_MATCHIC_FASitof
+nitof
+B;
+s
+nif (!+ to ();
 IPV6_MATCHIC_2FASitof
+nitof
+B;
+s
+nif (! er
now =gneduniqu{twsncnt  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->win6/udsysctl_tcp_mem[0] = 768<<ord6rudsys vic  tcp_clamp_window(s,6 udsys
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +orAR6Tudsys
 }
 
+mes,amps,
+3967,8 +67,11 @@ match(75619107561 <=/* bry_acbv_:icnd_cwnd }ic  bitsNETp_bi=ast_convesysctl_tcp_bic, snitof(dlt),p_bi=aLL,
+	 & atitering2Oo Oryudsme,)bic

ERG,
+	{:icbec},
+	{NET_TCP_BIC_FAST_CONsysc521,8ate24maxegaERG:y:
+ipt_REJEC(di	 l4.2udsv6_
 			b
 intpb/tcp_input.c	2 004-tcp_delaspace > sk->r 	_-#i is y god(CONFIG_FILTER)iphsctliger e boun-NasL,
+TCPUuet.d+->sCHECKSUM_UNNECESSARY+oHeA?sctlig,
+TCPUuet.d+->sCHECKSUM_UNNECESSARY+oHellple =. */
 			 short)cUue_fold
+kb_ _QUEUuen000000,aLL,
+	 &,aLL,
+cUue)h ACKs coUDP6 INC_STATS_BH+UdpInE_borsp->snd_IP6 INC_STATS_BH+Ip6InDiscw ssp->OHed531
@@ 533,6-er/ipt_REJEC(di	 l4.2udsv6_
 			b
 intpb/tcit/bitcp.sL,
+TCPUuet.d+>sCHECKSUM_UNNECESSARY_s,ate tcp_veg Osctli * _
 			b
 intpb/tk,tT_C<0 ACKs cUDP6 INC_STATS_BH+UdpInE_borsp->sndIP6 INC_STATS_BH+Ip6InDiscw ssp->OHed586,34ate 7,26 Kahale  Harfousudsv6_mces,idelskb g2Oo Oryusctl_ttcp_delaspace > sk->r 	_ 0;
 		df(t.c	2004-2002r */;cp_delaspace > ace +++ l4.2_ve =cr  +	 *_lpv4/&uds_hash lpv4Erc .sL+>suds_hash[ntohs(uh
+destsr& (UDP_HTABLE+SIZE,7 @)]rc ._vei=aLL,
+dev->i			 exrc .sL+>suds_v6_mces,iajetIC_FAuh
+dest
+nitof
+uh
+s0ur+	FASitof
+nif ;iphsctl!es)p-r
now =
+	{Nsk-+ +hsctl!es)oHeA?sk
+	{Ntpb/tT_CON+r
now =ERGtp =_@t s,ace >-	amma =c.sL2i=aLL =c.whileb0;
2+>suds_v6_mces,iajetIC_2->ajetFAuh
+dest
+nitof
sctl_tt?p_uh
+s0ur+	FASitof
+nif ))t9oy to al!
+ * Networkace >-	+kb_ lonen00000GFP_ATOMICur */
+o al!
+ * 		tp-> been Ae;oy t}oy to ali * _
 			b
 intpb/tk2;
up, )+l=o0)tworkace >-	amma =-t}oy o al
+ * 		tpk
+	{Ntpb/
+ * ;iphsctli * _
 			b
 intpb/tk,AST_C < 0 ACK-
+	{Ntpb:		tpk
+	{Ntpb/tT_CON+r
;cp_delaspace > ace >-	+kb_ lonen00000GFP_ATOMICur geto al
+ * 	
 
	udsv6_
 			b
 intpb/tk2;
up, )_s,ate+	udsv6_
 			b
 intpb/tkc",
+	 &sERG:y:_+	 *_unlpv4/&uds_hash lpv4Erc cnt  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->tp-syms= maxwin),{
@@ -352,6 +3tp-syms=  vic  tcp_clamp_windowtp-syms= 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +otp-syms= 
 }
 
+@ -160,7 7s",
+	 &sysctl_tcp_vcp.la eturn ,6-er
 #includ(t<
+ * Tfcurn ceyh>
 #includ(t<
+ * TioB;
+yh>
 #includ(t<
+ * Tttyyh>
-#includ(t<
+ * Tethtoolyh>
 #includ(t<m +oneighb0uryh>
 #includ(t<m +osnmsyh>
 #includ(t<m +op))yh>
sysc6T2,11 +621,4 KahEXPORT_SYMBOL>sw_handler_ho* LhrspyErc EXPORT_SYMBOL>wire 
ss_spysearch Erc tcp_vegna CONFIG_NET_RADIOr BICONFIG_NET_PCMCIA_RADIOr    ipna ethtoolyc_m	LfEXPORT_SYMBOL>ethtool_op_ho* lin4ErcfEXPORT_SYMBOL>ethtool_op_ho* tx_cUue)rcfEXPORT_SYMBOL>ethtool_op_so* tx_cUue)rcfEXPORT_SYMBOL>ethtool_op_ho* sg)rcfEXPORT_SYMBOL>ethtool_op_so* sg)rcfc tcp_veggna CONFIG_NET     = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/Ceturg.in*
+ * THeAalgorithm +oaused/Ceturg.in vic  tcp_clamp_windowaused/Ceturg.in
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oaused/Ceturg.in
 }
 
+@ -160,7 4:28ctl_tcp_mem[1] = sysc1 
@@ -conges,iriist > '  SFQ_m	LIS'ICONFIG_NET_SCH_SF
,iriist > '  TEQL_m	LIS'ICONFIG_NET_SCH_TEQL
,iriist > '  TBF_m	LIS'ICONFIG_NET_SCH_TBF
,iriist > '  GRED_m	LIS'ICONFIG_NET_SCH_GRED
-iriist > '  /* slowIPT_OWNsimd_cwor'ICONFIG_NET_SCH_DELAY
+iriist > '  /* slowIemd_cwor'ICONFIG_NET_SCH_NETEM
,iriist > '  ry+*s de fielstmt_aB,'ICONFIG_NET_SCH_DSMARK
rill[ "$CONFIG_NETFILTER">-	"y" ];is lOeveryiriist > '  In amd lQdisc'ICONFIG_NET_SCH_INGRESS  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/!=no i+	*
+ * THeAalgorithm +oaused/!=no i+	 vic  tcp_clamp_windowaused/!=no i+	
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oaused/!=no i+	
 }
 
+@ -160,7 8:38ctl_tcp_mem[1] = sysc1tcp_tr4maxegaEbj-$(CONFIG_NET_CLS_POLICE)	+=+B;l ceyo
aEbj-$(CONFIG_NET_SCH_INGRESS)	+=+aus_in amd .o 
aEbj-$(CONFIG_NET_SCH_CBQ)	+=+aus_cbqyo
aEbj-$(CONFIG_NET_SCH_CSZ)	+=+aus_cszyo
-Ebj-$(CONFIG_NET_SCH_DELAY)	+=+aus_PT_OWyo
+Ebj-$(CONFIG_NET_SCH_NETEM)	+=+aus_m +emyo
aEbj-$(CONFIG_NET_SCH_HPFQ)	+=+aus_hpfqyo
aEbj-$(CONFIG_NET_SCH_HFSC)	+=+aus_hfscyo
aEbj-$(CONFIG_NET_SCH_HTB)	+=+aus_htbyo
 = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_cbqy maxwin),{
@@ -352,6 +3aused/aus_cbqy  vic  tcp_clamp_windowaused/aus_cbqy 
 }
 
+2la ecei36:3 &sysctl_tcp_defau
+ *
+ * THeAalgorithm +oaused/aus_cbqy 
 }
 
+@ -160,7 5:3,
+	 &sysctl_tcp_vcp.la05tcp_tr05tcp_KahFbq_PT		/* Here _nPQdisc-20ch)nt = tp->ich
+q.qs(tpACKs cich
+ist  .okb liOk,s /hoy to alq->wd_expires -Na!tptifb
 			bstopped/tch
+dev)g2slow s,arq->wd_expires ACKs cold + PT_OWN= PSCHED_US2JIFFIErq->wd_expires ->snd_ed2tiT_OWN<);
 }nd <	PT_OWN= 1e  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_PT_OWy maxwin),{
@@ -352,6 +3aused/aus_PT_OWy  vic  tcp_clamp_windowaused/aus_PT_OWy 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oaused/aus_PT_OWy 
1970-01-01 00:00:00
+	 &sysctl_tcp_vcp.la,27p_t0,<=/*ipna
- * m +oaused/aus_PT_OWy 
S_snd__maesbanbPT_OWN
- *
- * 		frt *art aam*/
+		eCA_oftware; youa+Hanrevic rib_begi impl/or
- * 		mopacygi iund To fe d_cws/l:6To
dGNU General Publ c L cense
- * 		_qu5ublished+ostTo
dF	eCASoftware Fch
+	queu; eiuo Tod_unv_rt- * 		2/l:6To
dL cense,io f(at your opd+of2pproxsnd_cod_unv_r.
- *
- * Authors:	Step lOHHemmiw s, <shemmiw s,@osdl.org>
- *	Lf
-#includ(t<
+ * Tceturg.h>
-#includ(t<
+ * Tmopule.h>
-#includ(t<
+ * TCypFs.h>
-#includ(t<
+ * TumedAs.h>
-
-#includ(t<
+ * Tc ring.h>
-#includ(t<
+ * Tmm.h>
-#includ(t<
+ * T_o* wi_h>
-#includ(t<
+ * T_o* ios.h>
-#includ(t<
+ * Tinyh>
-#includ(t<
+ * Terrno.h>
-#includ(t<
+ * Tino Wrupt.h>
-#includ(t<
+ * Tif_euo T.h>
-#includ(t<
+ * Tinwi_h>
-#includ(t<
+ * Tnwiurn ceyh>
-#includ(t<
+ * Tetherurn ceyh>
-#includ(t<
+ * TlomefieT.h>
-#includ(t<m +orAyh>
-#includ(t<m +orERGeyh>
-#includ(t<
+ * T,
+p, yh>
-#includ(t<m +o_o* yh>
-#includ(t<m +opk* sused.h>
-
-/*	/* slowIPT_OWNsimd_cworoy frt *suseduleraitoAACK we13,PT_OWNEata,hi	 * wit.
-
S_silaomr6ANISTne impleBSD Dummynwi_
-
-	Itunatsd_cwnK wfoiund TneathNsimilaomr6ATBF_m	Lfl,e _nPdm-/iusedNET_TNetwou32	snd_ncy;twou32	siOk,tp*/;cp_delore
+_l@ -lore
+tp*/;cp_delQdisc-2qdisctp*};
-
-/*rt */(CK we put000000_o* wi
up, wed beerol blpv4am	Lfl,e _nPdm-/ikb_ bNetwopiusedNlibHet	
 			libHtp*};
-
-/*rEn
 			f	 * wit- *sk,und Tlys,* discip(di	 ( wfo)
- * se ceq = them- *sk,me,_dT2nlibHK wre_ma-_m	Lfl,atiB _snddm-/en		/* Here _nPrspace > sk-4-tcp_delQdisc-20ch)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/;cp_deldm-/ikb_ bN* bN og2Oo Orydm-/ikb_ bN*aLL,
+cb;iphs4.2ro* =-
-	PSCHED_GET_TIME(c,
+
 			libH) =-
-	/*rQ 			fto,und Tlys,* suseduleragely ro*H= q->qdisc_mea		/* Hee-4-q->qdisc ;iphsctlro*;
- cich
+ist  .drops /hoy jeY2t9oy tich
+q.qs(t /hoy tich
+ist  ._cwnd.+=aLL,
+	 &rcy tich
+ist  .	 * wit /hoy }ly ro*retu*tp-}
-
-/*rRe
 			f	 * wit-se c/homr6g_snd_nx */(CK we m	Lfl,atiB _snddm-/re		/* Here _nPrspace > sk-4-tcp_delQdisc-20ch)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/s4.2ro* =-
-	ro*H= q->qdisc_mops
+
e		/* Hee-4-q->qdisc ;iphsctlro*kb);
 }y tich
+q.qs(t /hoy ro*returo* =-}
-
-l,atiB  */
 			     dm-/dropHere _nPQdisc-20ch)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/ */
 			     s(t =-
-	llOHh	q->qdisc_mops
+dropHq->qdisc ;iphsctls(tpACKy tich
+q.qs(tome - cich
+ist  .drops /hoy }ly ro*retus(t =-}
-
-/*rDe
 			f	 * wima-_meI
+	 * wi m e
+e644be helstup,is lOHstop old_-_me
 			f_maxse@ # /homr6Aw=noup5snd_cwn-_m	Lfl,atiB ere _nPrspace > dm-/dT		/* Here _nPQdisc-20ch)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/;cp_delrspace > sk-Hh	q->qdisc_mdT		/* Hq->qdisc ;ipiphsctligbpACKy ticp_deldm-/ikb_ bN* bN og2Oo Orydm-/ikb_ bN*aLL,
+cb;iphopiusedNlibHetAold;iphold + Pwnd(tpiph	PSCHED_GET_TIME(oldur */
*psllndq->snd_ncy - PSCHED_TDIFF(old, c,
+
 			libH) =-
-	Aolollo
-#<);
 Networkich
+q.qs(tome - ckich
+_tcp_bi= ~TCQ_F_THROTTLEDe - ckro*retusk-+ y t}oyoy to al!tptifb
 			bstopped/tch
+dev)g2sl- cold + PT_OWN= PSCHED_US2JIFFIErlo
-ur */
+o aliT_OWN<);
 }-d <	PT_OWN= 1e -d <mop_ore
+(&q->ore
+, jo
-ies+PT_OW)+ y t}oyoy to alq->qdisc_mops
+
e		/* Hee-4-q->qdisc +->sNET_XMIT_SUCCESSe/etworkich
+q.qs(tome - ckich
+ist  .drops /hoy t}oy tich
+_tcp_b|BICTQ_F_THROTTLEDe - }ly ro*retuamma =-}
-
-l,atiB rfousdm-/rec	2/tre _nPQdisc-20ch)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*p*/qdisc/rec	2/q->qdisc ;iphich
+q.qs(t_no_ts+
ich
+_tcp_bi= ~TCQ_F_THROTTLEDe - PT__ore
+(&q->ore
+) =-}
-
-l,atiB rfousdm-/ore
+( */
 			 ld + arg)n-{p*/;cp_delQdisc-20cht og2Oo OryQdisc-2)arg;p*p*/ich
+_tcp_bi= ~TCQ_F_THROTTLEDe - tptifbsusedule/tch
+dev) =-}
-
-/*rTe,hiFwfoifldbajw siOk,T_m	Lfl,atiB _sndg_snd__liOk,g2Oo OryQdisc-2qart amliOk,)n-{p*/;cp_delr,attragr_T;p*/s4.2ro* =-
-	r_TN= km@@ vc(RTA_LENGTHPltering2Oo Orytn_ wfo_qopd))00GFP_KERNEL ;iphsctl!r_T }-d ro*retu-ENOMEM =-
-	r_T
+
ta_CypF+= RTM_NEWQDISC;iph(g2Oo Orytn_ wfo_qopd-2)RTA_on f(r_T )->siOk,+= siOk,tp*/ro*H= q->ops
+g_snd_(qarr_T tp*/k
+	{(r_T tp*oy ro*returo* =-}
-
-6 1
.
up5und Tlys,* FIFO discip(di	 m	Lfl,atiB _snddm-/g_snd_(;cp_delQdisc-20ch4-tcp_delr,attragopd)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/;cp_deltn_dm-/qopd-2qopd-= RTA_on f(opd);p*/s4.2 Wr;ipiphsctlq->qdisckb);&noop_qdisc +CKy ticp_delQdisc-2child - ck= qdisc/dreaiAodflt/tch
+dev, &b wfo_qdisc/ops);oy to al!child) - ckro*retu-EINVAa =-t	q->qdisckb childe - }lyoy j_bi=as_snd__liOk,gq->qdisc4-qopd->siOk, ;iphsctlerry(co-t	qdisc/destroy/q->qdisc ;iph	q->qdisckb &noop_qdisce - }ajeY2t9oy tq->snd_ncy =-qopd->snd_ncy;twotq->siOk,+= qopd->siOk,e - }ly ro*retu Wr;ip}
-
-l,atiB _snddm-/cp_rtt_esdelQdisc-20ch4-tcp_delr,attragopd)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/s4.2 Wr;ipiphsctl!opd)n-ckro*retu-EINVAa =-n-cMOD INC_USE_COUNT;ipiphsnk,_ore
+(&q->ore
+) =-	q->ore
+.funtp->ve=sdm-/ore
+ =-	q->ore
+.ET_TN og */
 			 ld +) sus =-	q->qdisckb &noop_qdisce -oy j_bi=adm-/g_snd_(;ch4-opd);p*/sctlerryn-ckMOD DEC_USE_COUNT;ipiphro*retu Wr;ip}
-
-l,atiB rfousdm-/destroy/tre _nPQdisc-20ch)n-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*p*/PT__ore
+(&q->ore
+) =-	qdisc/destroy/q->qdisc ;iphq->qdisckb &noop_qdisce -oy MOD DEC_USE_COUNT;ip}
-
-l,atiB _snddm-/dumpHere _nPQdisc-20ch4-tcp_delaspace > sk->r-{p*/;cp_deldm-/iusedNET_TN*qt og2Oo Orydm-/iusedNET_TN*)tch
+dT_T;p*/ */
 			 g_sr	 *bi=aLL,
+tail;p*/;cp_deltn_dm-/qopd-qopd;p*p*/qopt.snd_ncy =-q->snd_ncy;twoqopt.siOk,+= q->siOk,e -twoRTA_PUTHee-4-Tf dfPTIONS,titeringqopd), &qopd);p*iphro*retuLL,
+	 &rcy
-r,attr_failure:		tikb_trien00000b atiL,
+da_T tp*/ro*retu-1;ip}
-
-l,e _nPQdisc/opsydm-/qdisc/ops+= {p*/.idck=	"PT_OW",p*/.w-rvar MFk=	ltering2Oo Orydm-/iusedNET_T),p*/.ea		/* k=	dm-/en		/* ,p*/.dT		/* k=	dm-/dT		/* ,p*/.rT		/* k=	dm-/rT		/* ,p*/.drop	k=	dm-/drop,p*/.snk,	k=	dm-/snk,,p*/.rTc	2	k=	dm-/rTso*;p*/.dTstroyk=	dm-/dTstroy;p*/.g_snd_	k=	dm-/g_snd_;p*/.dump	k=	dm-/dump,p*};
-
-#ifnly MODULE
-ECT.snk,_mopule	&proq
-{p*/ro*returogisp_faqdisc(&dm-/qdisc/ops) =-}
-
-rfous
 int+syoopule	&proq
-{p*/un "gisp_faqdisc(&dm-/qdisc/ops) =-}
-tcp_veg-MODULE_LICENSE("GPL"CON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_Pseq =y maxwin),{
@@ -352,6 +3aused/aus_Pseq =y  vic  tcp_clamp_windowaused/aus_Pseq =y 
 }
 
+2la ecei36:3 &sysctl_tcp_defau
+ *
+ * THeAalgorithm +oaused/aus_Pseq =y 
 }
 
+mes,amps is0967,8 +67,11 @@ match(324max+324mgas_gammaPseq =/cp_rtt_esdelQdisc-20ch4t_esde
 	__u16 ts :Dt = DPRINTK("Pseq =/cp_rttcht%p,[qdisck%p],opd-%p)\n",0ch4p,opd);p*/sctlr,attr_parse(tb,Tf dDSMARK+MAX,RTA_on f(opd),RTA_PAYLOAD(opd)C < 0 || +hsctl!opd-|| +hveryr,attr_parse(tb,Tf dDSMARK+MAX,RTA_on f(opd),RTA_PAYLOAD(opd)C < 0 ||  hvery!tb[Tf dDSMARK+INDICES-img||  hveryRTA_PAYLOAD(tb[Tf dDSMARK+INDICES-imC < ltering__u16 (!                 ro*retu-EINVAa = = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_hfscy maxwin),{
@@ -352,6 +3aused/aus_hfscy  vic  tcp_clamp_windowaused/aus_hfscy 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oaused/aus_hfscy 
 }
 
+@ -160,7 8:1 &sysctl_tcp_defaucp.la722ega+a722ep_Kahhfsc_PT		/* Here _nPQdisc-20ch)nt		clHh	e5viAs,iho* minvt(&q->roo*;
gur_libH) =llple =clHh-	ammay(const	ech
+ist  .okb liOk,s /hoy tto al!tptifb
 			bstopped/tch
+dev)g}-d <	hfsc_susedule_wtcp.dog(;ch4-gur_libH) =+ <	hfsc_susedule_wtcp.dog(;ch4-gur_libH) =  ckro*retuamma =c.bitcpit = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_htby maxwin),{
@@ -352,6 +3aused/aus_htby  vic  tcp_clamp_windowaused/aus_htby 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oaused/aus_htby 
 }
 
+@ -160,7 4:4 &sysctl_tcp_defaucp.la01An:31101An6 Kahajet:
hale  Harfoushtb_PT_OW_by/tre _nPQdisc-20ch,ld + PT_OW>r 	_ 0;
 		dfhtb_ausedN*qt og2Oo Oryhtb_ausedN*)tch
+dT_T;p*/s)_cwntifb
 			bstopped/tch
+dev)g2ro*retchlled2tiT_OWN<);
  PT_OWN= 1e lled2tunHat lytiT_OWN> 5*HZ)+oHellple =_doa
d;_liOk,g)g} = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_m +emy maxwin),{
@@ -352,6 +3aused/aus_m +emy  vic  tcp_clamp_windowaused/aus_m +emy 
1970-01-01 00:00:00
+	 &sysctl_tcp_v
+ *
+ * THeAalgorithm +oaused/aus_m +emy 
 }
 
+@ -160,7 8:3,
+	 &sysctl_tcp_vcp.l0,<=+1,9617 +
+i1
e * m +oaused/aus_m +emy 
/* slowIemd_cwor
e *
e * 		frt *art aam*/
+		eCA_oftware; youa+Hanrevic rib_begi impl/or
+ * 		mopacygi iund To fe d_cws/l:6To
dGNU General Publ c L cense
+ * 		_qu5ublished+ostTo
dF	eCASoftware Fch
+	queu; eiuo Tod_unv_rt+ * 		2/l:6To
dL cense,io f(at your opd+of2pproxsnd_cod_unv_r.
e *
e * Authors:	Step lOHHemmiw s, <shemmiw s,@osdl.org>
e *		CT_T
+ (ux aka Dino) BOIE <cT_Tb at umbrella doelro>
e *_frto#includ(t<
+ * Tceturg.h>
o#includ(t<
+ * Tmopule.h>
o#includ(t<
+ * Tcp_r.h>
o#includ(t<asm/bitops.h>
o#includ(t<
+ * TCypFs.h>
o#includ(t<
+ * TumedAs.h>
o#includ(t<
+ * Terrno.h>
o#includ(t<
+ * Tnwiurn ceyh>
o#includ(t<
+ * T,
+p, yh>
o#includ(t<
+ * Trtnwilin4yh>
o
+#includ(t<m +opk* sused.h>
+
+i1
/* slowIemd_cwor
e *
e * frt *susedulera+Hana bou *spacs,* _max Cont
e * S_silaomr6ANISTne impleBSD Dummynwi_
e *_frto2Oo Orym +em/iusedNET_TNet+ticp_delQdisc	2qdisctp+/;cp_delrspace ivegas_COd_cntp+/;cp_delore
+_l@ -lore
+tp>v
+t amlnd_ncy;t
+t aml 0;
-		t amliOk,
-		t am buffer
-		t amgap
-		t amjitfer
-	};
+
+i1rt */(CK we put000000_o* wi
up, wed beerol blpv4am	Lo2Oo Orym +em/ikb_ bNet+opiusedNlibHet	libHeto_ntcp
-	};
+
+i1rtrt *is6To
dvic rib_b->veL,
+	H
datfldbaormal vic rib_b->veartoly2d
e *  *sk,NISTne itools_
e *sk, isReniesnreprTso vai*sual		   d_un
/l:6To
dcumd_cwiv
dvic rib_b->v
e *sfuntp->v_
e *_fronly gooTABLESIZE
 }48fronly gooTABLEFACTOR	8192&(se50roc_s besbeehortdvic L,
+	[TABLESIZE]+= {p+	-31473,		-26739,		-25e26,		-24269relL-23560,		-22993,		-22518,		-22109relL-21749,		-21426,		-21133,		-20865relL-20618,		-20, fi		-20174i		-19972relL-19782i		-19601i		-19430i		-19267relL-19112i		-18962i		-18819i		-18681relL-18549i		-18421i		-18298i		-18178relL-18062i		-17950i		-17841i		-17735relL-17632i		-17532i		-17434i		-17339relL-17245i		-17155i		-17066,		-16979relL-16894i		-16811i		-16729i		-16649relL-16571i		-16494i		-16419i		-16345relL-16272i		-16201i		-16130i		-16061relL-15993,		-15926,		-15861i		-15796relL-15732i		-15669i		-15607i		-15546,elL-15486,		-15426,		-15368,		-15310,elL-15253,		-15196,		-15140i		-15086,elL-15031i		-14977i		-14925i		-14872relL-14821i		-14769i		-14719i		-14669relL-14619i		-14570i		-14522i		-14473,elL-14426,		-14379i		-14332i		-14286,elL-14241i		-14196,		-14150i		-14106,elL-14062i		-14019i		-13976i		-13933,elL-1, f0i		-13848i		-13807i		-13765relL-13724i		-13684i		-13643i		-13604relL-13564i		-13525i		-13486,		-13447relL-13408i		-13370i		-13332i		-13295relL-132	re		-13221i		-13184i		-13147relL-13111i		-13075i		-13040i		-13004relL-12969i		-12934i		-12899i		-12865relL-12830i		-12796,		-12762i		-12729ielL-12695i		-12662i		-12629i		-12596relL-12564i		-12531i		-12499i		-12467relL-12435i		-12404i		-12372i		-12341relL-12310,		-12279i		-12248i		-12218relL-12187i		-12157i		-12127i		-12097relL-12067i		-12038i		-12008i		-11979relL-11950i		-11921i		-11892i		-11863,elL-11835i		-11806i		-11778i		-11750,elL-1a722e		-11694i		-11666i		-11639relL-11611i		-11584i		-11557i		-11530,elL-1a503i		-11476i		-11450i		-11423,elL-11396,		-11370i		-11344i		-11318relL-11292e		-11266i		-11240i		-11214relL-11189i		-11164i		-11138i		-11113relL-11088i		-11063i		-11038i		-11013relL-10988i		-10964i		-10939,		-10915relL-10891i		-10866i		-10843i		-10818relL-10794i		-10770i		-10747i		-10723,elL-10700i		-10676i		-10652i		-10630,elL-10606i		-10583i		-10560,		-10537relL-10514,		-10491i		-10469i		-10446,elL-10424,		-10401i		-10378i		-10356,elL-10334i		-10312i		-102f0i		-10267relL-10246i		-10224,		-10202i		-10180relL-101	re		-101RAn		-10115i		-10094relL-10072i		-10051i		-10030i		-1cp_9relL-9988i		-9967i		-9945i		-9925ielL-9904i		-9883i		-9862i		-9842ielL-9821i		-9800i		-9780i		-9760relL-9739,		-9719i		-9699i		-9678relL-96	re		-963re		-9618,		-9599telL-9578,		-9559i		-9539,		-9519telL-9499i		-9480i		-9461i		-9441relL-9422e		-9402i		-9383i		-9363,elL-9344i		-9325i		-9306i		-9287relL-9268,		-9249i		-9230i		-9211relL-9192e		-9173,		-9155i		-9136relL-9117i		-9098i		-9080i		-9062ielL-9043i		-9025i		-9006i		-8988ielL-8970i		-8951i		-8933,		-8915relL-8897,		-8879i		-8861i		-8843ielL-8825i		-8807i		-8789i		-8772relL-8754i		-8736i		-8718,		-8701relL-8683,		-8665i		-8648i		-8630,elL-8613,		-8595i		-8578,		-8561relL-8543,		-8526,		-8509i		-8492relL-8475i		-84	re		-8441i		-8423,elL-8407i		-83f0i		-8373,		-8356,elL-8339,		-8322e		-8305i		-8289,elL-8272i		-8255i		-8239,		-8222relL-8206i		-8189i		-8172i		-8156,elL-8140i		-8123i		-8107i		-8090,elL-8074i		-80	re		-8042e		-8025ielL-8009i		-7993,		-7977i		-7961relL-7945i		-7929i		-7913,		-7897relL-7881,		-7865i		-7849i		-7833,elL-7817i		-7802e		-7786e		-7770,elL-7754i		-7739,		-7723i		-7707relL-7692e		-7676i		-7661i		-7645relL-7630i		-7614,		-7599i		-7583ielL-7568,		-7553,		-75RAn		-7522relL-750An		-7492e		-7476i		-7461relL-7446i		-7431i		-7416i		-7401relL-7385i		-7370i		-7356,		-7340,elL-7325i		-7311i		-7296,		-7281relL-7266i		-7251i		-7236i		-7221relL-720An		-7192e		-7177i		-7162ielL-7148i		-7133,		-7118i		-7104relL-7089i		-7075i		-7060i		-7046,elL-7031i		-7016i		-7002e		-6988ielL-6973e		-6959i		-6944i		-6930,elL-6916i		-6901i		-6887i		-6873,elL-6859i		-6844i		-6830i		-68168elL-6802e		-6788i		-6774i		-6760relL-6746i		-6731i		-6717i		-6704relL-6690i		-6675i		-6661i		-6647relL-6633,		-6620i		-6606i		-6592relL-6578,		-6564i		-6550i		-6537relL-6523,		-6509i		-6495i		-6482relL-6468,		-6454i		-6441i		-6427relL-6413,		-6400i		-63r6i		-6373,elL-6359i		-6346i		-6332i		-6318relL-6305i		-6291i		-6278,		-6264relL-6251i		-6238,		-6224,		-6211relL-6198,		-6184i		-6171i		-61	reelL-6144i		-6131i		-6118i		-6;05FelL-6091i		-6078,		-6065i		-6052relL-6039,		-6025i		-6012i		-5999,elL-59r6i		-5973e		-5960e		-5947relL-5934i		-5921i		-5908i		-5895relL-5882i		-5869i		-5856,		-5843ielL-5830i		-5817i		-5804i		-5791ielL-5779i		-5766i		-5753,		-5740,elL-5727i		-5714i		-5702e		-5689,elL-5676i		-5663,		-5650i		-563reelL-5625i		-5612e		-5600i		-5587relL-5575i		-5562i		-5549i		-5537relL-5524,		-5512e		-5499i		-5486,elL-5474i		-5461i		-5449i		-5436,elL-5424,		-5411i		-5399i		-5386,elL-5374i		-5362i		-5349i		-5337relL-5324,		-5312i		-5299i		-5287relL-5275i		-5263,		-5250i		-523reelL-5e26,		-5213,		-5201i		-5189,elL-5177i		-5164i		-5152i		-5140ielL-5128i		-5115i		-5103i		-5091ielL-5079i		-5067i		-5055i		-5043ielL-5030i		-5018i		-5006i		-4994relL-4982i		-4970i		-4958i		-4946,elL-4934i		-4922i		-4910,		-4898,elL-48r6i		-4874i		-4862i		-4850,elL-4838,		-4826i		-4814i		-4803ielL-4791i		-4778i		-4767i		-4755ielL-4743,		-4731i		-4719i		-4708ielL-4696,		-4684i		-4672i		-4660relL-4649i		-46RAn		-4625i		-4613relL-4601i		-4590i		-4578,		-4566relL-4554i		-4543,		-4531i		-4520relL-4508i		-4496,		-4484i		-4473,elL-4461i		-4449i		-4438,		-4427relL-4415i		-4403i		-4392e		-4380relL-4368,		-435An		-4345i		-4334ielL-4322i		-4311i		-4299i		-4288ielL-4276,		-4265i		-4253,		-4242ielL-4230i		-4219i		-420An		-4196,elL-4184i		-4173,		-4162i		-4150,elL-4139,		-4128i		-4116,		-4;05FelL-4094i		-4082i		-4071i		-4060relL-4048i		-403An		-4026i		-4014relL-4003,		-3992,		-3980i		-3969relL-3958i		-3946i		-3935i		-3924relL-3913,		-3901i		-, f0i		-3879relL-3868i		-385An		-3845i		-3834relL-3823,		-3812i		-3801i		-,790,elL-3779i		-3767i		-3756,		-3745,elL-3734i		-3723i		-3712i		-3700ielL-3689i		-3678,		-3667i		-3656,elL-3645i		-3634i		-3623i		-3612eelL-3601i		-,590i		-35A9i		-3568,elL-3557i		-3545i		-3535i		-3524relL-3513,		-3502e		-3491i		-3480relL-3469i		-34	re		-3447r		-3436,elL-3425i		-3414i		-3403i		-3392relL-3381,		-3370i		-3360i		-3348,elL-333An		-332An		-3316,		-3305FelL-3294i		-3283,		-3272i		-3262ielL-3251i		-3240i		-3229i		-3218relL-320An		-319An		-3185i		-3175FelL-3164i		-3153,		-3142e		-3132ielL-3121i		-3110i		-3099i		-3088ielL-3078,		-3067i		-3056,		-3045,elL-3035i		-3024,		-3013,		-3003ielL-2992,		-2981,		-2970i		-2960relL-294fi		-2938,		-2928,		-2917relL-2906i		-2895i		-2885i		-2874relL-2864i		-2853,		-2842e		-2832relL-2821i		-2810i		-2800i		-2789,elL-2778i		-2768i		-2757i		-2747relL-2736i		-2725i		-2715i		-2704relL-2694i		-2683,		-2673,		-2662ielL-2651i		-2641i		-2630i		-2620relL-2609,		-2599,		-2588i		-2578relL-2567i		-2556i		-2546i		-2535relL-2525i		-2515i		-2504i		-2493relL-2483,		-2472i		-2462i		-2451relL-2441i		-2431i		-2420i		-2410,elL-2399i		-2, fi		-2378i		-2367relL-235An		-234An		-2336i		-2326relL-2315i		-2305i		-2295i		-2284relL-2274i		-2263,		-2253,		-2243relL-2232i		-2222i		-2211i		-2201relL-2191i		-2180i		-2170i		-2159relL-2149,		-2139,		-2128i		-2118relL-2107i		-2097r		-2087r		-2076relL-2066,		-2056,		-2046i		-2035relL-2025i		-2014i		- }
 i		-1994relL-1983i		-1973e		-1963e		-1953,elL-1942i		-1932i		-1921i		-1911relL-1901i		-1891i		-1880i		-1870,elL-1860,		-1849i		-1839,		-1829ielL-1819i		-1808i		-1798i		-1788ielL-1778i		-1767i		-1757i		-1747relL-1736i		-1726,		-1716,		-1706,elL-1695i		-1685i		-1675i		-1665relL-1654i		-1644i		-1634i		-1624relL-1613,		-1603,		-1593,		-1583ielL-1573,		-1563e		-1552i		-1542ielL-1532i		-1522i		-1511i		-1501relL-1491i		-1481i		-1471i		-1461relL-1450i		-1440i		-1430i		-1420relL-1409i		-1400i		-1389i		-1379relL-1369i		-1359i		-1348i		-1339relL-1328i		-1318i		-1308i		-1298relL-1288i		-1278,		-1267i		-1257relL-1247i		-12RAn		-1227i		-1217relL-1207i		-1196,		-1186i		-1176,elL-1166i		-1156i		-1146,		-1135relL-1126,		-1115i		-1105i		-1095relL-1085i		-1075i		-1065i		-1055relL-1044i		-1034,		-1024,		-1014relL-1004i		-994i		-984i		-974relL-964i		-954i		-944i		-933,elL-923,		-913i		-903,		-893ielL-883,		-873,		-863,		-853,elL-843,		-833,		-822e		-812eelL-802e		-792e		-782e		-772ielL-762i		-752e		-742e		-732relL-722e		-712i		-702e		-691relL-682e		-671i		-662e		-651relL-641i		-631i		-621i		-611relL-601i		-591i		-581i		-571ielL-561i		-551i		-541i		-531ielL-521i		-511i		-501i		-491relL-480i		-471i		-460i		-451relL-440i		-430i		-420i		-410relL-400i		-390i		-380i		-370ielL-360i		-350i		-340i		-330,elL-320i		-310i		-300i		-290,elL-280i		-270i		-260,		-250,elL-240i		-230i		-220i		-210,elL-199i		-1f0i		-179i		-170,elL-159i		-150i		-139i		-129relL-119,		-109i		-99,		-89relL-79i		-69i		-59i		-49relL-39i		-29i		-1fi		-9relL1i		11i		21i		31ielL41i		51i		61i		71ielL81i		91i		101i		111ielL121i		131i		141i		152relL161i		172i		181i		192relL202i		212i		222i		232relL242e		252e		262e		272ielL282e		292e		302i		312eelL322i		332i		342e		352relL362i		372i		382e		392relL402i		412i		422e		433,elL442e		453,		462i		473,elL483,		493,		503i		513relL523,		533,		543,		553,elL563e		573,		583i		593ielL603,		613,		623i		633,elL643i		653,		664i		673,elL684i		694i		704i		714relL724i		734i		744i		754ielL764i		774i		784i		794relL804i		815i		825i		835relL845i		855i		865i		875FelL885i		895i		905i		915relL925i		936i		946i		956,elL966i		976i		9r6i		996,elL1006i		1016i		1026i		1037,elL1047i		1057i		1067i		1077,elL1087i		1097r		1107i		1117relL1128i		1138i		1148i		11	reelL1168i		1178i		1188i		1198relL1209i		1219i		1229i		1239relL1249i		1259i		1269i		1280relL12f0i		1300i		1310i		1320relL1330i		1341i		1351i		1361relL1371i		1381i		1391i		1402ielL1412i		1422e		1432e		1442ielL1452e		1463e		1473,		1483ielL1493,		a503i		1513,		1524relL1534i		1544i		1554i		1565relL1575i		1	r5i		1	95i		1606relL1616i		1626i		1636i		1647relL1656i		1667i		1677i		1687relL1697r		1708i		1718,		1729ielL1739,		1749,		1759,		1769ielL1780i		17f0i		1800i		1810,elL1821i		1831i		1841i		1851relL1862i		1872i		1883i		1893ielL1903,		1913i		1923,		1934relL1944i		1955i		1965i		1975FelL1985i		1996,		2006i		20168elL2027i		2037i		2048i		20	reelL2068i		2079i		2089i		2099,elL2110i		2120i		2130i		2141relL2151i		2161i		2172i		2182relL2193,		2203,		2213,		2224relL2234,		2245i		2255i		2265relL2276,		2286,		2297r		2307relL2318i		2328i		2338i		2349relL2359i		2370i		2380i		2391relL2401i		2412i		2422e		2433,elL2443,		2454i		2464i		2475FelL2485i		2496,		2506,		2517relL2527r		25RAn		2548i		2559relL2569i		2580i		2590i		2601relL2612e		2622e		2632i		2643relL2654i		2664i		2675i		2685ielL2696,		2707i		2717i		272reelL2738i		2749,		2759,		2770,elL2781i		2791i		2802e		2813ielL2823,		2834,		2845i		2855relL2866i		2877i		2887i		2898,elL2f09,		2919,		2930i		2941relL2951i		2962i		2973e		2984relL2994i		3005i		3015i		3027relL3037i		3048i		30	re		3069ielL3080i		3091i		3101i		3113relL3123i		3134,		3145i		3156,elL3166i		3177i		3188i		3199,elL3210i		3220i		3231i		3242ielL3253,		3264i		3275i		3285ielL3296,		3307i		3318i		3329,elL3340i		3351i		3362i		3373,elL3384i		3394i		3405i		34168elL3427r		3438,		3449i		3460relL3471i		3482e		3493,		3504relL3515i		3526,		35RAn		3548,elL3559i		3570i		3581i		3592relL3603,		3614,		3625i		3636,elL3647i		3659i		3670i		3681relL3692e		3703,		3714i		3725ielL3736i		3747i		37	re		3770,elL3781i		3792e		3803,		3814relL3825i		38RAn		3848i		3859relL3870i		3881,		3893,		3904relL3915i		3926,		39RAn		3949relL3960e		3971i		3983i		3994relL4005i		4017i		4028i		4039relL4051i		4062i		4073e		4085ielL4096,		4107i		4119,		4130,elL4141i		4153,		4164i		4175FelL4187i		4198,		4210i		4221relL4233,		4244i		4256i		4267relL4279i		42f0i		4302i		4313relL4325i		4336i		4348i		4359relL4371i		4382e		4394i		4406,elL4417i		4429i		4440i		4452relL4464i		4475i		4487i		4499,elL4510i		4522i		4533,		4545,elL4557i		4569i		4581i		4592relL4604i		4616i		4627i		4639relL4651i		4663,		4674i		4686,elL4698,		4710i		4722e		4734relL4746i		47	re		4769i		4781relL4793,		4805i		4817i		4829ielL4841i		4853,		4865i		4877,elL4889i		4900i		4913i		4925ielL4936i		494fi		4961i		4973,elL4985i		4997i		5009i		5021relL5033,		5045i		5057i		5070,elL5081i		5094i		5106,		5118relL5130i		5143,		5155i		5167relL5179i		5191i		5204i		5216relL5228i		5240i		5253,		5265relL5278,		52f0i		5302i		5315relL532An		5340i		5352i		5364relL5RAAn		5389i		5401i		5414relL5426,		5439i		5451i		5464relL5476i		5489i		5502e		5514relL5527r		5539,		5552i		5564relL55AAn		5590i		5603,		5615relL5628i		5641i		5653,		5666relL5679i		5691i		5704i		5717relL5730i		5743,		5756,		5768,elL5781i		5794i		5807i		5820relL5833,		5846i		5859i		5872relL5885i		5897,		5911i		5924relL59RAn		5950i		5963e		5976,elL5989i		6002e		6015i		602reelL6042e		6055i		6068i		6081relL6094i		6108i		6121i		6134relL6147i		6160i		6174i		6187relL6201i		6214i		6227i		6241relL6254i		6267i		6281i		6294relL6308i		6321i		6335i		6348,elL6362i		6375i		6389i		6403,elL6416i		6430i		6443,		6457relL6471i		6485i		6498,		6512eelL6526,		6540i		6554i		6567relL6581i		6	95i		6609,		6623,elL66RAn		6651i		6665i		6679relL6692e		6706,		6721i		6735relL6749,		6763e		677An		6791ielL6805i		6819i		6833,		6848,elL6862i		6876,		6 f0i		6905FelL6919,		6933,		6948i		6962ielL6976i		6991i		7005i		7020relL7034,		7049,		7064i		7078relL7093,		7107i		7122e		7136relL7151i		7166i		7180i		7195relL7210i		7225i		7240i		7254ielL7269i		7284i		7299i		7314relL7329i		7344i		7359i		7374relL7389i		7404i		7419i		7434ielL7449i		7465i		7480i		7495relL7510i		7526,		7541i		7556,elL7571i		7587i		7602e		7618relL7633,		7648i		7664i		7680relL7695i		7711i		7726,		7742ielL77	re		77A3,		7789i		7805FelL7821i		7836i		7852i		7868,elL7884i		7900i		7916i		7932relL7948i		7964i		7981,		7997relL8013,		8029,		8045i		8061relL8078,		8094i		8110i		8127relL8143,		8160i		8176i		8193ielL8209i		8e26,		8242e		8259relL8276,		8292e		8309i		8326relL8343,		8360i		8RAAn		8394relL8410i		8428i		8444i		8462ielL8479i		8496,		8513,		8530,elL8548i		8565i		8582e		8600ielL8617i		8634i		8652i		8670ielL8687i		8704i		8722e		8740,elL87	re		8775i		8793,		8811ielL8829,		8847i		8865i		8883ielL8901i		8919,		89RAn		8955relL8974i		8992,		9010,		9029ielL9047i		9066,		9084i		9103,elL9121i		9140i		9159i		9177,elL9196,		9215i		9234,		9253,elL9272i		9291i		9310i		9329,elL9349i		9368,		9387i		9406,elL9426,		9445i		9465i		9484relL9504i		9524,		9544i		9563,elL9583i		9603,		9623i		9643relL9663,		9683,		9703,		9723,elL9744i		9764i		9785i		9805FelL9826i		9846i		9867i		9888ielL9f09,		9930i		9950i		9971ielL9993,		10013,		10035,		10056,elL10077i		10099i		10120i		10142ielL10163e		10185i		10207i		10229ielL10251i		10273,		10294i		10317,elL10339,		10361i		10384i		10406,elL10428i		10451i		10474i		10496,elL10519i		10542e		10565i		10588ielL10612i		10635,		106	re		10682ielL10705,		10729i		10752i		10776,elL10800i		10824i		10848i		10872ielL10896i		10921i		10945,		10969relL10994i		11019i		11044i		11069relL11094i		11119i		11144i		11169relL11195i		11221i		11246i		11272ielL11298i		11324i		11350i		11376,elL11402i		11429i		11456i		11482relL1a509i		11536i		11563e		11590,elL11618i		11645i		11673,		11701relL1a728i		11756i		11785i		11813relL11842e		11870i		11899i		1192reelL11957i		119r6i		12015i		12045,elL12074i		12104i		12134i		12164relL12194i		12225i		12255i		12286,elL12317i		12348i		12380i		12411ielL12443,		12475i		1250An		12539relL12571i		12604i		126RAn		12670relL12703,		127RAn		12771i		12804relL12839,		12873,		12f0An		12942ielL12977i		13013,		13048i		13084relL13120i		13156i		13192,		13229ielL13267i		13304i		13341i		13379relL13418i		13456i		13495i		13534relL13573,		13613,		13653,		13693ielL13734i		13775i		13817i		138	reelL13901i		13943,		139r6i		14029ielL14073e		14117i		14162i		14206,elL14252e		14297r		14343,		14390,elL14437r		14485i		14533,		14582relL14631i		14680i		14731i		14782relL14833,		14885i		14937r		14991ielLa5044i		15099i		15154i		15210,elL15266,		15324,		15382e		15441ielLa5500i		15561i		15622e		15684relL15747i		15811i		15877i		15943relL16010i		16078,		16148i		16218relL162f0i		16363e		16437r		16513relL165f0i		16669i		16749,		16831ielL16915i		17000i		17088i		17177,elL17268i		17362i		174	re		17556,elL17657i		17761i		17868i		17977,elL18090,	L1820An		18328i		18452relL18581i		18715i		18854,		18998relL19149,		1930An		19472i		19645FelL19828i		20021i		20e26,		20444relL20678,		20930i		21204,		2a503ielL21835i		22206,		22630i		23124relL23721i		24478i		25529,		27316rel};
+
+i1rL,
+	vic  - ro*retua pseudo-randomlydvic rib_bed value  *sk,mean muimpl
e *sstas_Cvi	queu sigma.  UatsdL,
+	HlookupNEatapproximt > To
dvesir2d
e * vic rib_b->v,implea uniformly-vic rib_bed pseudo-random s0ur+	_
e *_fript_REJEC(di	 l4.2L,
+	vic (l4.2mu, l4.2sigma)
+HeA?s4.2x;eA?s4.2		 exrcA?s4.2sigmamod,2sigmadivtp>v
+sctliigmakb);
 }+ckro*retumutp>v
+s	 ext og_doa
dndom(sr& (TABLESIZE-1)) =+ sigmamodi=aLigma%TABLEFACTOR =+ sigmadivi=aLigma/TABLEFACTOR =+ xi=aLigmamod*vic L,
+	[s	 ex]tp>v
+sctlx+l=o0)t+ckx.+=aTABLEFACTOR/2 =+ jeY2t+ckx.-=aTABLEFACTOR/2 =+=+ xi/=aTABLEFACTOR =+ xi+=2sigmadiv*vic L,
+	[s	 ex]tp> xi+=2mutp>kro*retuxrcA}
+
+i1rEn
 			f	 * wit- *sk,und Tlys,* discip(di	 ( wfo)
+ * se ceq = them- *sk,me,_dT2nlibHK wre_mae *_fript_REJECrym +em/en		/* Here _nPrspace > sk-4-tcp_delQdisc-20ch)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+ticp_delm +em/ikb_ bN* bN og2Oo Orym +em/ikb_ bN*aLL,
+cb;i+opiusedNlibHetAold;i+old + PT_OW =+=+ pr_debug("m +em/en		/* tiL,=%p @%lu\n", sk-4-jo
-ies) =+=+ /*rRandom 	 * wi drop 0 =>Aolne, ~0 =>Aa,hi*_frhsctlq->l 0; -Naq->l 0; l=o_doa
dndom(sg2slow ich
+ist  .drops /ho+ckro*retu0; /*rlie aboe cl 0; so TCP doesomr6koldi*_frh}
+
+=+ /*rIf dos,* s_snd__PT_OWNE lOHgapkb);
 so a,hi	 * wit=+  * go000000To
dveOd_cn holds,* 		/* =+  * ouo Twiserilldos,* oe cofx Cont onlyd"1 oe cofxgap"=+  * 	 * wit- *,hib
dveOd_cn.=+  *_frhsctlq-> buffer <aq->gapg2slow s4.2ro* =+=+ 	++q-> bufferho+ckro*H= q->qdisc_mea		/* Hee-4-q->qdisc ;iow s,arro*;
+ ckich
+ist  .drops /ho+ckro*returo* =+ate+	e+	q-> buffer no_ts+	e+	PSCHED_GET_TIME(oldur rhsctlq->jitfer) o+ckPT_OWN= L,
+	vic (q->snd_ncy4-q->jitfer) =+ jeY2t+ckPT_OWN= q->snd_ncy;t+e+	PSCHED_TADD2(old, PT_OW, c,
+libHeto_ntcp)ts+	e+	/*rAlwayse
 			f_.2L,ilNEatkeep 	 * wit-inx Cont *_frhsctlHat lytq
+deOd_cn.qs(t_< q->siOk,sg2slow _/ikb_
 			bL,il(&q->deOd_cnc",
+	 &s tich
+q.qs(t /ho+ tich
+ist  ._cwnd.+=aLL,
+	 &rc+ tich
+ist  .	 * wit /ho+ckro*retu0;frh}
+
+kich
+ist  .drops /ho+ck
+	{Ntpb/tT_CON+rro*retuaET_XMIT_DROPrcA}
+
+i1rRe
 			f	 * wit-se c/homr6g_snd_nx */(CK we m	Lript_REJECrym +em/re		/* Here _nPrspace > sk-4-tcp_delQdisc-20ch)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+ts4.2ro* =+=+ sctl(ro*H= q->qdisc_mops
+
e		/* Hee-4-q->qdisc )kb);
 }+ckich
+q.qs(t /ho+N+rro*returo* =+}&(se50roc_s */
 			     m +em/dropHere _nPQdisc* 0ch)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+t */
 			     s(t =+=+ sctl(llOHh	q->qdisc_mops
+dropHq->qdisc  +->s0g2slow ich
+q.qs(tome ow ich
+ist  .drops /ho+c}N+rro*retus(t =+}
+
+i1rDe
 			f	 * wima+ *  Move a,hi	 * wit0To_.2are +	 *WNEatntcp from To
dveOd_ holds,*a+ *  l@ -lo00To
dund Tlys,* qdisc4-E lOHju -lca,hiPT		/* ae *_fript_REJere _nPrspace > m +em/dT		/* Here _nPQdisc-20ch)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+ticp_delrspace > sk-;i+opiusedNlibHetAold;i+e+	PSCHED_GET_TIME(oldur rhwhile b0;
bi=aLL,_peek(&q->deOd_cn  +->sammay(co+-> besbeecp_delm +em/ikb_ bN* b
+ ck og besbeecp_delm +em/ikb_ bN*aLL,
+cb;i+oold + PT_OWN
+ ck oPSCHED_US2JIFFIErPSCHED_TDIFF(c,
+libHeto_ntcp,Aold)) =+  pr_debug("m +em/dT		/* : PT_OWN
 			f%p@%lu %ld\n",
+ ck sk-4-jo
-ies, PT_OW) =+=+ 	/*rsctmor_nx */(remains,*? *_frhled2tiT_OWN>s0g2slow <mop_ore
+(&q->ore
+, jo
-ies + PT_OW) =+w <b+	 k =+w }low _/ikb_unHankHee-4-&q->deOd_cn  =+=+ 	o alq->qdisc_mea		/* Hee-4-q->qdisc ;
+ ckich
+ist  .drops /ho+c}
+
+kik-Hh	q->qdisc_mdT		/* Hq->qdisc ;i+hsctligbpAlow ich
+q.qs(tome owro*retusk-+ +}&(se50roc_svfousm +em/wtcp.dog( */
 			 ld + arg)n+et+ticp_delQdisc-20cht og2Oo OryQdisc-2)arg;p+=+ pr_debug("m +em/wtcp.dog:K wr		 @%lu\n", jo
-ies) =+ tptifbsusedule/tch
+dev) =+}&(se50roc_svfousm +em/rec	2/tre _nPQdisc-20ch)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+e+	qdisc/rec	2/q->qdisc ;i+kik-_
 			bpurge(&q->deOd_cn  =+=+ ich
+q.qs(t_no_ts+/PT__ore
+_sync(&q->ore
+) =+}&(se50roc_ss4.2sdoa wfo_liOk,g2Oo OryQdisc-2qar    siOk,)n+et+        ;cp_delr,attragr_T;p+ts4.2ro*_no-ENOMEM =+N+rr_TN= km@@ vc(RTA_LENGTHPltering2Oo Orytn_ wfo_qopd))00GFP_KERNEL ;i+/sctlr,ag2slow r_T
+
ta_CypF+= RTM_NEWQDISC;iow r_T
+
ta_s(t_noRTA_LENGTHPltering2Oo Orytn_ wfo_qopd));Alow (g2Oo Orytn_ wfo_qopd-2)RTA_on f(r_T )->siOk,+= siOk,tpow o+ckro*H= q->ops
+g_snd_(qarr_T tp+ckk
+	{(r_T tp+c}N+rro*returo* =+}&(se50roc_s    m +em/g_snd_(;cp_delQdisc-20ch4-tcp_delr,attragopd)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+ticp_deltn_m +em/qopd-2qopd-= RTA_on f(opd);p+ticp_delQdisc-2childe +ts4.2ro* =+=+ sctlopd->
ta_s(t_<oRTA_LENGTHPltering*qopd)) }+ckro*retu-EINVAa =+=+ child = qdisc/dreaiAodflt/tch
+dev, &p wfo_qdisc/ops);o+to al!child) +ckro*retu-EINVAa =+=+ ro*H= sdoa wfo_liOk,gchild4-qopd->siOk, ;i+ s,arro*;2slow qdisc/destroy/child)ho+ckro*returo* =+ate+=+ ich_t+	{Nlpv4/tch ;i+ s,archild)(co+-> hild = xchg(&q->qdisc4-child)ho+cks,archild+->s&noop_qdisc 
+ ckqdisc/destroy/child)ho+clow q->snd_ncy =-qopd->snd_ncy;tow q->jitfer =-qopd->jitfer
-	otq->siOk,+= qopd->siOk,e 	otq->gapkb qopd->gap
-			q->l 0; = qopd->s 0;
-		}=+ ich_t+	{NunHpv4/tch ;i+N+rro*retu0 =+}&(se50roc_s    m +em/cp_rtt_esdelQdisc-20ch4-tcp_delr,attragopd)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+ts4.2 Wr;i+=+ sctl!opd)n+ckro*retu-EINVAa =+=+ MOD INC_USE_COUNT;i+kik-_
 			bvega/cp_rt&q->deOd_cn  =+hq->qdisckb &noop_qdisce >v
+s	k,_ore
+(&q->ore
+) =+	q->ore
+.funtp->ve=sm +em/wtcp.dog =+	q->ore
+.ET_TN og */
 			 ld +) sus =+	q-> buffer no_ts+=+ j_bi=am +em/g_snd_(;ch4-opd);p+/sctlerr+->s0gn+ckMOD DEC_USE_COUNT;i+hro*retu Wr;i+}&(se50roc_svfousm +em/destroy/tre _nPQdisc-20ch)n+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+e+	PT__ore
+(&q->ore
+) =+e+	qdisc/destroy/q->qdisc ;i+hq->qdisckb &noop_qdisce >v
+MOD DEC_USE_COUNT;i+}&(se50roc_s    m +em/dumpHere _nPQdisc-20ch4-tcp_delaspace > sk->r+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+t */
 			 g_sr	 *bi=aLL,
+tail;p+ticp_deltn_m +em/qopd-qopd;p+e+	qopt.snd_ncy =-q->snd_ncy;t+	qopt.jitfer =-q->jitfer
-	oqopt.siOk,+= tch
+dev
+tx_
 			b	 &rc+ qopt.s 0; = q->s 0;
-		qopt.gapkb q->gap
-	-		RTA_PUTHee-4-Tf dfPTIONS,titeringqopd), &qopd);p+N+rro*retuLL,
+	 &rc+
+r,attr_failure:	+tikb_trien00000b atiL,
+da_T tp+/ro*retu-1;i+}&(se50roc_s    m +em/dump_classHere _nPQdisc-20ch4- */
 			 ld + cl,
+ ck -tcp_delaspace > sk-4-tcp_deltcmsg *tcm>r+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_T*)tch
+dT_T;p+e+	le =clH->s1) 	/*ronlydone class *_frhlro*retu-ENOENT;i+frhtcm
+tcm__sndle |BICT_H_MIN(1 tp+/tcm
+tcm_infoHh	q->qdisc_m_sndle;i+N+rro*retu0 =+}&(se50roc_s    m +em/grafrtt_esdelQdisc-20ch4- */
 			 ld + arg4-tcp_delQdisc-2new,
+ c     ;cp_delQdisc-2*old) +et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+e+	le =_dwHh-	ammay
+ c_dwHh &noop_qdisce >v
+ich_t+	{Nlpv4/tch ;i+ *old = xchg(&q->qdisc4-_dw ;i+hqdisc/rec	2/*old);=+ ich
+q.qs(t_no_ts+/ich_t+	{NunHpv4/tch ;i+N+rro*retu0 =+}&(se50roc_stcp_delQdisc-2ne+em/leaftt_esdelQdisc-20ch4- */
 			 ld + arg>r+et+ticp_delm +em/iusedNET_TN*qt og2Oo Orym +em/iusedNET_TN*)tch
+dT_T;p+tro*retuq->qdisc =+}&(se50roc_s */
 			 ld + m +em/g	2/tre _nPQdisc-20chart amclassid) +et+tro*retu1;i+}&(se50roc_svfousm +em/purtt_esdelQdisc-20ch4- */
 			 ld + arg) +et+}&(se50roc_s    m +em/g_snd__classHere _nPQdisc-20ch4-  amclassid4-  ampa_dT2id4-
+ ck -  ;cp_delr,attrag*tca4- */
 			 ld + *arg>r+et+tro*retu-ENOSYS;i+}&(se50roc_s    m +em/del +ett_esdelQdisc-20ch4- */
 			 ld + arg>r+et+tro*retu-ENOSYS;i+}&(se50roc_svfousm +em/wtlkHere _nPQdisc-20ch4-tcp_delqdisc/wtlknt *wtlknt)
+HeA?sctl!wtlknt
+isopg2slow sctlwtlknt
+ buff l=owtlknt
+ikip 
+ cksctlwtlknt
+fn(;ch4-1,owtlkntC < 0g2slow <	wtlknt
+isopN= 1e ow <	ro*retchow <}low wtlknt
+ buff /ho+c}
+}&(se50roc_stcp_deltcf_protoag*m +em/find_tcfHere _nPQdisc-20ch4- */
 			 ld + cl>r+et+tro*retuamma =+}&(se50roc_stcp_delQdisc_class/ops+m +em/glass/ops+= {p+	.grafr	k=	m +em/grafr,
+ .leaf	k=	m +em/leaf,
+ .ger	k=	m +em/ger,
+ .pur	k=	m +em/pur,
+ .g_snd_	k=	m +em/g_snd__class,
+ .del +e	k=	m +em/del +e,
+ .wtlk	k=	m +em/wtlk,
+ .tcf_g_sink=	m +em/find_tcf,
+ .dump	k=	m +em/dump_classrel};
+
+50roc_stcp_delQdisc_ops+m +em/qdisc/ops+= {p+/.idck=	"m +em",
+ .gl/opsck=	&m +em/glass/ops,
+ .p-rvar MFk=	ltering2Oo Orym +em/iusedNET_T),
+ .ea		/* k=	m +em/en		/* ,
+ .de		/* k=	m +em/dT		/* ,p+/.rT		/* k=	m +em/re		/* ,
+ .drop	k=	m +em/drop,
+ .snk,	k=	m +em/cp_r,p+/.rTser	k=	m +em/rTso*;p+/.dTstroyk=	m +em/destroy,
+ .g_snd_	k=	m +em/g_snd_,
+ .dump	k=	m +em/dumprel};
+
+se50roc_s    _/cp_rym +em/mopule/cp_rtvoid) +et+tro*retu "gisp_faqdisc(&m +em/qdisc/ops) =+}&(50roc_svfous__ex_rym +em/mopule/ex_rtvoid) +et+tun "gisp_faqdisc(&m +em/qdisc/ops) =+}&(mopule/cp_rtm +em/mopule/cp_r)&(mopule/ex_rtm +em/mopule/ex_r)&(MODULE_LICENSE("GPL"CON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->aused/aus_tbfy maxwin),{
@@ -352,6 +3aused/aus_tbfy  vic  tcp_clamp_windowaused/aus_tbfy 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oaused/aus_tbfy 
 }
 
+@ -160,7 5:1 &sysctl_tcp_defaucp.l201i7 +201i7 cp.ipt_REJere _nPrspace > tbf/dT		/* Here _Dt = sctligbpACK hopiusedNlibHetAold;iphold + toks;i+oold + toks, PT_OW = oold + ptoks_no_ts oo */
 			     s(t =aLL,
+	 &rc ucp.l229, Re+229, 2 cp.ipt_REJere _nPrspace > tbf/dT		/* Here _Dt ckro*retusk-+ c.bitcoy to al!tptifb
 			bstopped/tch
+dev)g2sl- cold + PT_OWN= PSCHED_US2JIFFIErmax_t(ld +, -toks, -ptoks)) =+  PT_OWN= PSCHED_US2JIFFIErmax_t(ld +, -toks, -ptoks)) =  */
+o aliT_OWN=);
 }-d <	PT_OWN= 1e +
+o aliT_OWN=);
 }+ <	PT_OWN= 1e   -d <mop_ore
+(&q->wp_ore
+, jo
-ies+PT_OW)+ y t}o+ <mop_ore
+(&q->wp_ore
+, jo
-ies+PT_OW)+ t = 	/*rMaybe we have aeehortnt 	 * wi in0To
d		/* ,
 ck - whicha+Hanbe so vaold. It s0unds cool,
cp.l503i6 +501i11 cp.ipt_REJvfoustbf/wtlkHere _nPQdisc-20ch4-tcpit itcoe50roc_stcp_deltcf_protoag*tbf/find_tcfHere _nPQdisc-20ch4- */
 			 ld + cl>r+et+tro*retuamma =+}&(s 50roc_stcp_delQdisc_class/ops+tbf/glass/ops+=r 	_ 0.grafr	k= 	tbf/grafr,
cp.l512i6 +515i7 cp.ipt_REJere _nPQdisc_class/ops+tbf/glass/_ 0.g_snd_	k=	tbf/g_snd__class,
  .del +e	k=	tbf/dTl +e,
  .wtlk	k=	tbf/wtlk,
+ .tcf_g_sink=	tbf/find_tcf,
  .dump	k=	tbf/dump_classre }+ t  = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/associolay maxwin),{
@@ -352,6 +3autp/associolay  vic  tcp_clamp_windowautp/associolay 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/associolay 
 }
 
+@ -160,7 7:35&sysctl_tcp_defaucp.la,5=+1,57 +
 6 1
CTP umedAsu "fe_dTce Isnd_mo v	queu
- * (C) Copyright IBM Corp.  }
1,o }
3a+ * (C) Copyright IBM Corp.  }
1,o }
4
  * Copyright (c) 1999- }
0 Cisco, Inc.
  * Copyright (c) 1999- }
1 Motorola, Inc.
  * Copyright (c)  }
1 IntAsuCorp.ucp.l210i6 +210i7 cp.ipe _nPrutp_associ	queu *rutp_associ	que
  asoc->ajet_tst =aasoc->c.snk,ial_tst+ t = asoc->ctst_ * _po    =aasoc->ajet_tst - 1e +
asoc->adv_peer_ * _po    =aasoc->ctst_ * _po   ; = asoc->highest_s * wd =aasoc->ctst_ * _po   ; = asoc->last_cwr_tst =aasoc->ctst_ * _po   ; = asoc->un * _ET_TN o_tscp.l261, 2 +262e6 cp.ipe _nPrutp_associ	queu *rutp_associ	que
 
 	/*rCreaiA Hanoutput0		/* .  *_f 	rutp_outq/cp_rtasoc, &asoc->outq	/* )+ y rutp_outq/sdoaoutput__sndlers(&asoc->outq	/* ,}-d <	      ;utp_	 * wi/snk,,p*/ <	      ;utp_	 * wi/ceturg,p*/ <	      ;utp_	 * wi/append_chunk,p*/ <	      ;utp_	 * wi/transmit_chunk,p*/ <	      ;utp_	 * wi/transmit)+ t = o al!;utp_ulpq/cp_rt&asoc->ulpq,aasoc))nt		gotoafail/cp_rtscp.l478i1cp_473,8 cp.ipe _nPrutp_transportd*rutp_assoc_add_pe
 	/*rk, iasoc->peer.portdmight notnbe meaningful yo*;-se   hv* snk,ialter0To
d	 * wi ipe _nurA Hayway.  hv*/p*/(asoc->outq	/* .snk,aoutput)(&peer->p * wi,p*/ <	     peer,p*/ <	     asoc->base.bind_addr.port,p*/ <	     asoc->peer.port);=+ ictp_	 * wi/snk,(&peer->p * wi, peer, asoc->base.bind_addr.port,p+ ck asoc->peer.port);= 
 	/*r7.2.1 Slow-Star   hv*scp.l611r7 +604i7 cp.vfousrutp_assoc_ beerol_transport(t_esde
 	switcha(commsndpACK hcase1
CTP_TRANSPORT_UP:nt		transport->acwiv
d=1
CTP_ACTIVE+ y tspc_ipt_
d=1
CTP_ADDR_REACHABLEe +
+spc_ipt_
d=1
CTP_ADDR_AVAILABLEe   <b+	 k = K hcase1
CTP_TRANSPORT_DOWN:scp.l958i6 +951i9 cp.vfousrutp_assoc_mig
d;_(ipe _nPrutp_asso
.vfousrutp_assoc_updd;_(ipe _nPrutp_associ	queu *asoc,
 ck -  -  ;cp_delrutp_associ	queu *_dw 
Net+ticp_delrutp_transportd*trans;p+ticp_deliAs,ivegas*pos, *+emp
-	- 	/*rCopy in0_dwHparamebou *of peer. *_f 	asoc->ci=am w->c; = asoc->peer.rwndi=am w->peer.rwndtscp.l966i22 +962i22 cp.vfousrutp_assoc_updd;_(ipe _nPrutp_assocf 	rutp_tstmap/cp_rt&asoc->peer.tst_map,1
CTP_TSN_MAP_SIZE,
 ckk asoc->peer.i.snk,ial_tst) =  *//*rFIXME: */ *    Do we newd toacopy priwiny_	 th etc? */ * */ *    Mor_nexplicitly, addresatsdmd_ have beetu "movwd mpl
*/ *    trt *newds ac buffs,* for.
*/ *_frhi1rRemove any peer addresatsdnotnprTso vain0To
d_dwHassoci	queu. *_frhiAs,ifor_eaus_safe(pos, +emp, &asoc->peer.transport_addr_l@ -g2slow trans+= sis,isReny(pos, icp_delrutp_transport, +ransports)ho+cks,ar!rutp_assoc_lookup_	 ddr=_dw, &+rans->i	 ddr ;
+ ckictp_assoc_PT__peertasoc, &+rans->i	 ddr ho+c}
 
 	/*rI:6To
dcase1t *A (associ	queu rTstar )4- se  hv* snk,ial_tst as ajet_tst.rI:6To
dcase1t *B4- se  hv* me,_dT2najet_tst in0case1ET_TNso vatoapeer  hv* has beetudiscardwd mpl*newds ro*ransmisnv_r.
 hv*/p*/sctlictp_ipt_
tasoc, ESTABLISHED)g2sl-eA?sctlasoc->ipt_
d>=1
CTP_STATE_ESTABLISHED)ACK hoasoc->ajet_tst =am w->ajet_tst;K hoasoc->ctst_ * _po    =am w->ctst_ * _po   ; +	
asoc->adv_peer_ * _po    =am w->adv_peer_ * _po   + t = 	/*rResnk,ialter0SSNH
datboth local icpeams
 ck * mpl*peer's icpeams.ucp.l989i Re+985i23 cp.vfousrutp_assoc_updd;_(ipe _nPrutp_assocf 	kictp_sstmap/clearlasoc->istmap);= 
 	} jeY22slow /*rAdd any peer addresatsdfrom To
d_dwHassoci	queu. *_frhhiAs,ifor_eaus(pos, &m w->peer.transport_addr_l@ -g2slow  trans+= sis,isReny(pos, icp_delrutp_transport, ow <	k - +ransports)ho+ckks,ar!rutp_assoc_lookup_	 ddr=asoc, &+rans->i	 ddr ;
+ ck	rutp_assoc_add_peertasoc, &+rans->i	 ddr, ow <	kk -  GFP_ATOMIC)ho+ck}&(s hoasoc->ctst_ * _po    =aasoc->ajet_tst - 1e +

asoc->adv_peer_ * _po    =aasoc->ctst_ * _po   ; = ks,ar!asoc->istmap)ACK ho	/*rMove To
distmap. *_f 	

asoc->istmap =am w->istmap; = k	m w->istmap =uamma =c.bitcbit-t itco 6 1Updd;_ To
dro*ran 	 th 
datntcps,* _ ro*ransmitbed p * wimacp.la205i7 +1210i7 cp.s4.2sutp_assoc_sdoabind_addr_from_ bokier 	_ 0s4.2varar MF2 =amtohs( bokie->peer/cp_r
+g_unk_hdr.length ;i 0s4.2varar MF3 =a bokie->raw_addr_l@ -b	 &rc-	__u8 *rawt og__u8 *) bokie + ltering2Oo Orysutp_ bokie) + varar MF2e +
__u8 *rawt og__u8 *) bokie->peer/cp_r + varar MF2e  
 	ro*retusutp_raw_toabind_addrs(&asoc->base.bind_addr, raw,2varar MF3,
 ckkk -  - asoc->ep->base.bind_addr.port, gfpCON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/g_unky maxwin),{
@@ -352,6 +3autp/g_unky  vic  tcp_clamp_windowautp/g_unky 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/g_unky 
 }
 
+@ -160,7 5:34&sysctl_tcp_defaucp.la,5=+1,57 +
 6 1
CTP umedAsu "fe_dTce Isnd_mo v	queu
- * Copyright (c)  }
3 IntArn	queual Businesa MausinesuCorp.u+ * (C) Copyright IBM Corp.  }
3,o }
4
  *
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
 v*scp.l31i6 +31i7 cp
  *
  * Writbenx C mopacied by:
  *    Jeu Griwm             <jgriwm@us.ibm.com>a+ *    Sridhar Samudrala     <sri@us.ibm.com>a  *
  * Any bugsnreportnd giv
natoaus we  *,hienyatoafix... any fixesusharnd  *,h
  * b	 l4corpo
d;_d000000To
dajetd
CTP release.
cp.l55i7 +56,8 cp.vfousrutp_ET_Tmsg/cp_rtt_esdelrutp_ET_Tm = atomic_sdo(&msg
+
efcnt, 1 ;i 0msg
+ntcp_failwd =a0;i 0msg
+ntcp_error no_ts-0msg
+can_expire_no_ts+/msg
+can_abdndon_no_ts+/msg
+expires_at =a0;i 0INIT_LIST_HEAD(&msg
+g_unks)ho itcocp.la85i27 +187i Recp.ipe _nPrutp_ET_Tmsgd*rutp_ET_Tmsg/from_u = 	/*rsinfo_ore
toliv
dit-inxm*,hise beds *_f 	
msg
+expires_at =ajo
-ies +
 ckkk -  -
CTP_MSECS_TO_JIFFIES(sinfo
+ninfo_ore
toliv
)+ y tmsg
+can_expire_no1e +

msg
+can_abdndon_no1e +


CTP_DEBUG_PRINTK("%s: msg:%p expires_at: %ldajo
-ies:%ld\n",
+ ckk -__FUNCTION__, msg, msg
+expires_at, jo
-ies) = bitcoy /*rWo_.2it-_ roason,
+	Hfragmo v	queu po    right now?v*/p*/max =aasoc->pmtu;p*/sctlmax <-
CTP_MIN_PMTU }-d max =a
CTP_MIN_PMTU;p*/max -=a
CTP_IP_OVERHEAD;p*oy /*rMak
diurA notnbeybeddmdximum g_unk lter.v*/p*/sctlmax >a
CTP_MAX_CHUNK_LEN }-d max =a
CTP_MAX_CHUNK_LENts+/max =aasoc->frag_po   + t y /*rSub*ra_nPoe cTo
dovervegasl:6a1ET_TNg_unk vegaer. *_f*/max -=altering2Oo Orysutp_ET_T_chunk) = bwhole_no_ts*oy /*rI:6 ser has specacied sm@@ er fragmo v	queu, mak
dit s0.v*/p*/sctlictp_ik(asoc->base.sk)-> ser_frag }-d max =amin_ (l4., max, ictp_ik(asoc->base.sk)-> ser_frag ts*o 	 wre__s(t_nomax;= 
 	/*rE4courage Cookie-ECHO bund
+ g.v*/pcp.l299, Re+288i11 cp.errout:t itco 6 1Check wheuo T trt *mesaage has expired.v*/p*s4.2sutp_ET_Tmsg/expiresg2Oo Orysutp_ _unk *chunk)
+s4.2sutp_g_unk_abdndoned/tOo Orysutp_ _unk *chunk)
 	_ 0ipe _nPrutp_ET_Tmsgd*msgd=Ng_unk->msg =  *//*rFIXME:rWo(t_PR-
CTP t *supportnd wea+Hanmak
dtrt 
*/ * check mor_ns(tio v.
*/ *_f*/sctl!msg
+can_expire)eA?sctl!msg
+can_abdndon)nt		ro*retu0 =t = o allibHeaftAr(jo
-ies, msg
+expires_at ;
cp.l316i7 +302i7 cp.s4.2sutp_ET_Tmsg/expiresg2Oo Orysutp_ _ut itco 6 1trt * _unk (mpl* besT		/ntly dT2ire*mesaage) has failwd inxitstntcps,*.v*/p*vfousrutp_ET_Tmsg/fail/tOo Orysutp_ _unk *chunkar    error)eAvfousrutp_g_unk_fail/tOo Orysutp_ _unk *chunkar    error)eACK hc_unk->msg
+ntcp_failwd =a1e  hc_unk->msg
+ntcp_error noerrorON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/grc32cy maxwin),{
@@ -352,6 +3autp/grc32cy  vic  tcp_clamp_windowautp/grc32cy 
 }
3-11-28 18:2,7 "autotuning" code.
+ *
+ * THeAalgorithm +oautp/grc32cy 
 }
 
+@ -160,731:2,&sysctl_tcp_defaucp.l69r7 +69i7 cp
 6 1 *sk,24 mpl*32 Parity Bits",                                  *_f /*rIEEE Transatp->vs eu Communic	queus, Vol.41, No.6, June 1993  *_f /*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*r*/p*__u amcrc_c[256]+= {p+ipt_REJ besbe__u amcrc_c[256]+= {p 	0xysctl_tc, 0xF26B83
3,o0xE13B70F7,o0x1350F3F4,p 	0xC79A971F,o0x35F1141C,o0x26A1E7E8,o0xD4CA64EB,p 	0x8AD958CF,o0x78B2DBCC,o0x6BE22838,o0x9989AB3B,p = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/debugy maxwin),{
@@ -352,6 +3autp/debugy  vic  tcp_clamp_windowautp/debugy 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/debugy 
 }
 
+@ -160,7 7:44&sysctl_tcp_defaucp.la,8=+1,87 +
 6 1
CTP umedAsu "fe_dTce Isnd_mo v	queu
+ * (C) Copyright IBM Corp.  }
1,o }
4
  * Copyright (c) 1999- }
0 Cisco, Inc.
  * Copyright (c) 1999- }
1 Motorola, Inc.
  * Copyright (c)  }
1 IntAsuCorp.u- * Copyright (c)  }
1 IntArn	queual Businesa MausinesuCorp.u  * 
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
 v*cocp.l43i6 +43i7 cp
  *    Xs,*ang Guo           <xs,*ang.guo@intAs.com>a  *    Jeu Griwm             <jgriwm@us.ibm.com>a  *    Daisy1Changk -  <daisyc@us.ibm.com>a+ *    Sridhar Samudrala	    <sri@us.ibm.com>a  * 
  * Any bugsnreportnd giv
natoaus we  *,hienyatoafix... any fixesusharnd  *,h
  * b	 l4corpo
d;_d000000To
dajetd
CTP release.
cp.l88i6 +89i9 cp. besbeg_srd*rutp_cnameg besbeectp_iub*ypK hcase1
CTP_CID_ASCONF_ACK:nt		ro*retu"ASCONF_ACK" =t +hcase1
CTP_CID_FWD_TSN:frhlro*retu"FWD_TSN"
-	- 	default:nt		ro*retu"unknown* _unk" = biON = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/ipv6y maxwin),{
@@ -352,6 +3autp/ipv6y  vic  tcp_clamp_windowautp/ipv6y 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/ipv6y 
 }
 
+@ -160,7 8:3 &sysctl_tcp_defaucp.l1r7 +1i7 cp
 6 1
CTP umedAsu "fe_dTce Isnd_mo v	queu
+ * (C) Copyright IBM Corp.  }
2,o }
4
  * Copyright (c)  }
1 Nokia, Inc.
  * Copyright (c)  }
1 La MontA H.P. Yarro,h
- * Copyright (c)  }
2- }
3 IntArn	queual Businesa Mausines,uCorp.u  * Copyright (c)  }
2- }
3 IntAluCorp.u  *
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
cp.l703,7 +703,7 cp.ipt_REJvfousectp_inet6_ev
nt_msgnamegtOos oo *ueu sutp_addrd*addr =c.bipe _nPrutp_associ	queu *asoce   -d asoc noev
nt
+nndrcvinfo.ninfo_assoc_ide +

asoc noev
nt
+asoce  k	rutp_inet6_msgnamegmsgname, addrs(t)e  k	rin6t og2Oo Orysockaddr_in6t*)msgnamee  k	rin6
+nin6_portd= htbes(asoc->peer.port);= = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/objc v. maxwin),{
@@ -352,6 +3autp/objc v.  vic  tcp_clamp_windowautp/objc v. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/objc v. 
 }
 
+@ -160,7 7:25&sysctl_tcp_defaucp.la32r7 +132i7 cp.vfousrutp_dbg_objc v/cp_rtvoid)  6 1CleanupNEo
dobjcbuff sRenyain0To
dproc filesystem.  *_f vfousrutp_dbg_objc v/ex_rtvoid) 2sl-  "movw_procisReny("rutp_dbg_objcbuff", proci_doarutp tp+/romovw_procisReny("rutp_dbg_objcff", proci_doarutp tp itco = = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/output. maxwin),{
@@ -352,6 +3autp/output.  vic  tcp_clamp_windowautp/output. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/output. 
 }
 
+@ -160,7 8:13&sysctl_tcp_defaucp.l62,29 +62,357 +
 #l4clude <m +oautp/sm.h>tco 6 1Forwaras_Cclar	queus 
datp-rvd;_ helpers.v*/p*ipt_REJvfousectp_	 * wi/rec	2/tre _nPectp_	 * wi *	 * wi tp ipt_REJectp_xmit_nPectp_	 * wi/append_ET_T/tre _nPectp_	 * wi *	 * wi,
 ckkk	-  ;cp_delrutp_ _unk *chunk);tco 6 1Ceturgua p * wima- * trt *appearsatoabe aefo,howupNc	2/l:6snk,ialte	queus.)
+ * trt *appearsatoabe aefo,howupNc	2/l:6snk,ialte	queus.
  *_f tre _nPectp_	 * wi *;utp_	 * wi/ceturg/tre _nPectp_	 * wi *	 * wi,
*/ <	      e__u amvtagar    ecn_cap,
+	,
*/ <	      e;utp_	 * wi/p_sndler_i *	repend__sndler)
+ ckk -    e__u amvtagar    ecn_cap,
+	) 2sl-     	 * wi/emptWN= (	 * wi
+nizeN=);
CTP_IP_OVERHEAD);p+ticp_delrutp_ _unk *chunk =uamma =+N+r
CTP_DEBUG_PRINTK("%s: 	 * wi:%p vtag:0x%x\n", __FUNCTION__,
+ ck -p * wi, vtag);= 
 		 * wi
+vtag =uvtag;p*/	 * wi
+ecn_cap,
+	 noecn_cap,
+	;p*/	 * wi
+gwi/prepend_chunk =u	repend__sndler;
 		 * wi
+has_ bokie_echo =a0;i 0	 * wi
+has_s *  =a0;i 0	 * wi
+ipfrago  =a0;i oy /*rWedmight newd toaca,hiTo
dprepend__sndler right away.  *_f*/sctl	 * wi/emptW }-d ectp_	 * wi/rec	2/	 * wi tp+/sctlecn_cap,
+	 &&e;utp_	 * wi/emptW/	 * wi )(co+-> hunk =u;utp_gwi/ecne/prepend(	 * wi
+transport->asoc);=+=+ 	/*rI:6To
rA H2it-_ prepend g_unk l_REkdit on0To
dl@ -lbe
da =+  k * mpy ouo T g_unks gwi appendcn.=+  	 *_frhled2tchunk)
+	d ectp_	 * wi/append_chunk(p * wi, chunk);t+k}&(s hro*retup * wiho itcocp.l93,19 +99,-16cp.ipe _nPrutp_	 * wi *;utp_	 * wi/cp_rtt_e
 ckkk -  -icp_delrutp_transportd*transport,  ckkk -  -__u16 sport, __u16 dport)
Net+ticp_delrutp_associ	queu *asocN= Lransport->asoc;p+tiize_i overvega =+N+r
CTP_DEBUG_PRINTK("%s: 	 * wi:%p Lransport:%p\n", __FUNCTION__,
+ ck -p * wi, Lransport)
-	- 		 * wi
+transportN= Lransport;i 0	 * wi
+s0ur+	_portd= sport;i 0	 * wi
+destin	queu_portd= dport;i 0ik-_
 			bvega/cp_rt&	 * wi
+g_unks)ho*/	 * wi
+nizeN=a
CTP_IP_OVERHEAD;pA?sctlasocg2slow icp_delrutp_opd-2sp =u;utp_ik(asoc->base.sk);clow overvegas= sp->pf->af->aj,ivegaer_	 &rt +h} jeY22slow overvegas= stering2Oo Oryipv6hdr ho+c}
+ overvegas+=altering2Oo Orysutphdr ho+c	 * wi
+overvegas= overvega =+/	 * wi
+nizeN=aovervega = 		 * wi
+vtag =u0;p*/	 * wi
+ecn_cap,
+	 no0;p*/	 * wi
+gwi/prepend_chunk =uamma =c.	 * wi
+has_ bokie_echo =a0;i 0	 * wi
+has_s *  =a0;i 0	 * wi
+ipfrago  =a0;i 0	 * wi
+m@@ vcwd =a0;i- ectp_	 * wi/rec	2/	 * wi tp hro*retup * wiho itcocp.l114i6 +131i8 cp.vfousrutp_	 * wi/
+	{(ipe _nPrutp_	 * wi
 	_ 0ipe _nPrutp_ _unk *chunk =t +h
CTP_DEBUG_PRINTK("%s: 	 * wi:%p\n", __FUNCTION__, 	 * wi tp+
         while b0chunk =u/tOo Orysutp_ _unk *)_/ikb_dT		/* H&	 * wi
+g_unks)))nt		rutp_g_unk_f+	{(chunk);tcocp.la34i6 +153i9 cp.ectp_xmit_nPectp_	 * wi/transmit_chunk(sf 	rutp_xmit_nPro*val;i 0s4.2error no_tst +h
CTP_DEBUG_PRINTK("%s: 	 * wi:%p chunk:%p\n", __FUNCTION__,
+ ck -p * wi, chunk);t+
 	switcha((ro*val =u/tctp_	 * wi/append_chunk(p * wi, chunk)))pACK hcase1
CTP_XMIT_PMTU_FULL: = ks,ar!	 * wi
+has_ bokie_echopACKcp.la48r7 +170e6 cp.ictp_xmit_nPectp_	 * wi/transmit_chunk(sf 	bitcb<b+	 k = K-hcase1
CTP_XMIT_MUST_FRAG:K hcase1
CTP_XMIT_RWND_FULL: = case1
CTP_XMIT_OK: = case1
CTP_XMIT_NAGLE_DELAY:ucp.l201i6 +222i9 cp.ectp_xmit_nPectp_	 * wi/append_chunk(t_e
 ciize_i pmtu;p 0s4.2tooabigtst +h
CTP_DEBUG_PRINTK("%s: 	 * wi:%p chunk:%p\n", __FUNCTION__,-p * wi,
+ ck -chunk);t+
 	ro*val =uectp_	 * wi/bund
e_s * (p * wi, chunk);t 0	nizeN=a	 * wi
+nizerc ucp.l215,17 +239i Recp.ictp_xmit_nPectp_	 * wi/append_chunk(t_e
 
 	/*rDeciderillwe newd toafragmo vx C recubOk,+snd_r. *_f 	o allooabigg2sl- c    	 * wi/emptWN= (	 * wi
+nizeN=);
CTP_IP_OVERHEAD);p- = 	/*rBoth  beerol g_unks mpl*ET_TNg_unkt- *sk,TSNs2are
 ck * non-fragmo v	
+	.
 ck */oy to al	 * wi/emptWN|| !rutp_g_unk_is_ET_T/chunk))2slow sctl;utp_	 * wi/emptW/	 * wi N|| !rutp_g_unk_is_ET_T/chunk))2sl ho	/*rWA no ld + T do re-fragmo v	queu.
 ckk * Ju -lfragmo vxa cTo
dIP Od_cr,rillwe
 ckk * actu@@ y hit trt * bediqueu
 	ck */oy
 	ck	 * wi
+ipfrago  =a1; = k	gotoaappendrc ucp.l233i9 +254i6 cp.ictp_xmit_nPectp_	 * wi/append_chunk(t_e
 c		ro*val =u
CTP_XMIT_PMTU_FULL; = k	gotoafcp_sh =c.bit-h} jeY22sl-		/*rk, i _unk fiit-inxTo
d	 * wi.  *_f*/	gotoaappendrc c}
 
 append:ucp.l260i6 +278i7 cp.append:u 	/*rI.2it-OKNEatntcp trt * _unk.  *_f 	_/ikb_
 			bL,il(&	 * wi
+g_unks,u/tOo Orysspace > )chunk);t 0	 * wi
+nizeN+=Ng_unkb	 &rc+ c_unk->transportN= 	 * wi
+transport;t fcp_sh:p hro*returo*val;i }ucp.l283i6 +302i8 cp.s4.2sutp_	 * wi/transmit(ipe _nPrutp_	 *f 	_/u8 has_ET_TN o_ts 0ipe _nPds,isReny *ds, =t +h
CTP_DEBUG_PRINTK("%s: 	 * wi:%p\n", __FUNCTION__, 	 * wi tp+
 	/*rDo NOT gwneraiA HNg_unklesa 	 * wi. *_f 	chunk =u/tOo Orysutp_ _unk *)LL,_peek(&	 * wi
+g_unks)ho 	o alunHat lyt!chunk))pcp.l297i7 +318i7 cp.s4.2sutp_	 * wi/transmit(ipe _nPrutp_	 *f 		gotoanomem;= 
 	/*rMak
diurA Eo
doutb0undusk- has enough vegaer room recerved.v*/p*0ik-_recerve(nsk-4-
CTP_IP_OVERHEAD);p+tik-_recerve(nsk-4-	 * wi
+overvega);= 
 	/*rSe cTo
downs,* so* wi io0To_.2we koldiwo
rA toage cTo
  hv* destin	queudIP addresa.scp.l471r7 +492i7 cp.s4.2sutp_	 * wi/transmit(ipe _nPrutp_	 *f 	(*tp->af_specacic->ictp_xmit)(nsk-4-tp4-	 * wi
+ipfrago );= 
 out:t*/	 * wi
+nizeN=a
CTP_IP_OVERHEAD;pA?	 * wi
+nizeN=a	 * wi
+overvegatp hro*retu Wr;iano_route:p hk
+	{Ntpb/ntT_CONcp.l497i7 +518i6 cp. Wr:p hgotoaout;ianomem:p hj_bi=a-ENOMEM =*/	rs4.k("%s @@ vcNtpb failwd.\n", __FUNCTION__)ho 	gotoa Wr;iaitcocp.l505,25 +525i6 cp.nomem:p v* 2nduLevel Abs*ra_nueusp v********************************************************************/= K-/*a- * trt *p-rvd;_ funtp->verec	2s0To
d	 * wi toaalfresh ipt_ema- */p*ipt_REJvfousectp_	 * wi/rec	2/tre _nPectp_	 * wi *	 * wi 
-sl-	icp_delrutp_ _unk *chunk =uamma =-t*/	 * wi
+nizeN=a
CTP_IP_OVERHEAD;p-f*/sctl	 * wi
+gwi/prepend_chunk }-d chunk =u	 * wi
+gwi/prepend_chunk(	 * wi
+transport->asoc);=*oy /*rI:6To
rA H2it-_ prepend g_unk l_REkdit on0To
dl@ -lbe
da =-k * mpy ouo T g_unks gwi appendcn.=*/ *_f*/sctlchunk }-d ectp_	 * wi/append_chunk(p * wi, chunk);t-it-t /* trt *p-rvd;_ funtp->ve_sndles0To
dspecacic *of appends,* on f g_unks.  *_f trt_REJectp_xmit_nPectp_	 * wi/append_ET_T/tre _nPectp_	 * wi *	 * wi,
 ckkk	-  ;cp_delrutp_ _unk *chunk)ucp.l609r7 +610i7 cp.ipt_REJectp_xmit_nPectp_	 * wi/append_ET  hv* sf any previous y *ransmitbed ET_TNon0To
d benetp->veremains  hv* un * oldlwdgcn.= hv*/p*/sctl!sp->noPT_OWN&&a
CTP_IP_OVERHEADN=);	 * wi
+nizeN&&eA?sctl!sp->noPT_OWN&&a;utp_	 * wi/emptW/	 * wi N&&e k -  q->outiptnds,*__cwnd.&&a;utp_ipt_
tasoc, ESTABLISHED)g2sl oo */
 			 s(t_noET_TnizeN+ q->out_q	 &rc ucp.l617i7 +618i7 cp.ipt_REJectp_xmit_nPectp_	 * wi/append_ET  hhv* dT_TN *,hifivx C PT_OWNinxhope *of bund
+ gaalfu,h
 hhv* nized p * wima ck */oy to als(t_<oasoc->pmtu --
CTP_IP_OVERHEAD)2slow sctls(t_<oasoc->pmtu --	 * wi
+overvega)2sl ho	ro*val =u
CTP_XMIT_NAGLE_DELAY; = k	gotoafcp_sh =c.bitcp.l637i7 +638,8 cp.ipt_REJectp_xmit_nPectp_	 * wi/append_ET  
= asoc->peer.rwndi=arwndts 	/*rHas beetuaccepbed 
dat*ransmisnv_r. */oy c_unk->msg
+can_expire_no_ts+/s,ar!asoc->peer.prrutp_ ap,
+	) +-> hunk->msg
+can_abdndon_no_ts t fcp_sh:p hro*returo*val;i = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/outq	/* . maxwin),{
@@ -352,6 +3autp/outq	/* .  vic  tcp_clamp_windowautp/outq	/* . 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/outq	/* . 
 }
 
+@ -160,7 6:50&sysctl_tcp_defaucp.la,8=+1,87 +
 6 1
CTP umedAsu "fe_dTce Isnd_mo v	queu
+ * (C) Copyright IBM Corp.  }
1,o }
4
  * Copyright (c) 1999- }
0 Cisco, Inc.
  * Copyright (c) 1999- }
1 Motorola, Inc.
  * Copyright (c)  }
1- }
3 IntAluCorp.u- * Copyright (c)  }
1- }
3 IntArn	queual Businesa MausinesuCorp.u  *
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
 v*scp.l69i6 +69i8 cp.ipt_REJvfousectp_eq =_misnvng/tre _nPect
 	ck     e__u amhighest_new_tst,
 	ck     es4.2cbuff_of_new * s)ho &(50roc_svfous;utp_gwneraiA_fwdtst/tre _nPectp_outq-2qar__u ams * _ctst) =+
 6 1Add dT_TN000To
dfront/l:6To
d		/* . *_f trt_REJEC(di	 vfous;utp_outq/vega/ET_T/tre _nPectp_outq-2qa
 ckkk	;cp_delrutp_ _unk *ch)pcp.l222, 2 +224i7 cp.vfousrutp_outq/cp_rticp_delrutp_associ	qi 0ik-_
 			bvega/cp_rt&q-> beerol);i 0INIT_LIST_HEAD(&q
+
etransmit)+ t0INIT_LIST_HEAD(&q
+s * wd);=*oy q
+snk,aoutput =uamma =-	q-> bturgaoutput =uamma =-	q->append_output =uamma =-	q->build_output =uamma =-	q->
dace_output =uamma =+0INIT_LIST_HEAD(&q
+abdndoned);= 
 	q->outiptnds,*__cwnd. o_ts 0q->emptWN= 1tscp.l252r7 +249i7 cp.vfousrutp_outq/teardown/tre _nPectp_outq
 ckkchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
 ckkk	-  *ransmitbed_l@ -g;l ho	/*rMq = a *part/l:6a failwd mesaage. */oy d ectp_ET_Tmsg/fail/chunkarq->error);
+	d ectp_g_unk_fail/chunkarq->error);
 			rutp_g_unk_f+	{(chunk);tc.bitcbitcp.l262r7 +259i7 cp.vfousrutp_outq/teardown/tre _nPectp_outq
 cksis,iPT__cp_rtlchunk);tc.bchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
 ckkk-  *ransmitbed_l@ -g;l-d ectp_ET_Tmsg/fail/chunkarq->error);
+	dectp_g_unk_fail/chunkarq->error);
 		rutp_g_unk_f+	{(chunk);tc.itcocp.l271r7 +268i16 cp.vfousrutp_outq/teardown/tre _nPectp_outq
 cksis,iPT__cp_rtlchunk);tc.bchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
 ckkk-  *ransmitbed_l@ -g;l-d ectp_ET_Tmsg/fail/chunkarq->error);
+	dectp_g_unk_fail/chunkarq->error);
+		rutp_g_unk_f+	{(chunk);t+ate+=+ /* trrow away any g_unks To_.2are inxTo
dabdndonedd		/* . *_frhiAs,ifor_eaus_safe(lchunkar+emp, &q
+abdndoned)2slow sis,iPT__cp_rtlchunk);t+.bchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
+ckkk-  *ransmitbed_l@ -g;l+	dectp_g_unk_fail/chunkarq->error);
 		rutp_g_unk_f+	{(chunk);tc.itcocp.l279r7 +285i7 cp.vfousrutp_outq/teardown/tre _nPectp_outq
 cwhile b0chunk =urutp_outq/dT		/* /ET_T/q))pACK 
 o	/*rMq = a *ntcp failure. */oy dectp_ET_Tmsg/fail/chunkarq->error);
+	dectp_g_unk_fail/chunkarq->error);
 		rutp_g_unk_f+	{(chunk);tc.itcocp.l363e am+369,-16cp.s4.2sutp_outq/tail/tOo Orysutp_outq-2qarp hro*retu Wror;iaitco-/*rInsert/TNg_unk 00000To
d
etransmit0		/* .  C_unks on0To
d
etransmitu- * 
 			f_re kepb-inx Cont, based on0To
dTSNs.
+i1rInsert/TNg_unk 00000To
dsortnd l@ -lbased on0To
dTSNs. rk, i
etransmit0l@ -
+ * acp tr
dabdndoneddl@ -lare inxascends,*  Cont.
  *_f*vfousrutp_
etransmit_cpsert/tOo OryiAs,ivegas*tlchunkar;cp_delrutp_outq-2q)eAvfousrutp_cpsert_l@ -/tOo OryiAs,ivegas*vegaar;cp_deliAs,ivegas*_dw 
Net-	icp_deliAs,ivegas*rlchunk =-	icp_delrutp_ _unk *tchunkar*rchunk =-	__u amttst, rtst;K+ticp_deliAs,ivegas*pos;p+ticp_delrutp_ _unk *nchunkar*lchunk =+	__u amntst, ltst;K hs4.2done =a0;i oy tchunk =usis,isReny(tlchunkar;cp_delrutp_chunkar+ransmitbed_l@ -g;l-dttst =amtohl(t hunk->subh.ET_T_hdr->tst) =+	nchunk =usis,isReny(_dw, ;cp_delrutp_chunkar+ransmitbed_l@ -g;l+	ntst =amtohl(n hunk->subh.ET_T_hdr->tst) = oy iAs,ifor_eaus(rlchunkar&q
+
etransmit)2sl-		rchunk =usis,isReny(rlchunkar;cp_delrutp_ _unk,
*/ <	    *ransmitbed_l@ -g;l-d rtst =amtohl(r hunk->subh.ET_T_hdr->tst) =y to alTSN_lt(ttst, rtst)g2sl- colis,iadd(tlchunkarrlchunk->prev) =+hiAs,ifor_eaus(pos, vega)2slow schunk =usis,isReny(pos, icp_delrutp_chunkar+ransmitbed_l@ -g;l+		ltst =amtohl(l hunk->subh.ET_T_hdr->tst) =+	to alTSN_lt(ntst, ltst))2slow olis,iadd(_dw, pos->prev) = ckkdone =a1; = k	b+	 k = .bitcbit-/s,ar!doneg2sl- clis,iadd/tail/tlchunkar&q
+
etransmit) =y }s+/s,ar!doneglow sis,iadd/tail/_dw, vega); t itco 6 1Mq = a,hiTo
deligi
+	 	 * wis on0a Lransport 
datro*ransmisnv_r. v*/pcp.l404i6 +408i13 cp.vfousrutp_
etransmit_eq =/tOo Orysutp_outc.bchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
 ckkk-  *ransmitbed_l@ -g;l =+ 	/*rI:6To
Ng_unk 0sdabdndoned, move ii toaabdndoneddl@ -. *_frhled2trutp_g_unk_abdndoned/chunk))2slow  sis,iPT__cp_rtlchunk);t+.b	rutp_cpsert_l@ -/&q
+abdndoned, lchunk);t+.b	 beeinueho+ck}&(s ho/*rI:6w	f_re dos,* ro*ransmisnv_r due toaalfasti
etransmit,
 hhv* onlydTo
Ng_unk's To_.2are eq =ed 
datfasti
etransmit
 hhv* nhouldabe addwd toaTo
d
etransmit0		/* .  I:6w	f_re dos,*pcp.l444i1cp_455i1cpcp.vfousrutp_
etransmit_eq =/tOo Orysutp_outc.bc}
 
 	o	/*rMove To
dg_unk toaTo
d
etransmit0		/* . k, i _unksl- cov* onaTo
d
etransmit0		/*  0sdalwaysekepb-inx Cont.
+ ck * onaTo
d
etransmit0		/*  _re alwaysekepb-inx Cont.
 	ck */o w  sis,iPT__cp_rtlchunk);ty d ectp_
etransmit_cpsert/lchunkarq);t+.b	rutp_cpsert_l@ -/&q
+
etransmit, lchunk);tc.b}tc.itcocp.l490i6 +501i12pcp.vfousrutp_
etransmit/tOo Orysutp_outq-2q
 
 	rutp_
etransmit_eq =/q, Lransport,tfast_
etransmit)+ t=+ /* PR-
CTP A5) Any x */(To
dT3-rtx x */r expires, on0any destin	queu,
+c * To
dsendcr SHOULDienyatoaadvaTce To
d"AdvaTced.Peer.Ack.Po   " by
+c * fo,hows,* To
dproceduresaout(di	d inxC1 - C5.=+  *_frh;utp_gwneraiA_fwdtst/qarq->asoc->ctst_ * _po    tp+
 	error nosutp_outq/flush/qar/* rtx_ore
oe c*/ 1 ;i o 	o alerror)ecp.l552, 2 +569, 2 cp.ipt_REJs4.2sutp_outq/flush_rtx/tOo Orysutc.b}tcs ho/*rAt+empi toaappend trt * _unk toaTo
d	 * wi. *_fy dept_ud. o(*q->append_output)(pki, chunk);t+kdept_ud. oectp_	 * wi/append_chunk(pki, chunk);tcs hoswitcha(ept_ud)2sl hocase1
CTP_XMIT_PMTU_FULL: = k	/*rSend trt *	 * wi.  *_f*/	 sctl(error no(*q->
dace_output)(pki )kb);
 }+ck sctl(error nosutp_	 * wi/transmit(pki )kb);
 } ckkk*star _ore
+N= 1e   = k	/*rI:6w	f_re ro*ransmitbi +, w	fnhouldaonlyecp.l573,7 +590i7 cp.ipt_REJs4.2sutp_outq/flush_rtx/tOo Orysutcl hocase1
CTP_XMIT_RWND_FULL: = k -    e /*rSend trt *	 * wi. *_f*/	 sctl(error no(*q->
dace_output)(pki )kb);
 }+ck sctl(error nosutp_	 * wi/transmit(pki )kb);
 } ckkk*star _ore
+N= 1e   = k	/*rSsopNsends,* on f as6To
rA t *no mor_nroomecp.l583i6 +600i16 cp.ipt_REJs4.2sutp_outq/flush_rtx/tOo Orysutc.b schunk =uamma =c.b<b+	 k = K+hocase1
CTP_XMIT_NAGLE_DELAY:u+ k -    e /*rSend trt *	 * wi. *_f+ck sctl(error nosutp_	 * wi/transmit(pki )kb);
 }+ckkk*star _ore
+N= 1e +=+ 		/*rSsopNsends,* on f because1of nagl
dveOd_. *_f+ck lis,iadd(lchunkarlq	/* )+ +.b schunk =uamma =+w <b+	 k =+=c.bdefault:nt			/*rk, iappend wa *nuccessful, io0add trt * _unk to
 ckk * To
d*ransmitbed l@ -.ucp.l625i13 +652i9 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 ctre _nPectp_	 * wi *	 * wi;
 ctre _nPectp_	 * wi nvngleton;
 ctre _nPectp_associ	queu *asocN= q->asoc;p-     ecn_cap,
+	 noasoc->peer.ecn_cap,
+	;p 	_/u16 sport noasoc->base.bind_addr.port;p 	_/u16 dport noasoc->peer.port;p 	_/u amvtag noasoc->peer.i.snk,_tag;p*//* trt *is0To
dECNE _sndler 
datnvngleton 	 * wis.  *_f*/sutp_	 * wi/p_sndler_i *s/ecne/_sndler =uamma =-	sutp_	 * wi/p_sndler_i *ecne/_sndler =uamma = ctre _nPespace ivegas*q	/* ;
 ctre _nPectp_transportd*transport =uamma = ctre _nPectp_transportd*new_transport;tcp.l656i1cp_679i6 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c *    *skinxad
CTP 	 * wi inxindreass,*  Cont1of TSN.
 c *   ...= hv*/p*/sctlecn_cap,
+	)2sl- cs/ecne/_sndler =u&;utp_gwt_no/prepend;ty decne/_sndler =u&;utp_gwt_ecne/prepend =y }s 
 	q	/*  = &q-> beerol;
 cwhile b0chunk =u/tOo Orysutp_ _unk *)LL,_dT		/* Hq	/* ))pACKcp.l686,8 +705i8 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c ckk -    &transport_l@ -g;l ho	}
 	ck	 * wi = &transport->	 * wi;
*/	 (*q-> bturgaoutput)(p * wi, vtaga
*/ <	k -  ecn_cap,
+	, ecne/_sndler);t+.b	rutp_	 * wi/ceturg/p * wi, vtaga
ow <	k - asoc->peer.ecn_cap,
+	);tc.b}tcs hoswitcha( hunk->g_unk_hdr->typepACKcp.l700i11 +719i1cpcp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c case1
CTP_CID_INIT:
 c case1
CTP_CID_INIT_ACK:nt		case1
CTP_CID_SHUTDOWN_COMPLETE: */	 (*q->snk,aoutput)(&nvngleton, Lransport,tsport,tdport)
-*/	 (*q-> bturgaoutput)(&nvngleton, vtagarecn_cap,
+	,
*/ <	k -  ;_ecne/_sndler);t*/	 (void)o(*q->build_output)(&nvngleton, chunk);ty d error no(*q->
dace_output)(&nvngleton);t+.b	rutp_	 * wi/cp_rt&nvngleton, Lransport,tsport,tdport)
-+.b	rutp_	 * wi/ceturg/&nvngleton, vtagar0)
-+.b	rutp_	 * wi/append_chunk(&nvngleton, chunk);t+ d error nosutp_	 * wi/transmit(&nvngleton);t ck sctlerror <;
 } ckkkro*retu Wror;iaw <b+	 k =cp.l720, 2 +738i1cpcp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c case1
CTP_CID_COOKIE_ACK:nt		case1
CTP_CID_ECN_ECNE:nt		case1
CTP_CID_ECN_CWR:t*/	 (void)o(*q->build_output)(p * wi, chunk);t-w <b+	 k =-nt		case1
CTP_CID_ASCONF:nt		case1
CTP_CID_ASCONF_ACK:n*/	 (void)o(*q->build_output)(p * wi, chunk);t+		case1
CTP_CID_FWD_TSN:frhl	sutp_	 * wi/transmit_chunk(p * wi, chunk);tc.b<b+	 k = Kc.bdefault:ncp.l770,8 +786i8 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c c}
 
 	o		 * wi = &transport->	 * wi;
*/	 (*q-> bturgaoutput)(p * wi, vtaga
*/ <	k -  ecn_cap,
+	, ecne/_sndler);t+.b	rutp_	 * wi/ceturg/p * wi, vtaga
ow <	k - asoc->peer.ecn_cap,
+	);tc.bro*ran:nt			error nosutp_outq/flush_rtx/q,-p * wi,
 c ckkk -  rtx_ore
oe ,u&;tar _ore
+CONcp.l803,15 +819i15 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c csctlchunk
+ninfo.ninfo_icpeam >=
 	ck    asoc->c.ssnk,anum_oicpeamspACK 
*/ <	/*rMq = a *n failwd send. *_f*/	 dectp_ET_Tmsg/fail/chunkar
CTP_ERROR_INV_STRM);t+.b		/*rMq = a *failwd send. *_f+ ck	rutp_g_unk_fail/chunkar
CTP_ERROR_INV_STRM);t  ck	rutp_g_unk_f+	{(chunk);tc.bb	 beeinuehoc.bc}
 
 	o	/*rHas6Tot * _unk expired? *_f*/	 sctlectp_ET_Tmsg/expiresgchunk))2sl*/	 dectp_ET_Tmsg/fail/chunkar0)
-+.b	ed2trutp_g_unk_abdndoned/chunk))2slow  	rutp_g_unk_fail/chunkar0);t  ck	rutp_g_unk_f+	{(chunk);tc.bb	 beeinuehoc.bc}
cp.l836i11 +852, 1 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c ck}
 
 	o			 * wi = &transport->	 * wi;
*/	  (*q-> bturgaoutput)(p * wi, vtaga
*/ <	kk -  ecn_cap,
+	, ecne/_sndler);t+.b		rutp_	 * wi/ceturg/p * wi, vtaga
ow <	kk - asoc->peer.ecn_cap,
+	);tc.bbitcoy th
CTP_DEBUG_PRINTK("ectp_transmit_p * wi(%p, %p[%s]), ",
+ ck
CTP_DEBUG_PRINTK("ectp_outq/flush/%p, %p[%s]), ",
 c ckk -q, chunk,
 c ckk - _unk &&  hunk->g_unk_hdr ?
 c ckk -rutp_gnameg
CTP_ST_CHUNK(
cp.l855i7 +871i7 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c ckkatomic_pead(&chunk
+nL,
+ serspA: -1 ;i o 	w /*rAdd To
dg_unk toaTo
d	 * wi.  *_f*/	 ept_ud. o(*q->build_output)(p * wi, chunk);t+		dept_ud. oectp_	 * wi/transmit_chunk(p * wi, chunk);tc
 			rwitcha(ept_ud)2sl hoocase1
CTP_XMIT_PMTU_FULL: cp.l879r7 +895i7 cp.s4.2sutp_outq/flush/tre _nPectp_outq-2qa
 c ckBUG();tc.bbitcoy th/*rBUG:rWA assu*/(Toa cTo
d(*q->
dace_output( ;
+ ck/*rBUG:rWA assu*/(Toa cTo
dsutp_	 * wi/transmit() 
 ckk * ca,hibelldiw*,hinuccewd m,hiTo
dx */(acp add tre
 ckk * g_unk toaTo
d*ransmitbed l@ -(acp rTstar  tre
 ckk * ore
+s.ucp.l922,33 +938i1Recp.ictp_flush_out:t 	ctre _nPectp_transportd*t =usis,isReny(ltransport,  ckkk<	      ;cp_delrutp_transport,  ckkk<	      ;end_peady) =y to alt != Lransport }-d <transportN= L;=*oy 		 * wi = &transport->	 * wi;
*/	sctl	 * wi
+nizeN!);
CTP_IP_OVERHEAD)ty d error no(*q->
dace_output)(	 * wi tp+ 		 * wi = &t->	 * wi;
+cks,ar!rutp_	 * wi/emptW/	 * wi )t+ d error nosutp_	 * wi/transmit(	 * wi tp h}
rp hro*retu Wror;iaitco-/*rSe cTo
dvariousnoutput0_sndls,* ca,hb * s.  *_f*s4.2sutp_outq/sdoaoutput__sndlers(tre _nPectp_outq-2qa
*/ <	      ;utp_outq/o_sndler_snk,_t snk,,p*/ <	      ;utp_outq/o_sndler_ bturga.2cbturg,p*/ <	      ;utp_outq/o_sndler_i append,p*/ <	      ;utp_outq/o_sndler_i build,p*/ <	      ;utp_outq/o_sndler_
dace_t 
dace 
-sl-	q
+snk,aoutput =ucp_rts-	q-> bturgaoutput =u bturg =-	q->append_output =uappendrc-	q->build_output =ubuild =-	q->
dace_output =u
dace;l-  "*retu0 =-it-t /* Updd;_ un * _ET_TNbased on0To
dl4coms,* SACK g_unk *_f trt_REJvfousrutp_s * _updd;__un * _ET_T(ipe _nPrutp_associ	queu *assoc,
 ck		ctre _nPectp_s * hdr *s * )ecp.l1007i7 +1004i7 cp.s4.2sutp_outq/s * (tOo Orysutp_outq-2qarp 	_ 0ipe _nPrutp_associ	queu *asocN= q->asoc;p ctre _nPectp_transportd*transport =-	icp_delrutp_ _unk *tchunk;p+ticp_delrutp_ _unk *tchunk =uamma = ctre _nPiAs,ivegas*lchunkar*transport_l@ -,s*pos, *+emp
- 	rutp_s * _vari,
+	_i *fragd. oe * ->vari,
+	;p 	_/u ams * _ctst, ctst, tst;Kcp.l1059,8=+1056i1cpcp.s4.2sutp_outq/s * (tOo Orysutp_outq-2qarp c}
 
 	/*rGe cTo
dhighest TSN inxTo
ds * . *_f*/highest_tst =as * _ctst +p*/ mtohs(fragd[mtohs(e * ->num_gap_ * _blo* s) - 1].gab.end tp+ highest_tst =as * _ctstts+/s,are * ->num_gap_ * _blo* s)t+ dhighest_tst +=u+ k -  mtohs(fragd[mtohs(e * ->num_gap_ * _blo* s) - 1].gab.end tp o 	o alTSN_lt(asoc->highest_s * wd, highest_tst)g2sl oohighest_new_tstd= highest_tst;Kcp.l1110i11 +1109i6 cp.s4.2sutp_outq/s * (tOo Orysutp_outq-2qarp l octst =aasoc->ctst_ * _po   ; =p*/
CTP_DEBUG_PRINTK("%s: s *  Cumulawiv
dTSN Ack 0sd0x%x.\n",l- cov __FUNCTION__, s * _ctst) =*/
CTP_DEBUG_PRINTK("%s: Cumulawiv
dTSN Ack l:6associ	queu "l- cov "%p 0sd0x%x.\n", __FUNCTION__, asoc, ctst) =*
  /* trrow away stce >rotbi + on0To
ds *  		/* .  *_f 	iAs,ifor_eaus_safe(lchunkar+emp, &q
+s * wd)2sl ootchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
cp.l1139i1cp+1133,19 cp.s4.2sutp_outq/s * (tOo Orysutp_outq-2qarp l oasoc->peer.rwndi=as * _a_rwndts frh;utp_gwneraiA_fwdtst/qars * _ctst) =+
+h
CTP_DEBUG_PRINTK("%s: s *  Cumulawiv
dTSN Ack 0sd0x%x.\n",l+ cov __FUNCTION__, s * _ctst) =+h
CTP_DEBUG_PRINTK("%s: Cumulawiv
dTSN Ack l:6associ	queu, "l+ cov "%p 0sd0x%x.rAdv peer ack po   : 0x%x\n",l+ cov __FUNCTION__, asoc, ctst, asoc->adv_peer_ * _po    tp+
 	/*rSeerillm,hig_unks _re a* wd.
 c * Mak
diurA Eo
demptWNq	/*  _sndler w*,higwi run+snd_r.= hv*/p*/q->emptWN= ik-_
 			bemptW/&q->out N&&usis,ismptW/&q->
etransmit)+ +/q->emptWN= ik-_
 			bemptW/&q->out N&&uik-_
 			bemptW/&q-> beerol)N&&eA?k lis,ismptW/&q->
etransmit)+ = o al!q->emptW)nt		gotoafcp_sh =cacp.la218i6 +1221, 2 cp.ipt_REJvfousrutp_g_e* _*ransmitbed(tOo Ol ootchunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
 ckkk-   *ransmitbed_l@ -g;l =+ 	ed2trutp_g_unk_abdndoned/tchunk))2slow  /*rMove To
dg_unk toaabdndoneddl@ -. *_frhl	rutp_cpsert_l@ -/&q
+abdndoned, lchunk);t+.b	 beeinueho+ck}&(s hotst =amtohl(t hunk->subh.ET_T_hdr->tst) =  	ed2trutp_a* wd(e * , tst))2sl ho	/*rI:6To0sd		/*  0sdTo
d
etransmit0		/* , tre
cp.la599,- +1608i123 cp.ipt_REJs4.2sutp_a* wd(ere _nPectp_s * hd
d	 ss:p hro*retu1;iait+&(50roc_sEC(di	 s4.2sutp_gwt_skip_	os(tre _nPectp_fwdtst_skip *skipl@ -,
+ckkk-   s4.2nskips, __u16 icpeam)t+slows4.2i =+
+h
dat(i =a0; i <2nskips; i++)2slow sctl;kipl@ -[i].icpeam == icpeam)t+	kkro*retuiho+c}
+ ro*retuiho+it+&(/*rCreaiA Hap add a fwdtst g_unk toaTo
doutq's  beerol 		/*  0f newded.v*/p(50roc_svfous;utp_gwneraiA_fwdtst/tre _nPectp_outq-2qar__u amctst)t+slowipe _nPrutp_associ	queu *asocN= q->asoc;p+ticp_delrutp_ _unk *ftst_chunk =uamma =+wtre _nPectp_fwdtst_skip ftst_skip_arr[10];lows4.2nskips_no_ts+/s4.2skip_	os_no_ts+/__u amtst;K+ticp_delrutp_ _unk *chunk;p+ticp_deliAs,ivegas*lchunkar*temp
-	-+ /* PR-
CTP C1) Lwi S * CumAck be To
dCumulawiv
dTSN ACK garri	d inxtre
+c * receivwd SACK.=+  * =+  * I:6(AdvaTced.Peer.Ack.Po    <-
 * CumAck), tren updd;_=+  * AdvaTced.Peer.Ack.Po    toabe equal toa
 * CumAck.=+  *_frho alTSN_lt(asoc->adv_peer_ * _po   , ctst))t+	kasoc->adv_peer_ * _po    =actstts+-+ /* PR-
CTP C2) Tnyatoafuruo T advaTce To
d"AdvaTced.Peer.Ack.Po   "=+  * locally, to_.2it,atoamove "AdvaTced.Peer.Ack.Po   " up a *ld + a 
+c * To
d _unk ajetdinxTo
dout-		/*  spac  0sdeq =ed a *"abdndoned" a 
+c * shown*inxTo
dfo,hows,* exasnd_:
+c *=+  * Assu*s,* To_.2a SACK arrivnd  *th To
dCumulawiv
dTSN ACK 102=+  * acp tr
dAdvaTced.Peer.Ack.Po    0sdupdd;_d toaTo0sdvalu_:
+c * =+  *  dout-		/*  a cTo
dend l:6 ==>  dout-		/*  aftArdAdv.Ack.Po   =+  *  dnormal SACK procesnvng           local advaTcemo v=+  *  dddddddddddddd...                           ...=+  *  dAdv.Ack.Pt-> 102 a* wd                     102 a* wd=+  *  dddddddddddddd103aabdndonedd  dddddddddddddd103aabdndoned=+  *  dddddddddddddd104aabdndonedd  ddAdv.Ack.P-> 104aabdndoned=+  *  dddddddddddddd105                           105=+  *  dddddddddddddd106 a* wd                     106 a* wd=+  *  dddddddddddddd...                           ...=+  *=+  * InaTo0sdexasnd_, tre1ET_TNso ont1nuccessfully advaTcedxtre
+c * "AdvaTced.Peer.Ack.Po   " from 102 toa104alocally.=+  *_frhiAs,ifor_eaus_safe(lchunkar+emp, &q
+abdndoned)2slow chunk =usis,isReny(lchunkar;cp_delrutp_ _unk,
+ckkk	+ransmitbed_l@ -g;l+		tst =amtohl( hunk->subh.ET_T_hdr->tst) =+=+ 	/*rRemove any g_unks inxTo
dabdndonedd		/*  To_.2are a* wd by
+cc * To
d tst.
+cc */ =+ 	ed2tTSN_lte(tst, ctst))2slow  sis,iPT__cp_rtlchunk);t+.b	o al! hunk->tst_gap_ * ed)2slow  c_unk->transport->flightar MF -=
ow <	kk ectp_ET_Tar MF(chunk);t+.b	q->outiptnds,*__cwnd.-= ectp_ET_Tar MF(chunk);t+.b	}frhl	rutp_g_unk_f+	{(chunk);t+ck} jeY22slow 	ed2tTSN_lte(tst, asoc->adv_peer_ * _po   +1))2slow  	asoc->adv_peer_ * _po    =atst;K+tc csctlchunk
+g_unk_hdr->flagd.&
ow <	k 
CTP_DATA_UNORDERED }+ckkk	 beeinueho+ckl	rkip_	os_nosutp_gwt_skip_	os(&ftst_skip_arr[0]a
ow <	kknskips,
ow <	kk hunk->subh.ET_T_hdr->icpeam)ho+ckl	ftst_skip_arr[skip_	os].icpeam =}+ckkk	 hunk->subh.ET_T_hdr->icpeamho+ckl	ftst_skip_arr[skip_	os].ist =
ow <	k  hunk->subh.ET_T_hdr->ist;K+tc csctlrkip_	os_n=2nskips }+ckkk	nskips++;K+tc csctlnskips_n=a10 }+ckkk	b+	 k =+	ck} jeY2}+ckkkb+	 k =+	c}
+ate+=+ /* PR-
CTP C3) I:, aftArdstepxC1 acp C2, To
d"AdvaTced.Peer.Ack.Po   "=+  * 0sdgreaiAT tran To
dCumulawiv
dTSN ACK garri	d inxtre receivwd=+  * SACK, tre1ET_TNso ont1MUSTtntcp tre1ET_TNreceivwT a FORWARDdTSN=+  * chunk  beeains,* To
dsnd_stdvalu_/l:6To

+c * "AdvaTced.Peer.Ack.Po   ".=+  *=+  * C4)1For eaus*"abdndoned" TSN To
dsendcr l:6To
dFORWARDdTSN SHOULD=+  * l@ -(eaus*icpeam acp sT		/nc  numbcr inxTo
dforwara	d TSN. trt =+  * 0nformaqueu w*,hien,
+	Htre receivwr toaeassly fiap any
+c * s*rana	d TSN's waibi + on0icpeam re Cont1		/* s. Eaus*icpeam=+  * SHOULDionlydbenreportnd onc ; trt *means to_.2if multipl

+c * abdndoneddmesaages occur inxTo
ds me0icpeam tren onlydTo

+c * highest abdndoneddicpeam sT		/nc  numbcr isnreportnd.rI:6To

+c * Total r MF l:6To
dFORWARDdTSN does NOT fivxinxadnvngle MTU tren
+c * To
dsendcr l:6To
dFORWARDdTSN SHOULDalowAT tr_=+  * AdvaTced.Peer.Ack.Po    toaTo
dsnst TSN To_.2w*,hifivxinxa
+c * svngle MTU.=+  *_frho alasoc->adv_peer_ * _po    >mctst)t+l	ftst_chunk =usutp_mak
_fwdtst/asoc, asoc->adv_peer_ * _po   ,
ow <	k      nskips, &ftst_skip_arr[0]); t+frho alftst_chunk)2slow _/ikb_
 			bL,il(&q-> beerol,u/tOo Orysspace > )ftst_chunk)e +


CTP_INC_STATS(SutpOutCtrlC_unks);t+ate+}i = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/protocol. maxwin),{
@@ -352,6 +3autp/protocol.  vic  tcp_clamp_windowautp/protocol. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/protocol. 
 }
 
+@ -160,7 8:5"autotuning" code.cp.l719r7 +719r7 cp.ipt_REJvfousectp_inet_ev
nt_msgnamegtOou = o almsgname)2sl hoipe _nPrutp_associ	queu *asoce   -d asoc noev
nt
+nndrcvinfo.ninfo_assoc_ide +

asoc noev
nt
+asoce  k	rutp_inet_msgnamegmsgname, addr_s(t)e  k	rin  og2Oo Orysockaddr_int*)msgnamee  k	rinfrom = &asoc->peer.priwiny_addr.v4;Kcp.l981i6 +981i8 cp.__cp_r s4.2sutp_cp_rtvoid)  
 	/*rInk,ialte
dproc fs directory.  *_f 	sutp_	rocicp_rt)ts+/s,arept_ud) +

gotoa Wr_snk,_	roc;  
 	/*rInk,ialte
dobject2cbuff debuggs,*.v *_f 	sutp_dbg_objc v/cp_rt);Kcp.l1099i6 +1101i9 cp.__cp_r s4.2sutp_cp_rtvoid)  	/*rDis,
+	HADDIP by default. *_f 	sutp_addip_en,
+	Hno_tst +h/*rE4,
+	HPR-
CTP by default. *_f+	sutp_	rsutp_en,
+	Hno1;t+
 	sctp_sysctl_reg@ -er( tp o 	INIT_LIST_HEAD(&sutp_addresa_families) =cp.l1143i6 +1148i7 cp. Wr_ehash_@@ vc:
 	ck    altering2Oo Orysutp_hashbu* wi ) tp  Wr_ahash_@@ vc:
 	sutp_dbg_objc v/ex_rt)ts+ Wr_snk,_	roc:f 	sutp_	rociex_rt)ts 	cleanup_sutp_mibs( tp  Wr_snk,_mibs:i = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/sm_mak
_chunk. maxwin),{
@@ -352,6 +3autp/sm_mak
_chunk.  vic  tcp_clamp_windowautp/sm_mak
_chunk. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/sm_mak
_chunk. 
 }
 
+@ -160,7 4:55&sysctl_tcp_defaucp.l6i1cp_6i6 cpu  *
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
 v*s- * trt *file t4clude *part/l:6To
disnd_mo v	queu/l:6To
dadd-IP extensueu,
- * based on0<draft-ietf-tsvwg-addip-autp-02.txt> June 29,  }
1,
- * 
dat*o
d
CTP umedAsu "fe_dTce Isnd_mo v	queu.u- *
  * tres_ funtp->vs work  *th To
dipt_
 funtp->vs iu sutp_sm_ipt_
funs.    * Todisnd_mo v To
dipt_
 oper	queus. rk, s_ funtp->vs isnd_mo v To
   * steps whius*rT		ire*mopacys,* exisbi + ET_TNsOo Orures.
cp.l89i11 +85i13 cp.s4.2sutp_g_unk_iifg besbeeOo Orysutp_ _ut  * No_
 2:rk, iECN cap,
+	 field isnrecerved 
datfurure use1oft  * Explic_r Cd + squeu/No_acic	queu.
  */p*ipt_REJ besbeectp_ecn_cap,
+	_param_  ecap_param =2sl*/sl*/	
CTP_PARAM_ECN_CAPABLE,l- c__ besba v/htbes(ltering2ctp_ecn_cap,
+	_param_ )),=y }s+ipt_REJ besbeere _nPectp_	 ramhdr ecap_param =2sl+	
CTP_PARAM_ECN_CAPABLE,l+c__ besba v/htbes(ltering2re _nPectp_	 ramhdr)),=+};s+ipt_REJ besbeere _nPectp_	 ramhdr 	rsutp_param =2sl+	
CTP_PARAM_FWD_TSN_SUPPORT,l+c__ besba v/htbes(ltering2re _nPectp_	 ramhdr)),= };tco 6 1A helper Todink,ialte
dTodink,ialte
dan op2error insud
da=cp.l196i6 +194i8 cp.ipp_delrutp_ _unk *sutp_mak
_cp_rt besbep l oc_unksizeN=alteringcp_r) + addrs_s(t + 
CTP_SAT_LEN(num_types)ho 	c_unksizeN+=alteringecap_param)ts+/s,areutp_	rsutp_en,
+	) +-> hunksizeN+=altering	rsutp_param)ho 	c_unksizeN+=avparam_	 &rc u 	/*rRFC 2960 3.3.2rInk,iaqueu/(INIT) (1)pcp.l232i6 +232i8 cp.ipp_delrutp_ _unk *sutp_mak
_cp_rt besbep 	sutp_addto_chunk(ro*val, num_typesv* nizeing__u16), &types)ho p 	sutp_addto_chunk(ro*val, lteringecap_param), &ecap_param)ts+/s,areutp_	rsutp_en,
+	) +->sutp_addto_chunk(ro*val, ltering	rsutp_param), &	rsutp_param)ho noET_T: = o aladdrs.v)nt		k
+	{laddrs.v)tscp.l278i6 +280i1cpcp.ipp_delrutp_ _unk *sutp_mak
_cp_r_ * t b = o alasoc->peer.ecn_cap,
+	)
 -> hunksizeN+=alteringecap_param)tst +        /* te,hipeer To_.2we',hidoHPR-
CTP onlydo apeer advertisnd.r *_frho alasoc->peer.prrutp_ ap,
+	) +-> hunksizeN+=altering	rsutp_param)ho+
 	/*rNow a@ vcaiA Hap f*,hioe cTo
d _unk.v *_f 	ro*val =uectp_mak
_chunk/asoc, 
CTP_CID_INIT_ACK, 0, chunklter)+ = o al!ro*val)pcp.l293i6 +299i8 cp.ipp_delrutp_ _unk *sutp_mak
_cp_r_ * t b = sutp_addto_chunk(ro*val,  bokie_	 &,  bokie)+ = o alasoc->peer.ecn_cap,
+	)
 ->sutp_addto_chunk(ro*val, lteringecap_param), &ecap_param)ts+/s,arasoc->peer.prrutp_ ap,
+	) +->sutp_addto_chunk(ro*val, ltering	rsutp_param), &	rsutp_param)ho 
 	/*rWe newd toaromovw0To
d best0		altfier a cTot *po   .v *_f 	ro*val
+asoc =u/tOo Orysutp_associ	queu *) asoce cp.la286i6 +1294i9 cp.ectp_ bokie_param_  *;utp_	 * _ bokiet b = /*rSavw0To
draw addresa l@ -(	 &gth in0To
d bokie. *_f 	cbokie->c.raw_addr_sis,is(t_noaddrs_s(ttst +h/*rR_mombcr PR-
CTP  ap,
ilit_. *_f+ccbokie->c.prrutp_ ap,
+	 noasoc->peer.prrutp_ ap,
+	tp+
 	/*rSe-(ac expir	queu x */(
dat*o
d bokie.  *_f 	do_gwtore
ofday(&cbokie->c.expir	queu)+ = TIMEVAL_ADDrasoc-> bokie_	ife,  bokie->c.expir	queu)+ cp.la442i6 +1453i8 cp.no_hmac:f 	ro*val
+ajet_tstd= ro*val
+c.ink,ial_tst;K hro*val
+ctst_ * _po   d= ro*val
+ajet_tstd-a1; = ro*val
+addip_cerial =uro*val
+c.ink,ial_tst;K+ ro*val
+adv_peer_ * _po    =aro*val
+ctst_ * _po   ;K+ ro*val
+peer.prrutp_ ap,
+	 =uro*val
+c.prrutp_ ap,
+	tp 
  /* tre INIT stce >w*,hibe2done bydTo
Nsud
deffects.v *_f 	ro*returo*val;icp.la653i6 +1666i1cpcp.ipt_REJs4.2sutp_veracy_paramg besbeeOo O
= case1
CTP_PARAM_HOST_NAME_ADDRESS:
 	c/* te,hiTo
d	ent, we won'beeupportdtrt *	 ram.v *_f 		ro*retusutp_	rocesa_hn_paramgasoc, param, chunk,  Wr_chunk)e +
case1
CTP_PARAM_FWD_TSN_SUPPORT:low sctl;utp_	rsutp_en,
+	) +->kb+	 k =+	c6 1Fm,hitrrough */ = bdefault:nt		
CTP_DEBUG_PRINTK("Unrecognized p ram: %d 
dat _unk %d.\n",
 ckkkmtohs(	 ram.p->typep, cid)+ cp.la956i6 +1973, 2 cp.s4.2sutp_	rocesa_paramgtOo Orysutp_assoc
 ckasoc->peer.ecn_cap,
+	 =a1; = kb+	 k = K+hcase1
CTP_PARAM_FWD_TSN_SUPPORT:low sctl;utp_	rsutp_en,
+	)2slow  asoc->peer.prrutp_ ap,
+	Hno1;t+kkkb+	 k =+	c}
+ac6 1Fm,hitrrough */ = bdefault:nt		6 1Any unrecognized p rametersfnhouldahavw0beetucaught
 hhv* Hap _sndled by2sutp_veracy_paramg) whius*nhouldabetcp.l2610,- +2633,38 cp.s4.2sutp_	rocesa_as btu_ * (tOo Orysutp_
rp hro*returo*val;i }u+&(/*rMak
da FWD TSN  _unk.v*/ =+ipp_delrutp_ _unk *sutp_mak
_fwdtst/ besbeere _nPectp_associ	queu *asoc,
+ckkk-   __u amnew_cum_tst, iize_i nicpeams,
+ckkk-   tre _nPectp_fwdtst_skip *skipl@ -)t+slowipe _nPrutp_ _unk *ro*val =uamma =+wtre _nPectp_fwdtst_ _unk *ftst_chunk =+wtre _nPectp_fwdtst_hdr ftst_hdrrt +htre _nPectp_fwdtst_skip skip =+wtize_i h   ;K+ s4.2i =+
+hh    =a(nicpeams + 1)v* nizeing__u32)ts+-+ /* MaybeNc	2/To
dT-bitrillwe havw0no6associ	queu.r *_frhro*val =uectp_mak
_chunk/asoc, 
CTP_CID_FWD_TSN, 0, h    tp+
+ o al!ro*val)p+		ro*retuamma =+N+rftst_chunk =u(tre _nPectp_fwdtst_ _unk *)ro*val
+subh.fwdtst_hdr =+N+rftst_hdr.new_cum_tstd= htbel/_dw_cum_tst);K+ ro*val
+subh.fwdtst_hdr =
ow sutp_addto_chunk(ro*val, lteringftst_hdr), &ftst_hdr ho+
+h
dat(i =a0; i <2nscpeams; i++)2slow skip.icpeam = ;kipl@ -[i].icpeam;low skip.ist =askipl@ -[i].ist;K+tcsutp_addto_chunk(ro*val, lteringskip), &skip);t+ate+=+ ro*returo*val;i+}i = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/sm_iud
effect. maxwin),{
@@ -352,6 +3autp/sm_iud
effect.  vic  tcp_clamp_windowautp/sm_iud
effect. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/sm_iud
effect. 
 }
 
+@ -160,7 9:25&sysctl_tcp_defaucp.l429i6 +429i9 cp.ipt_REJvfousrutp_gma/cp_r_failwdtrutp_gm
 ->sutp_add_gma/sfg bmmsnds, 
CTP_CMD_EVENT_ULP,
 ckkk
CTP_ULPEVENT(ev
nt))ts frh;utp_add_gma/sfg bmmsnds, 
CTP_CMD_NEW_STATE,
+ ck
CTP_STATE(
CTP_STATE_CLOSED)gtp+
 	/*rSEND_FAILEDdsen,+snd_riwo
tucleani + up6To
dassoci	queu.r*_f 	asoc->outq	/* .error no Wror;iaw;utp_add_gma/sfg bmmsnds, 
CTP_CMD_DELETE_TCB, 
CTP_amma())+ cp.l457i6 +460i1cpcp.ipt_REJvfousrutp_gma/assoc_failwdtrutp_giaw;utp_add_gma/sfg bmmsnds, 
CTP_CMD_NEW_STATE,
  ck
CTP_STATE(
CTP_STATE_CLOSED)gtpt +h/*rSe-(sk_j_bitoaECONNRESET on0a 1-1.ipyle so* wi. *_frho al!rutp_ipyle(asoc->base.sk, UDP))t+	kasoc->base.sk
+nL_j_bi=aECONNRESET; t+f 	/*rSEND_FAILEDdsen,+snd_riwo
tucleani + up6To
dassoci	queu.r*_f 	asoc->outq	/* .error no Wror;iaw;utp_add_gma/sfg bmmsnds, 
CTP_CMD_DELETE_TCB, 
CTP_amma())+ cp.l579r7 +586i7 cp.ipt_REJvfousectp_gma/transport_rec	2/tct
 /*rHelper funtp->vetoa	rocesa To
dprocesa SACK gbmmsnd.  *_f trt_REJs4.2sutp_gma/	rocesa_s * (tutp_gma/seq_  *gmas,
 ckkk-ere _nPectp_associ	queu *asoc,
-<	kk ectp_s * hdr_  *; * h }+ckkk-ere _nPectp_s * hdr *s * h)p 	_ 0s4.2err =cacp.l729i6 +736i19 cp.ipt_REJvfousrutp_gma/	rocesa_operr(sutp_
rc}
 }
 
(/*rProcesa vari,
+	 FWDTSN  _unk 0nformaqueu.v*/p(50roc_svfous;utp_gma/	rocesa_fwdtst/tre _nPectp_ulpq *ulpq, 
+ckkk-   tre _nPectp_ _unk *chunk)t+slowipe _nPrutp_fwdtst_skip *skip; +h/*rWalk Torough m,hiTo
dskippwd SSNs2*_f+	sutp_walk_fwdtst/tkip, chunk)2slow sctp_ulpq_skip(ulpq, mtohs(ekip->icpeam), mtohs(ekip->ist));t+ate+=+ ro*retho+it+& /* tr s_ Toree eqcros @@ vw usetoa	u,hiTo
ddebuggs,* gbd
dout/l:6To

  * main f vw l:6sutp_do_smg) toakeep atten,ueu focused on0To
dpeal
  * funtp->valit_6To
rA.ucp.l903,7 +923i7 cp.s4.2sutp_gma/cpd_rpreterg2ctp_ev
nt_.2ev= ctre _nPore
+_sis, *ore
+;iaw */
 			 sd + ore
oe ;p ctre _nPectp_transportd*t =-	sutp_s * hdr_  s * h =+wtre _nPectp_s * hdr s * h = 0s4.2local_cork no_ts t ho al
CTP_EVENT_T_TIMEOUTN!);ev
nt_.ypepucp.l962i6 +982,18 cp.s4.2sutp_gma/cpd_rpreterg2ctp_ev
nt_.2ev= cw sctp_tstmap_eq =(&asoc->peer.tst_map, cmd->obj.u32)tsc.b<b+	 k = K+hocase1
CTP_CMD_REPORT_FWDTSN:frhl	/*rMove To
dCumulawwiv
dTSN Ack avega. *_frhl	rutp_tstmap_skip(&asoc->peer.tst_map, cmd->obj.u32)ts+=+ 		/*rAbortdany in 	rogresa 	 r,ialdveOivwry. *_frhl	rutp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC) =+w <b+	 k =+=+hocase1
CTP_CMD_PROCESS_FWDTSN:frhl	;utp_gma/	rocesa_fwdtst/&asoc->ulpq, cmd->obj.ptr ho+                        b+	 k =+=c.bcase1
CTP_CMD_GEN_SACK:nt			/*rGeneraiA HNSeletp-v
dACK.= ckk * k, iargumo v Tells usewo
uo T toaju -lcbuff cp.la247i6 +1279i9 cp.s4.2sutp_gma/cpd_rpreterg2ctp_ev
nt_.2ev= cwcase1
CTP_CMD_PROCESS_OPERR:= cw sctp_gma/	rocesa_operr( bmmsnds, asoc, chunk);tc.b<b+	 k =+hocase1
CTP_CMD_CLEAR_INIT_TAG:low  asoc->peer.i.snk,_tag_no_ts+/k	b+	 k = .bdefault:nt				rs4.k(KERN_WARNING "Impossi
+	  bmmsnd: %u, %p\n",
 ckk       cmd->vwrb, cmd->obj.ptr ho = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/sm_ipt_
funs. *
+ * THeAalgorithm +oautp/sm_ipt_
funs.  vic  tcp_clamp_windowautp/sm_ipt_
funs. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/sm_ipt_
funs. 
 }
 
+@ -160,7 8:13&sysctl_tcp_defaucp.la71r7 +171i7 cp.nomem:p v*    Veracic	queu Tag_field toaTag_A, Hap alsoa	rovud
diit-ownp v*    Veracic	queu Tag_(Tag_Z) in0To
dInk,iaqe Tag_field.
 v*s- * Veracic	queu Tag: No g_e* s,*.
+ * Veracic	queu Tag: Mu -lbe 0. u  *
  * Inputsp v* (endpo   , asoc, chunk)tcp.l219i6 +219i 2 cp.iutp_disposiqueu_nPectp_sf_do_5_1B_cp_rt
 k -  tlrk
+nL_ * _b * log >=ask
+nL_max_ * _b * log)))f 		ro*retusutp_sf_tabort_8_4_8(ep, asoc, .ype,iarg,  bmmsndsgtpt +h/*r3.1 A 	 * wi  beeains,* an INIT  _unk MUSTthavw0a zero Veracic	queu
+c * Tag. =+  *_frho al hunk->sutp_hdr->vtag !);
 }+ckro*retusutp_sf_tabort_8_4_8(ep, asoc, .ype,iarg,  bmmsndsgtp+f 	/*rVeracydTo
NINIT  _unk be
da  procesnvng it. *_f 	 Wr_chunk =uamma = co al!rutp_veracy_cp_rtasoc, chunk->g_unk_hdr->type,
cp.l377i6 +383i9 cp.ectp_disposiqueu_nPectp_sf_do_5_1C_ * t = co al!chunk
+ningleton)f 		ro*retu
CTP_DISPOSITION_VIOLATIONtpt +ho al!rutp_vtag_veracy/chunkarasoc) }+ckro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp+f 	/*rGrabdTo
NINIT vegaer.v *_f 	 hunk->subh.snk,_hdr =tl;utp_snk,hdr_  *)  hunk->sL,
+ET_T =cacp.l659,8=+668i12 cp.iutp_disposiqueu_nPectp_sf_do_5_1E_cat b = ckk       besbeectp_sub.ype_nP.ype,ivfous*arg, = ckk      tutp_gma/seq_  *gbmmsndsg
 slowipe _nPrutp_ _unk *chunk =uarg;p ctre _nPectp_ulpev
nt *evtpt +ho al!rutp_vtag_veracy/chunkarasoc) }+ckro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp+f 	/*rRFC 2960 5.1 Normal Eiptbsishmo v l:6an Associ	queu= hv*
 c * E) Up>verecepbueu/l:6To
dCOOKIE ACK, endpo    "A">w*,himovwNcp.l807i13 +820i7 cp.iutp_disposiqueu_nPectp_sf_beat_8_3/ besp ctre _nPectp_ _unk *roply;p ctize_i pays(t_no0;i oy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag. I:6To
Nreceivwd=-c * Veracic	queu Tag_valu_/does noi maqg_Htre receivwr't-ownp-k * Tag_valu_,Htre receivwr shm,hisis(ttly discardaTo
d	 * wi...=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  /* 8.3rk, i
eceivwr l:6To
dHEARTBEAT*nhouldaimmediaqelyecp.l876i11 +883i7 cp.iutp_disposiqueu_nPectp_sf_b * beat_8_3/
 	sctp_sendcr_hb_info_t *hbinfo;iaw */
 			 sd + max_cpd_rval;i oy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag. ...=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  hbinfo =tl;utp_sendcr_hb_info_t *)  hunk->sL,
+ET_T =cp.l1130i6 +1133, 2 cp.ipt_REJiutp_disposiqueu_nPectp_sf_do_une= co al!chunk
+ningleton)f 		ro*retu
CTP_DISPOSITION_VIOLATIONtpt +h/*r3.1 A 	 * wi  beeains,* an INIT  _unk MUSTthavw0a zero Veracic	queu
+c * Tag. =+  *_frho al hunk->sutp_hdr->vtag !);
 }+ckro*retusutp_sf_tabort_8_4_8(ep, asoc, .ype,iarg,  bmmsndsgtp+f 	/*rGrabdTo
NINIT vegaer.v *_f 	 hunk->subh.snk,_hdr =tl;utp_snk,hdr_  *)  hunk->sL,
+ET_T =cacp.l1386i6 +1395,8 cp.ipt_REJectp_disposiqueu_nPectp_sf_do_dup
 	sctp_snk,_g_unk_i *	eer_snk,;p ctre _nPectp_ulpev
nt *evtptctre _nPectp_ _unk *ropl;K+ticp_delrutp_ _unk *err =+	sutp_disposiqueu_nPdisposiqueutp 
  /* _dw_asoc 0sda b+snd-_dw6associ	queu, soaTo
s	f_re noi yet
 c * sud
deffects--i  0sdsafe toarun0To
m o
rA.ucp.l1405i6 +1416,29 cp.ipt_REJectp_disposiqueu_nPectp_sf_do_dup
 		ro*retu
CTP_DISPOSITION_CONSUMEtp h}
rp+	/*rI:6To
Nendpo    is inxTo
dSHUTDOWN-ACK-SENTdipt_
 acp rTcognize 
+c * To
dpeer has rTstar wd (Atp->veA), ii MUSTtNOT so*rpda _dw
+c * associ	queu bur s4stegasrec	cp tre1SHUTDOWN ACK acp sTap an ERROR=+  * chunk  *th a "Cbokie Receivwd while Shutbi + Down"2error cause1to=+  * 0it-peer.=+ *_frho alrutp_ipt_
/asoc, 
HUTDOWN_ACK_SENT))2slow disposiqueu =uectp_sf_do_9_2_rechut * tep, asoc,
+ckkk
CTP_ST_CHUNK(chunk->g_unk_hdr->type),
+ckkkchunkar bmmsndsgtp+	ho al
CTP_DISPOSITION_NOMEM_n=adisposiqueu }+ckkgotoanomem =+=+hoj_bi=aectp_mak
_op_errortasoc, chunk,
ow <	k 
CTP_ERROR_COOKIE_IN_SHUTDOWN,
ow <	k ammaar0)
-+.bsctlerr)frhl	;utp_add_gma/sfg bmmsnds, 
CTP_CMD_REPLY,
ow <	k
CTP_CHUNK(err))ts+=+ 	ro*retu
CTP_DISPOSITION_CONSUMEtp+k}&(s h6 1For now,*faildany  */
nt/un * wd ET_T.  Consud
at*o
dopp->val
 c * choicF l:6rec	cpi + o:6To0sdET_T.
 hv*/pcp.l1883i6 +1917i9 cp.ectp_disposiqueu_nPectp_sf_do_5_2_6_iptlo p 	sutp_addto_chunk(roply, lteringbht), &bht)tpt +h/*rClear-peer's snk,_tag_cag_ed inxassoc as w	f_re c	cpi + a _dwNINIT *_f+	sutp_add_gma/sfg bmmsnds, 
CTP_CMD_CLEAR_INIT_TAG, 
CTP_amma())+ (s h6 1Cnst away To
d best0mopacint, as w	fwa   toaju -
 c * rerun0ii torough msxadnvdeffect.
 hv*/pcp.l2071i13 +2108i7 cp.iutp_disposiqueu_nPectp_sf_do_9_2_chutdb = skb_	u,h( hunk->sL,, lteringsctp_shutdbwnhdr_ ))ho 	c_unk->subh.shutdbwn_hdr =tsdh;i oy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag. I:6To
Nreceivwd=-c * Veracic	queu Tag_valu_/does noi maqg_Htre receivwr't-ownp-k * Tag_valu_,Htre receivwr shm,hisis(ttly discardaTo
d	 * wi...=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  /* Up>vetre recepbueu/l:6To
dSHUTDOWN, To
dpeer endpo    shm,htcp.l2190i13 +2221,7 cp.iutp_disposiqueu_nPectp_sf_do_ecn_cwrt b = sutp_cwrhdr_  *cwrtptctre _nPectp_ _unk *chunk =uarg;p oy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag. I:6To
Nreceivwd=-c * Veracic	queu Tag_valu_/does noi maqg_Htre receivwr't-ownp-k * Tag_valu_,Htre receivwr shm,hisis(ttly discardaTo
d	 * wi...=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  cwr =tl;utp_cwrhdr_  *)  hunk->sL,
+ET_T =cp.l2246i13 +2271,7 cp.iutp_disposiqueu_nPectp_sf_do_ecne/ besb = sutp_ecnehdr_  *ecnetptctre _nPectp_ _unk *chunk =uarg;p oy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag. I:6To
Nreceivwd=-c * Veracic	queu Tag_valu_/does noi maqg_Htre receivwr't-ownp-k * Tag_valu_,Htre receivwr shm,hisis(ttly discardaTo
d	 * wi...=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  ecne =tl;utp_ecnehdr_  *)  hunk->sL,
+ET_T =cp.l2309i13 +2328i7 cp.iutp_disposiqueu_nPectp_sf_eat_ET_T_6_2(= 0s4.2tmp
- 	__u amtst;K oy /*rRFC 2960 8.5 Veracic	queu Tag=*/ *p-k * Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag.=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag)2slowo al!rutp_vtag_veracy/chunkarasoc) 2sl hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_REPORT_BAD_TAG,
 ckkk
CTP_amma())+  		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtpcp.l2569, 3 +2582i7 cp.iutp_disposiqueu_nPectp_sf_eat_ET_T_fast= 0s4.2tmp
- 	__u amtst;K oy /*rRFC 2960 8.5 Veracic	queu Tag=*/ *p-k * Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag.=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag)2slowo al!rutp_vtag_veracy/chunkarasoc) 2sl hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_REPORT_BAD_TAG,
 ckkk
CTP_amma())+  		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtpcp.l2745i11 +2752i7 cp.iutp_disposiqueu_nPectp_sf_eat_s * _6_2(= 0ectp_s * hdr_  *; * h
- 	__u amctst;K oy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag. ...=*/ *_f*/sctlmtohl( hunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  /*rPu,hiTo
dSACK g_unk from tre1ET_TNace wr */pcp.l2895i6 +2898i9 cp.ectp_disposiqueu_nPectp_sf_do_9_2_fival(p ctre _nPectp_ _unk *roply;p ctre _nPectp_ulpev
nt *evtpt +ho al!rutp_vtag_veracy/chunkarasoc) }+ckro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp+f 	/*r10.2 H)1SHUTDOWN COMPLETE noiacic	queu
 hv*
 c * Wo
tu
CTP  osnd_wnd.To
dshutdbwndproceduresa(setp->ve9.2)6To0s
cp.l3205i6 +3211i131 cp.ectp_disposiqueu_nPectp_sf_do_as btu_ * 
 }
 
 /*
+ * PR-
CTP Setp->ve3.6 Receivwr Sud
dIsnd_mo v	queu/l:6PR-
CTP
+ *
+ * Wo
tua FORWARDdTSN g_unk arrivns, tre1ET_TNreceivwr MUSTtfirst updd;_=+ * 0it-cumulawiv
dTSN po    toaTo
dvalu_/garri	d inxtre FORWARDdTSN=+ * chunk, acp tr
n MUSTtfuruo T advaTce 0it-cumulawiv
dTSN po    locally=+ * 0f possi
+	.
+ * Aft
at*o
dabove procesnvng, tre1ET_TNreceivwr MUSTtssopNreports,* any=+ * misnvng TSNs2earliAT tran or equal toatre1_dwNcumulawiv
dTSN po   .
+ *
+ * Veracic	queu Tag:  8.5 Veracic	queu Tag [Normal veracic	queu]
+ *
+ * k, i
e*retuvalu_/id.To
ddisposiqueu l:6To
d _unk.
+ */p(5utp_disposiqueu_nPectp_sf_eat_fwd_tst/ besbeere _nPectp_endpo    *ep,
+ckkk-       besbeere _nPectp_associ	queu *asoc,
+ckkk-       besbeectp_sub.ype_nP.ype,
+ckkk-      vfous*arg, +ckkk-      tutp_gma/seq_  *gbmmsndsg
+slowipe _nPrutp_ _unk *chunk =uarg;p+wtre _nPectp_fwdtst_hdr *fwdtst_hdr =+	_/u16 s(tts+/__u amtst;K+lowo al!rutp_vtag_veracy/chunkarasoc) 2sl+hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_REPORT_BAD_TAG,
+ckkk
CTP_amma())+ +ckro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp+ate+=+ fwdtst_hdr =u(tre _nPectp_fwdtst_hdr *) hunk->sL,
+ET_T =+	c_unk->subh.fwdtst_hdr =ufwdtst_hdr =+	s(t_nomtohs(chunk->g_unk_hdr->	 &gth) =+	s(t_-=altering2Oo Orysutp_g_unkhdr ho+ skb_	u,h( hunk->sL,, s(t)e +=+ tst =amtohl(fwdtst_hdr
+ajw_cum_tst);K+ 
CTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __FUNCTION__, tst) =+=+ /* tre TSN isetoo high--sis(ttly discardaTo
dg_unk acp cbuff on0ii=+  * gwtorng 
etransmitbed lnd_r.=+  *_frho alrutp_tstmap_g_e* (&asoc->peer.tst_map, tst) <;
 }+

gotoadiscard_no
dace;l+f+	sutp_add_gma/sfg bmmsnds, 
CTP_CMD_REPORT_FWDTSN, 
CTP_U32(tst));t+ao als(t_>altering2Oo Orysutp_fwdtst_hdr))l+hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_PROCESS_FWDTSN, 
+ckkk
CTP_CHUNK(chunk));t+a +h/*rCbuff To0sdas rTceivs,* DATA. *_frho alasoc->autoclose 2sl+hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_TIMER_RESTART,l+ckkk
CTP_TOl
CTP_EVENT_TIMEOUT_AUTOCLOSE));t+ate+a +h/*rFIXME:1For now sTap a SACK, bur DATA procesnvng may
+c * sTap anouo T. =+  *_frhiutp_add_gma/sfg bmmsnds, 
CTP_CMD_GEN_SACK, 
CTP_aOFORCE())+ +c/*rStar  tredSACK ore
+.r *_frhiutp_add_gma/sfg bmmsnds, 
CTP_CMD_TIMER_RESTART,l+ckk
CTP_TOl
CTP_EVENT_TIMEOUT_SACK))ts+=+ ro*retu
CTP_DISPOSITION_CONSUMEtp+
+discard_no
dace:=+ ro*retu
CTP_DISPOSITION_DISCARDho+it+&(5utp_disposiqueu_nPectp_sf_eat_fwd_tst_fast(=+	cbesbeere _nPectp_endpo    *ep,
+c besbeere _nPectp_associ	queu *asoc,
+c besbeectp_sub.ype_nP.ype,
+cvfous*arg, +ctutp_gma/seq_  *gbmmsndsg
+slowipe _nPrutp_ _unk *chunk =uarg;p+wtre _nPectp_fwdtst_hdr *fwdtst_hdr =+	_/u16 s(tts+/__u amtst;K+lowo al!rutp_vtag_veracy/chunkarasoc) 2sl+hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_REPORT_BAD_TAG,
+ckkk
CTP_amma())+ +ckro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp+ate+=+ fwdtst_hdr =u(tre _nPectp_fwdtst_hdr *) hunk->sL,
+ET_T =+	c_unk->subh.fwdtst_hdr =ufwdtst_hdr =+	s(t_nomtohs(chunk->g_unk_hdr->	 &gth) =+	s(t_-=altering2Oo Orysutp_g_unkhdr ho+ skb_	u,h( hunk->sL,, s(t)e +=+ tst =amtohl(fwdtst_hdr
+ajw_cum_tst);K+ 
CTP_DEBUG_PRINTK("%s: TSN 0x%x.\n", __FUNCTION__, tst) =+=+ /* tre TSN isetoo high--sis(ttly discardaTo
dg_unk acp cbuff on0ii=+  * gwtorng 
etransmitbed lnd_r.=+  *_frho alrutp_tstmap_g_e* (&asoc->peer.tst_map, tst) <;
 }+

gotoagen_shutdbwn;l+f+	sutp_add_gma/sfg bmmsnds, 
CTP_CMD_REPORT_FWDTSN, 
CTP_U32(tst));t+ao als(t_>altering2Oo Orysutp_fwdtst_hdr))l+hoiutp_add_gma/sfg bmmsnds, 
CTP_CMD_PROCESS_FWDTSN, 
+ckkk
CTP_CHUNK(chunk));t+a +h/*rGo a vegasHap fdace a SACK, nvnce w	f_re chutbi + dbwn. *_frgen_shutdbwn:p+	/*rIsnd_mo vor't-Guud
.=+  *=+  * While t4dSHUTDOWN-SENTdipt_
, tre1SHUTDOWN so ont1MUSTtimmediaqelye+c * respond toaeaus*rTceivwd 	 * wi  beeains,* one or mda  DATA chunk(d) +
 *  *th a SACK, a1SHUTDOWN chunk, acp rTstar  tre T2-shutdbwndore
+=+  *_frhiutp_add_gma/sfg bmmsnds, 
CTP_CMD_GEN_SHUTDOWN, 
CTP_amma())+ +ciutp_add_gma/sfg bmmsnds, 
CTP_CMD_GEN_SACK, 
CTP_FORCE())+ +ciutp_add_gma/sfg bmmsnds, 
CTP_CMD_TIMER_RESTART,l+ckk
CTP_TOl
CTP_EVENT_TIMEOUT_T2_SHUTDOWN))ts+=+        ro*retu
CTP_DISPOSITION_CONSUMEtp+}u+&(/*p v* Procesa an unknbwnd _unk.
  *
  * Setp->v: 3.2. Also, 2.1 inxtre isnd_mo vor't-guud
.=cp.l3239, 3 +3370i7 cp.iutp_disposiqueu_nPectp_sf_unk_chunk(ceu
 
  
CTP_DEBUG_PRINTK("Procesnvng tre unknbwnd _unk ous%d.\n", .ype.chunk);tcoy /*r8.5 Wo
tureceivs,* an 
CTP 	 * wi,cTo
dendpo    MUSTteniurA=-k * Toa cTo
dvalu_/in0To
dVeracic	queu Tag_field l:6To

-c * receivwd SCTP 	 * wi maqg_esdiit-own Tag.  I:6To
Nreceivwd=-c * Veracic	queu Tag_valu_/does noi maqg_Htre receivwr't-ownp-k * Tag_valu_,Htre receivwr shm,hisis(ttly discardaTo
d	 * wi.=*/ *_f*/sctlmtohl(unk_chunk->sutp_hdr->vtag) !);asoc->c.my_vtag) +ho al!rutp_vtag_veracy/unk_chunkarasoc) } 		ro*retusutp_sf_pdiscard(ep, asoc, .ype,iarg,  bmmsndsgtp 
  rwitcha(.ype.chunk & 
CTP_CID_ACTION_MASK 2slcp.l4671,28 +4796,2cpcp.ipp_delrutp_	 * wi *sutp_ootb_	kt_newt b =f 	/*rMak
da transportd
dat*o
dbu* wi, Eliza... *_f 	transportN= rutp_transport_newtsutp_souace(chunk), GFP_ATOMIC) =-= co al!Lransport } kkgotoanomem =coy /*rA@ vcaiA H1_dwN	 * wi 
datc	cpi + tre response. *_f*/	 * wi = t_newtspp_delrutp_	 * wi, GFP_ATOMIC) =-co al!	 * wi 
-<	gotoanomem_	 * wi;
*s h6 1Cnco
da rout/(
dat*o
dtransportN *th To
dchunk't-d squn	queu as
 c * To
dsouace addresa.
 hv*/p 0ectp_transport_rout/(transport, /unueu iutp_addr *)&chunk->d sq,
 ckk     sutp_s (tutp_gwt_ctl_so* ( ) tp f*/	 * wi = rutp_	 * wi_cp_rt	 * wi,cTransport, sport, dport ;f*/	 * wi = rutp_	 * wi_ bturgt	 * wi,cvtag, 0, amma)+ +c	 * wi = rutp_	 * wi_cp_rt&transport->	 * wi,cTransport, sport, dport ;f+c	 * wi = rutp_	 * wi_ bturgt	 * wi,cvtag, 0gtp 
  ro*retu	 * wi;
 f*nomem_	 * wi:=-	sutp_transport_
+	{lLransport ho nomem:p 	ro*retuamma = }lcp.l4701r7 +4818i6 cp.nomem:p vfous;utp_ootb_	kt_
+	{lipp_delrutp_	 * wi *	 * wi 
 	_ 0iutp_transport_
+	{l	 * wi
+Lransport ho-	sutp_	 * wi_
+	{l	 * wi);
 }
 
 /* Seap a iptl
d bokie2error wo
tua invalousCOOKIE ECHOd _unk os(
duap v*/p = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/sm_ipt_
ptbse. *
+ * THeAalgorithm +oautp/sm_ipt_
ptbse.  vic  tcp_clamp_windowautp/sm_ipt_
ptbse. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/sm_ipt_
ptbse. 
 }
 
+@ -160,7 9:34&sysctl_tcp_defaucp.la,5 +a,5 cpu /* SCTP umedAsu "fe_dTce Isnd_mo v	queu
- * (C) Copyright IBM Corp.  }
1,  }
3
+ * (C) Copyright IBM Corp.  }
1,  }
4
  * Copyright (c) 1999-2_tcpCisco, Inc.
  * Copyright (c) 1999-2_t1 Motorola, Inc.
  * Copyright (c) 2_t1 Inqel Corp.lcp.l40i6 +40i7 cpp v*    Hui Huangkk    <hui.huang@nokia. bm>p v*    Daisy Changk    <daisyc@us.ibm. bm>p v*    Ardel+	 Fank    <ardel+	.fan@cpd_l. bm>p+v*    Sridhar Samudralak    <sri@us.ibm. bm>p v*p v* Any bugsnreportnd givwvetoaus w	fw*,hitnyatoafix... any fixesfnh_redfw*,hp v* b
dl4corpord;_d cpdoatre1_dxt SCTP release. cp.l50r7 +51i7 cpp #t4clude <m +oautp/sm.h>
 
 ipt_REJ besbeectp_sm_ptbseisReny_nPbug =2sl*/.fu =uectp_sf_bug, 
+c.fu =uectp_sf_bug,_ 0.name =u"ectp_sf_bug"= };tcocp.l73,7 +74i7 cp. besbeectp_sm_ptbseisReny_nP*ectp_sm_loo} 		ro*retusutp_g_unk_ev
nt_lookup(ev
nt_sub.ype.chunkaript_
); = kb+	 k = ocase1
CTP_EVENT_T_TIMEOUT:=-		DO_LOOKUPl
CTP_EVENT_TIMEOUT_MAX, ore
oe , 
+ckDO_LOOKUPl
CTP_EVENT_TIMEOUT_MAX, ore
oe ,
 ckk  ore
oe _ev
nt_.,
+	); = kb+	 k = Kcp.l486i6 +487,34 cp. besbeectp_sm_ptbseisReny_nPaddip_g_unk_ = TYPE_
CTP_ASCONF_ACK,= }; /*ipt_
_fn_nPaddip_g_unk_ev
nt_.,
+	[][]v*/p 
+#defdi	 TYPE_
CTP_FWD_TSN { \ +c/*rSCTP_STATE_EMPTYv*/ \ +c{.fu =uectp_sf_ootb, .name =u"ectp_sf_ootb"}, \ +c/*rSCTP_STATE_CLOSEDv*/ \ +c{.fu =uectp_sf_tabort_8_4_8, .name =u"ectp_sf_tabort_8_4_8"}, \ +c/*rSCTP_STATE_COOKIE_WAIT *_ \ +c{.fu =uectp_sf_discard_chunkar.name =u"ectp_sf_discard_chunk"}, \ +c/*rSCTP_STATE_COOKIE_ECHOEDv*/ \ +c{.fu =uectp_sf_discard_chunkar.name =u"ectp_sf_discard_chunk"}, \ +c/*rSCTP_STATE_ESTABLISHEDv*/ \ +c{.fu =uectp_sf_eat_fwd_tstar.name =u"ectp_sf_eat_fwd_tst"}, \ +c/*rSCTP_STATE_
HUTDOWN_PENDING */ \ +c{.fu =uectp_sf_eat_fwd_tstar.name =u"ectp_sf_eat_fwd_tst"}, \ +c/*rSCTP_STATE_
HUTDOWN_SENTd*/ \ +c{.fu =uectp_sf_eat_fwd_tst_fastar.name =u"ectp_sf_eat_fwd_tst_fast"}, \ +c/*rSCTP_STATE_
HUTDOWN_RECEIVEDv*/ \ +c{.fu =uectp_sf_discard_chunkar.name =u"ectp_sf_discard_chunk"}, \ +c/*rSCTP_STATE_
HUTDOWN_ACK_SENTv*/ \ +c{.fu =uectp_sf_discard_chunkar.name =u"ectp_sf_discard_chunk"}, \ +} /* tYPE_
CTP_FWD_TSN *_fr
(/*rTo
dpriwiny cpdex(
dat*oiset,
+	 id.To
d _unk .ype.
+ * k, ise bediny cpdex(
dat*oiset,
+	 id.To
dipt_
.
+ */p( besbeectp_sm_ptbseisReny_nPprrutp_ _unk_ev
nt_.,
+	[
CTP_amM_PR
CTP_CHUNK_tYPES][SCTP_STATE_amM_STATES] =2sl+	tYPE_
CTP_FWD_TSN,=+}; /*ipt_
_fn_nPprrutp_ _unk_ev
nt_.,
+	[][]v*/p+
 ipt_REJ besbeectp_sm_ptbseisReny_n
  _unk_ev
nt_.,
+	_unknbwn[SCTP_STATE_amM_STATES] =2sl c/*rSCTP_STATE_EMPTYv*/ucp.l924i6 +953i11 cp. besbeectp_sm_ptbseisReny_nP*ectp_g_unk_ = o al ous>= 0 && cid <= 
CTP_CID_BASE_MAX } 		ro*retu& _unk_ev
nt_.,
+	[cid][ipt_
]tpt +ho alsutp_	rsutp_en,
+	)2slow o al ous== 
CTP_CID_FWD_TSN)t+	kkro*retu&prrutp_ _unk_ev
nt_.,
+	[0][ipt_
]tp+k}&(s hed2trutp_addip_en,
+	 2sl hoo al ous== 
CTP_CID_ASCONF } 		kro*retu&addip_g_unk_ev
nt_.,
+	[0][ipt_
]tp = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/so* wi. *
+ * THeAalgorithm +oautp/so* wi.  vic  tcp_clamp_windowautp/so* wi. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/so* wi. 
 }
 
+@ -160,7 6:14&sysctl_tcp_defaucp.la155i6 +1155i11 cp.SCTP_STATIC.s4.2sutp_c	cpmsgg2Oo Orysock= co al!asoc)2sl ho
CTP_DEBUG_PRINTK("To
rA id.no6associ	queu yet.\n")tpt +hhed2trinfo_flagd.& (MSG_EOF | MSG_ABORT))2slow oj_bi=a-EINVALts+/k	gotoaoe _unlock =+	c}
+
t		6 1C_e* (
datinvalousicpeam agas4st.To
dippeam cbuffs,
 ck * eiuo T to
ddefault dat*o
duswr specacinddippeam cbuffs.
 ck */pcp.l1495,8 +1500i7 cp.SCTP_STATIC.s4.2sutp_recvmsgg2Oo Orysock= cc * rwnd bydTo_.2ambuff. I:6m,hiTo
dET_TNinxTo
dskb isnread,= cc * rwnd 0sdupdd;_d wo
tuTo
dev
nt os(
+	{d.
 ck */p-hoiutp_assoc_rwnd_t4crease(ev
nt
+nndrcvinfo.ninfo_assoc_id,
-<	kk	 cbpind);K+tcsutp_assoc_rwnd_t4crease(ev
nt
+asoc, cbpind);K k	gotoaoe tp h} jeY22ed2t(ev
nt
+msg_flagd.& MSG_NOTIFICATION) ||
 ck   (ev
nt
+msg_flagd.& MSG_EOR)) cp.la940i6 +a944i9 cp.ipt_REJs4.2sutp_c	tsockopt_mappedv4gtOou = *_f trt_REJs4.2sutp_c	tsockopt_maxsegg2Oo Orysock *sk, char *optval, s4.2opts(t)
 slowipe _nPrutp_associ	queu *asoce owipe _nPsis,ivegas*pos;p+wtre _nPectp_opt *sp =uectp_sk(sk);tc.s4.2val;i o co alopts(t <alteringcpt)) cp.la948r7 +1955i15 cp.ipt_REJs4.2sutp_c	tsockopt_maxsegg2Oo Or} 		ro*retu-EFAULT = co al(val < 8) || (val >.SCTP_MAX_CHUNK_LEN) } 		ro*retu-EINVALts-	sutp_sk(sk)->uswr_frag_noval;i+	sp->uswr_frag_noval;i+ +ho alval)2slow /* Updd;_uTo
dfrag_po    l:6To
dexisbi + associ	queus. *_frhliAs,ifor_eaus(pos, &(sp->ep
+asocs))2slow  asoc =usis,isReny(pos, ipe _nPrutp_associ	queu, asocsgtp+	h asoc->frag_po    =uectp_frag_po   (sp, asoc->pmtu); t+	c}
+ate 
  ro*retu0 = }lcp.l2523i1cp_2538i6 cp.ipt_REJs4.2sutp_g	tsockopt_sutp_spt_ud(sp ctrt_ud.strt__p	cpET_TN= rutp_tstmap_p	cpi +(&asoc->peer.tst_map);p ctrt_ud.strt__s4strms );asoc->c.ssnk,_max_cpscpeams;p ctrt_ud.strt__outiprms );asoc->c.ssnk,_num_oscpeams;py /*rJu -liu x */(
rag_po    updd;_. *_f*/sctlsutp_sk(sk)->uswr_frag) -d asoc->frag_po   
-<	k= min_n(   , asoc->frag_po   , sutp_sk(sk)->uswr_frag);p ctrt_ud.strt__fragmo v	queu_po    =uasoc->frag_po   ;p ctrt_ud.strt__priwiny.spinfo_assoc_idN= rutp_assoc2id(transport->asoc);p cmemcpy(&trt_ud.strt__priwiny.spinfo_addresa,
cp.l4380r7 +4391i11 cp.out:p 	ro*retuerr =ca do_error:=-	j_bi=a-ECONNREFUSEDts+/s,arasoc->cbuffers[SCTP_COUNTER_INIT_ERROR] + 1s>=
ow <	k  asoc->max_cp_r_ ttemptd) +

j_bi=a-ETIMEDOUTts+/jeY2}+ckj_bi=a-ECONNREFUSEDts 	gotoaoe tp a do_cpd_rrup;_d:
cp.l4486i7 +4501i7 cp.ipt_REJvfousectp_sock_migrd;_g2Oo Orysoc
 hv*/p 0ectp_skb_for_eaus(sL,, &oldsk
+nL_receivw_
 			,2tmp)2sl hoev
nt =uectp_skb2ev
nt(sL, ho-	bsctlev
nt
+nndrcvinfo.ninfo_assoc_ids== assoc)2slow o alev
nt
+asocs== assoc)2sl 		k_/ikb_unlink(dL,, lL,
+l@ -);l 		k_/ikb_
 			bL,il(&newsk
+nL_receivw_
 			,2sL, ho 	c}
cp.l4515i7 +4530i7 cp.ipt_REJvfousectp_sock_migrd;_g2Oo Orysoc
 hhv*/p 00ectp_skb_for_eaus(sL,, &oldsp
+pd_lobby,2tmp)2sl hooev
nt =uectp_skb2ev
nt(sL, ho-	bbsctlev
nt
+nndrcvinfo.ninfo_assoc_ids== assoc)2slow  o alev
nt
+asocs== assoc)2sl 		kk_/ikb_unlink(dL,, lL,
+l@ -);l 		kk_/ikb_
 			bL,il(
 			,2sL, ho 	c	}i = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/sysctl. *
+ * THeAalgorithm +oautp/sysctl.  vic  tcp_clamp_windowautp/sysctl. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/sysctl. 
 }
 
+@ -160,7 6:06&sysctl_tcp_defaucp.la,5 +a,5 cpu /* SCTP umedAsu "fe_dTce Isnd_mo v	queu
- * Copyright (c) 2_t2 Inqern	queual Buninesa Mausines Corp.l+ * (C) Copyright IBM Corp.  }
2,  }
4
  * Copyright (c) 2_t2 Inqel Corp.l  *
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
cp.l35i6 +35i7 cpp v*    Jeu Griwm             <jgriwm@us.ibm. bm>p v*    Ardel+	 Fan           <ardel+	.fan@cpd_l. bm>p v*    Ryan Laywr            <rmlaywr@us.ibm. bm>p+v*    Sridhar Samudrala     <sri@us.ibm. bm>p v*p v* Any bugsnreportnd givwvetoaus w	fw*,hitnyatoafix... any fixesfnh_redfw*,hp v* b
dl4corpord;_d cpdoatre1_dxt SCTP release. cp.l170i6 +a71i14 cp.ipt_REJctl_t,
+	 rutp_t,
+	[] =2sl c	.mode	k= 0644il c	.	roci_sndlerk= &	rocido   vec
 h},l+cslow .ctl_namek= NET_
CTP_PR
CTP_ENABLE,l+c	.	rocnamek= "	rsutp_en,
+	",l+c	.ET_T	k= &sutp_	rsutp_en,
+	,l+c	.maxs(t	k= lteringcpt),l+c	.mode	k= 0644il+c	.	roci_sndlerk= &	rocido   vec
+h},l 	{ .ctl_name_no0 }
 };tco = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/transport. *
+ * THeAalgorithm +oautp/transport.  vic  tcp_clamp_windowautp/transport. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/transport. 
 }
 
+@ -160,7 8:39&sysctl_tcp_defaucp.la18r7 +118i6 cp.ipe _nPectp_transportd*iutp_transport_iu
 hINIT_LIST_HEAD(&peer
+Lransmitbed ho 	INIT_LIST_HEAD(&peer
+c	cp_ready ho 	INIT_LIST_HEAD(&peer
+transports ho-	sutp_	 * wi_cp_rt&peer
+	 * wi,c	ent, 0, 0gtp 
  /*rSe-(up6To
d
etransmissueu x */r.v *_f 	snk,_t */rt&peer
+T3_rtx_t */r)+ cp.la69i6 +168,8 cp.vfousectp_transport_d sqroy(tOo Orysutp_
r o altransport->asoc)l hoiutp_associ	queu_put(transport->asoc);p =+        sutp_	 * wi_
+	{l&transport->	 * wigtp+f 	dst_release(transport->d -);l 	k
+	{lLransport ho o
CTP_DBG_OBJCNT_DEClLransport ho = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/tstmap. *
+ * THeAalgorithm +oautp/tstmap.  vic  tcp_clamp_windowautp/tstmap. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/tstmap. 
 }
 
+@ -160,7 5:18&sysctl_tcp_defaucp.la,7 +1i7 cpp /* SCTP umedAsu "fe_dTce Isnd_mo v	queu
+ * (C) Copyright IBM Corp.  }
1,  }
4
  * Copyright (c) 1999-2_tcpCisco, Inc.
  * Copyright (c) 1999-2_t1 Motorola, Inc.
- * Copyright (c) 2_t1-2_t3 Inqern	queual Buninesa Mausines, Corp.l  * Copyright (c) 2_t1 Inqel Corp.l  *
  * trt *file t *part/l:6To
d
CTP umedAsu "fe_dTce Isnd_mo v	queu
cp.l36i6 +36i7 cpp v*    La Monqe H.P. Yarro,hi<piggy@acm.org>p v*    Jeu Griwm             <jgriwm@us.ibm. bm>p v*    Karl Knution          <karl@atr
na.usicago.il.us>p+v*    Sridhar Samudrala     <sri@us.ibm. bm>p v*p v* Any bugsnreportnd givwvetoaus w	fw*,hitnyatoafix... any fixesfnh_redfw*,hp v* b
dl4corpord;_d cpdoatre1_dxt SCTP release. cp.l253i6 +254,40 cp.s4.2sutp_tstmap_ajet_gap_ * t besbeeOo O
= ro*retuended;
 }
 
(/*rMark To0sdaap any lowwr TSN asfneeu.r *_frvfousectp_tstmap_skip(ipe _nPectp_tstmap *map, __u amtstg
+slow_/i amgap =+=+ /* Vacuously eq = any TSN whius*precednd.To
dmap base o+=+  * exceedscTo
dend/l:6To
dmap.=+  *_frho alTSN_lt(tstarmap->base_tst) }+ckro*retts+/s,ar!TSN_lt(tstarmap->base_tst +rmap->s(t + map->s(t) }+ckro*retts+=+ /* Bump6To
dmax.r *_frho alTSN_lt(map->max_tst_se &, tst) }+ckmap->max_tst_se & = tstts+=+ /* Assert: TSN isein range.r *_frhgap = tst -rmap->base_tst +r1ts+-+ /* Mark Toe TSNs2as rTceivnd.r *_frho algap <= map->s(t)}+ckmemc	2/map->tst_map, 0x
1, gap);t+ajeY22{}+ckmemc	2/map->tst_map, 0x
1, map->s(t);}+ckmemc	2/map->overf vw_map, 0x
1, lgap - map->s(t) tp+ate+=+ /*rGo fixrpdany inqern	l TSN mappi + vari,
+	seincludi +=+  * cumulawiv
_tst_ * _po   .=+  *_frhectp_tstmap_updd;_(map);p+it+& /********************************************************************p v* 2nd/Lev
l Abipeatp->vsp v********************************************************************/p = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/ulpev
nt. *
+ * THeAalgorithm +oautp/ulpev
nt.  vic  tcp_clamp_windowautp/ulpev
nt. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/ulpev
nt. 
 }
 
+@ -160,7 9:50&sysctl_tcp_defaucp.la,7 +1i7 cpp /* SCTP umedAsu "fe_dTce Isnd_mo v	queu
+ * (C) Copyright IBM Corp.  }
1,  }
4
  * Copyright (c) 1999-2_tcpCisco, Inc.
  * Copyright (c) 1999-2_t1 Motorola, Inc.
- * Copyright (c) 2_t1 Inqern	queual Buninesa Mausines, Corp.l  * Copyright (c) 2_t1 Inqel Corp.l  * Copyright (c) 2_t1 Nokia, Inc.
  * Copyright (c) 2_t1 La Monqe H.P. Yarro,hocp.l77,7 +77i7 cp.fail:p /* Ink,ializeNan ULPdev
nt from an givwveskb.v *_f vfousectp_ulpev
nt_cp_rttre _nPectp_ulpev
nt *eve  , s4.2msg_flagd)
 sl-kmemc	2/eve  , ltering2Oo Orysutp_ulpev
nt), 0x
0)
-+.memc	2/eve  , 0, ltering2Oo Orysutp_ulpev
nt) ho oev
nt
+msg_flagd.=2msg_flagd;
 }
 
cp.l590,8 +590,7 cp.ipe _nPectp_ulpev
nt *ectp_ulpev
nt_mak
l 		kk	wipe _nPrutp_ _unk *chunk,l 		kk	ws4.2gfp)
 sl-ktre _nPectp_ulpev
nt *eve  ;l-ktre _nPectp_nndrcvinfo *info;i+ktre _nPectp_ulpev
nt *eve   =uamma = ctre _nPek_ace  *skb;p ctize_i paddvng, s(ttst cp.l624,1t1 +623,21 cp.ipe _nPectp_ulpev
nt *ectp_ulpev
nt_mak
l 	/* Ink,ializeNev
nt  *th flagd.0.v *_f 	ectp_ulpev
nt_cp_rteve  , 0 tp f*/ev
nt
+io a=usutp_g_unk_io (chunk);t-f 	ectp_ulpev
nt_receivw_ET_Tteve  , asoc);p =-	info =tl;re _nPectp_nndrcvinfo *) &ev
nt
+nndrcvinfo;t-fy /*rSo* wis API Extensueus(
dat
CTP
-k * Setp->ve5.2.2 SCTP Hegaer Informaqueu Sre _nureal
CTP_SNDRCV)=*/ *p-k * ninfo_scpeam:60, biit-( */
 			 inqeg/r)=*/ *p-k * For recvmsgg)6To
d
CTP st *  placnd.To
dmesaage'sdippeam numbeatin=-k * Tois_valu_.=*/ *_f*/snfo
+ninfo_scpeam_nomtohs(chunk->subh.ET_T_hdr->icpeam);t-fy /*rSo* wis API Extensueus(
dat
CTP
-k * Setp->ve5.2.2 SCTP Hegaer Informaqueu Sre _nureal
CTP_SNDRCV)=*/ *p-k * ninfo_ssn:60, biit-( */
 			 inqeg/r)=*/ *p-k * For recvmsgg)6Tois_valu_  beeains.To
dippeam sequdTce numbeatTo_.=-k * To
d
emot
dendpo    placnd inxtre DATA chunk.v For fragmo vwd=-c * mesaages6Tois_id.To
diame_numbeat
datm,hiveOivwries6l:6To
dmesaage=-c * (o amda  tran one recvmsgg)6id.needed toaread6To
dmesaage).=*/ *_f*/snfo
+ninfo_sst_nomtohs(chunk->subh.ET_T_hdr->ist) =-fy        /*rSo* wis API Extensueus(
dat
CTP
-k * Setp->ve5.2.2 SCTP Hegaer Informaqueu Sre _nureal
CTP_SNDRCV)=*/ *p-k * ninfo_ppid:  ambiit-( */
 			 inqeg/r)=*/ *p-k * In recvmsgg)6Tois_valu_ is=-k * To
diame_0nformaqueudTo_.2wa *passed bydToe upper laywr inxtre peer=-k * applic	queu.v Please noiedTo_.2byte o+aer issues6_re NOT accbuffed=-c * 
datmcp triseinformaqueudi *passed opaqudly bydToe 
CTP st *  from=-c * one end toa*o
douo T.=*/ *_f*/snfo
+ninfo_ppid_nochunk->subh.ET_T_hdr->ppid;t-fy /*rSo* wis API Extensueus(
dat
CTP
-k * Setp->ve5.2.2 SCTP Hegaer Informaqueu Sre _nureal
CTP_SNDRCV)=*/ *p-k * ninfo_flagd:60, biit-( */
 			 inqeg/r)=*/ *p-k * trt *field may  beeaindany l:6To
dfo@ vwi + flagd.and 0sd osnosed of=-k * a biiwise OR l:6To
s
dvalu_s.=*/ *p-k * recvmsgg)6flagd:=*/ *p-k * MSG_UNORDERED - trt *flagdi *prec	ct wo
tuTo
dmesaage2wa *c	ctp-k *                 non-o+aer{d.
-  *_frhev
nt
+ncpeam_nomtohs(chunk->subh.ET_T_hdr->icpeam);trhev
nt
+nst_nomtohs(chunk->subh.ET_T_hdr->ist) =rhev
nt
+ppid_nochunk->subh.ET_T_hdr->ppid;t ho al hunk->g_unk_hdr->flagd.& 
CTP_DATA_UNORDERED) sl-k/snfo
+ninfo_flagd.|= MSG_UNORDERED;t-fy  /*rninfo_cumtsn:6 ambii-( */
 			 inqeg/r)=*// *p-kk * trt *field w*,hiholdaTo
dgurr	ct cumulawiv
dTSN asp-kk * knbwndbydToe u ontlyi + SCTP laywr.v NoiedTot *field isp-kk * 
 	or_d wo
tuc	cpi + and/lnly valous
datm rTceivnp-kk * operaqueu wo
tucinfo_flagd._re c	  toaMSG_UNORDERED.p-kk */l-k/snfo
+ninfo_cumtsnN= rutp_tstmap_gwt_ctst/&asoc->peer.tst_map);p+	hev
nt
+flagd.|= MSG_UNORDERED;t+	hev
nt
+cumtsnN= rutp_tstmap_gwt_ctst/&asoc->peer.tst_map);p h}
-fy /*rNoie:  For reassembly, we.need toahavw0To
dfragmo v	queu/biit.p-k * For now,*merge6To
s
dcpdoatre1msg_flagd, nvnce those/biip-k * possip->vsf_re noi used.
-  *_frhev
nt
+tst =amtohl(chunk->subh.ET_T_hdr->tst) = oev
nt
+msg_flagd.|= chunk->g_unk_hdr->flagd;
-fy /*rW*th 04 draft, tstimovwsdcpdoanndrcvinfo. *_f*/snfo
+ninfo_tst =amtohl(chunk->subh.ET_T_hdr->tst) =-fy /*rConqext id.noi used otureceive. *_f*/snfo
+ninfo_conqext no0;i-fy /*rSo* wis API Extensueus(
dat
CTP
-k * Setp->ve5.2.2 SCTP Hegaer Informaqueu Sre _nureal
CTP_SNDRCV)=*/ *p-k * ninfo_assoc_id: lterin2trutp_assoc_t)=*/ *p-k * tr
dassoci	queu _sndle*field, ninfo_assoc_id,iholdd.To
diden,ucint=-c * 
dattr
dassoci	queu annbufcnd inxtre COMMUNICATION_UP noiacic	queu.p-k * A,hinoiacic	queuss
datm givwveassoci	queu _svw0To
diame_0den,ucint.p-k * I 	or_d 
datTCP-ipyle so* wis.=*/ *_f*/snfo
+ninfo_assoc_idN= rutp_assoc2id(asoc);p-fy ro*retueve  ;l+/ev
nt
+io a=usutp_g_unk_io (chunk);t 
.fail:p-	ro*retuamma =+ ro*retueve  ;l }
 
 /* CreaiA H1	 r,ialdveOivwry reld;_d ev
nt.ocp.l797i11 +716,77 cp._/u16 ectp_ulpev
nt_gwt_noiacic	queu_.ypf vfousectp_ulpev
nt_read_nndrcvinfo/ besbeere _nPectp_ulpev
nt *eve  ,
= ckk   ere _nPmsghdr *msghdr)
 sl-ko al!rutp_ulpev
nt_cs_noiacic	queu(ev
nt)  sl-k/put_cmsggmsghdr, IPPROTO_
CTP, 
CTP_SNDRCV,
-<	k ltering2Oo Orysutp_nndrcvinfo),
-<	k (vfous*) &ev
nt
+nndrcvinfo ho-	}i+ktre _nPectp_nndrcvinfo sinfo;i+ +ho alsutp_ulpev
nt_cs_noiacic	queu(ev
nt) }+ckro*retts+=+ /* So* wis API Extensueus(
dat
CTP
+ k * Setp->ve5.2.2 SCTP Hegaer Informaqueu Sre _nureal
CTP_SNDRCV)=+ k *
+ k * ninfo_scpeam:60, biit-( */
 			 inqeg/r)=+ k *
+ k * For recvmsgg)6To
d
CTP st *  placnd.To
dmesaage'sdippeam numbeatin=+ k * Tois_valu_.=+ k*_frheinfo.ninfo_ncpeam_noev
nt
+ncpeam+ +c/*rninfo_ssn:60, biit-( */
 			 inqeg/r)=+  *=+  * For recvmsgg)6Tois_valu_  beeains.To
dippeam sequdTce numbeatTo_.=+c * To
d
emot
dendpo    placnd inxtre DATA chunk.v For fragmo vwd=+c * mesaages6Tois_id.To
diame_numbeat
datm,hiveOivwries6l:6To
dmesaage=+c * (o amda  tran one recvmsgg)6id.needed toaread6To
dmesaage).=+  *_frheinfo.ninfo_nst =aev
nt
+nst+ +c/*rninfo_ppid:  ambiit-( */
 			 inqeg/r)=+  *=+  * In recvmsgg)6Tois_valu_ is=+c * To
diame_0nformaqueudTo_.2wa *passed bydToe upper laywr inxtre peer=+k * applic	queu.v Please noiedTo_.2byte o+aer issues6_re NOT accbuffed=+c * 
datmcp triseinformaqueudi *passed opaqudly bydToe 
CTP st *  from=+c * one end toa*o
douo T.=+  *_frheinfo.ninfo_ppid_noev
nt
+ppid+ +c/*rninfo_flagd:60, biit-( */
 			 inqeg/r)=+  *=+  * trt *field may  beeaindany l:6To
dfo@ vwi + flagd.and 0sd osnosed of=+k * a biiwise OR l:6To
s
dvalu_s.=+  *=+  * recvmsgg)6flagd:=+  *=+  * MSG_UNORDERED - trt *flagdi *prec	ct wo
tuTo
dmesaage2wa *c	ctp+k *                 non-o+aer{d.
+  *_frheinfo.ninfo_flagd.=2ev
nt
+flagd+ +c/*rninfo_tsn:6 ambii-( */
 			 inqeg/r)=+  *=+  * For tre receivi + nvde,dTot *field holdd.adTSN To_.2wa *
+c * ass
 			 toaone/l:6To
d
CTP DT_TNChunks.
+  *_frheinfo.ninfo_tst =aev
nt
+tst+ +c/*rninfo_cumtsn:6 ambii-( */
 			 inqeg/r)=+  *=+  * trt *field w*,hiholdaTo
dgurr	ct cumulawiv
dTSN asp+k * knbwndbydToe u ontlyi + SCTP laywr.v NoiedTot *field isp+k * 
 	or_d wo
tuc	cpi + and/lnly valous
datm rTceivnp+k * operaqueu wo
tucinfo_flagd._re c	  toaMSG_UNORDERED.p+  *_frheinfo.ninfo_cumtsnN= ev
nt
+cumtsn+ +c/*rninfo_assoc_id: lterin2trutp_assoc_t)=+  *=+  * tr
dassoci	queu _sndle*field, ninfo_assoc_id,iholdd.To
diden,ucint=+c * 
dattr
dassoci	queu annbufcnd inxtre COMMUNICATION_UP noiacic	queu.p+k * A,hinoiacic	queuss
datm givwveassoci	queu _svw0To
diame_0den,ucint.p+k * I 	or_d 
datone-to-one/ipyle so* wis.=+  *_frheinfo.ninfo_assoc_idN= rutp_assoc2id(ev
nt
+asoc) =+=+ /* trese*fieldsf_re noi used while receivi +. *_frheinfo.ninfo_conqext no0;irheinfo.ninfo_timetoOivw no0;irirhput_cmsggmsghdr, IPPROTO_
CTP, 
CTP_SNDRCV,
+	k ltering2Oo Orysutp_nndrcvinfo), (vfous*)&sinfo ho }
 
 /* Stubdskb d sqr Oror.v *_fcp.l831i14 +816,14 cp.ipt_REJinline vfousectp_ulpev
nt_c	 _ownp oiutp_associ	queu_hold(g2Oo Orysutp_associ	queu *)asoc);p cskb = rutp_ev
nt2skb(ev
nt);p cskb
+nL =uasoc->base.sk;f*/ev
nt
+nndrcvinfo.ninfo_assoc_ids= rutp_assoc2id(asoc);p+/ev
nt
+asoc =ug2Oo Orysutp_associ	queu *)asoc;p cskb
+d sqr Oror =uectp_stub_r
+	{ho }
 
 /* A ltsnd_ d sqr Oror toagivw(up6To
d
efe_dTce toa*o
dassoci	queu. *_f trt_REJs4line vfousectp_ulpev
nt_release_ownerttre _nPectp_ulpev
nt *eve  )
 sl-ktutp_associ	queu_put(ev
nt
+nndrcvinfo.ninfo_assoc_id)+ +ciutp_associ	queu_put(ev
nt
+asoc);p }
 
 /* Do accbuffi + for bytes rTceivnd and/holdaad
efe_dTce toa*o
dassoci	queufcp.l854i6 +839i9 cp.ipt_REJvfousectp_ulpev
nt_receivw_ET_Ttsf 	ectp_ulpev
nt_c	 _ownerteve  , asoc);p csutp_assoc_rwnd_decrease(asoc, ikb_vegalen(sL, )tpt +ho al!rL,
+ET_T_s(t)}+ckro*retts+=  /*rNoie:  Noi cleari + tre en,ureNev
nt tre _nPas6Tois_id.ju - a
 c * fragmo v/l:6To
dreal ev
nt.  Howev
r, we.st*,hineed toado rwnd
 c * accbuffi +.ocp.l880,8 +868i1cpcp.ipt_REJvfousectp_ulpev
nt_release_ET_Ttsf 	v*/p 
 cskb = rutp_ev
nt2skb(ev
nt);p-oiutp_assoc_rwnd_t4crease(ev
nt
+nndrcvinfo.ninfo_assoc_id,
-<	kk ikb_vegalen(sL, )tp+csutp_assoc_rwnd_t4crease(ev
nt
+asoc, ikb_vegalen(sL, )tp+ +ho al!rL,
+ET_T_s(t)}+ckgotoadonetpt=  /*rDon'i 
daget0To
dfragmo vs. *_f 	for (frag_noikb_shinfo/sL, ->frag_l@ -;dfrag;dfrag =ufrag
+ajxt 2slcp.l891i6 +881,8 cp.ipt_REJvfousectp_ulpev
nt_release_ET_Ttsf 	hv*/p 00ectp_ulpev
nt_release_ET_Ttsctp_skb2ev
nt(frag));p h}
+
+done:f 	ectp_ulpev
nt_release_ownertev
nt);p }tco = tp->rcv_wnd;
+
 	maxwin = tcp_full_space(s,);
,
 	df (tp->autp/ulp
 			. *
+ * THeAalgorithm +oautp/ulp
 			.  vic  tcp_clamp_windowautp/ulp
 			. 
 }
 
+/* Receiver "autotuning" code.
+ *
+ * THeAalgorithm +oautp/ulp
 			. 
 }
 
+@ -160,7 4:18&sysctl_tcp_defaucp.la,7 +1i7 cpp /* SCTP umedAsu "fe_dTce Isnd_mo v	queu
+ * (C) Copyright IBM Corp.  }
1,  }
4
  * Copyright (c) 1999-2_tcpCisco, Inc.
  * Copyright (c) 1999-2_t1 Motorola, Inc.
- * Copyright (c) 2_t1-2_t3 Inqern	queual Buninesa Mausines, Corp.l  * Copyright (c) 2_t1 Inqel Corp.l  * Copyright (c) 2_t1 Nokia, Inc.
  * Copyright (c) 2_t1 La Monqe H.P. Yarro,hocp.l79,7 +79i7 cp.fail:p tre _nPectp_ulpq *ectp_ulpq_cp_rttre _nPectp_ulpq *ulpq,
= ckk ipe _nPrutp_associ	queu *asoc)
 sl-kmemc	2/ulpq, ltering2Oo Orysutp_ulpq), 0x
0)
-+.memc	2/ulpq, 0, ltering2Oo Orysutp_ulpq)gtp 
  ulpq
+asoc =uasoc;p cskb_
 			bvega_cp_rt&ulpq
+reasmgtpcp.l25a,7 +251i7 cp.ipt_REJs4line vfousectp_ulpq_stor__reasmp ctre _nPectp_ulpev
nt *ceve  ;l /__u amtst,mctst;K oy tsnN= ev
nt
+nndrcvinfo.ninfo_tsn+ +ctst =aev
nt
+tst+  
  /*rSe22ed2ii-b= tngd._tcTo
dend. *_f 	nos_noikb_peekbL,il(&ulpq
+reasmgtpcp.l262,7 +262i7 cp.ipt_REJs4line vfousectp_ulpq_stor__reasmp 
  /*rShortdcircuii-ju - droppi + ii-_tcTo
dend. *_f 	cev
nt =uectp_skb2ev
nt(nos);p-octst =acev
nt
+nndrcvinfo.ninfo_tsn+ +cctst =acev
nt
+tst+  ho alTSN_lt(ctst,mtst) 2sl c	_/ikb_
 			bL,il(&ulpq
+reasm, rutp_ev
nt2skb(ev
nt))+  		ro*rettpcp.l27a,7 +271i7 cp.ipt_REJs4line vfousectp_ulpq_stor__reasmp c/*rFicp tre1right placn inxtrid.l@ -. We.stda  tremdbydTSN.v *_f 	ekb_
 			bwalk(&ulpq
+reasm, nos)2sl c	cev
nt =uectp_skb2ev
nt(nos);p-ooctst =acev
nt
+nndrcvinfo.ninfo_tsn+ +ccctst =acev
nt
+tst+  l hoo alTSN_lt(tstarctst) }= ckb+	 k =cp.l368r7 +368r7 cp.ipt_REJs4line ipe _nPectp_ulpev
nt *ectp
 hv*/p 0ekb_
 			bwalk(&ulpq
+reasm, nos)2sl c	cev
nt =uectp_skb2ev
nt(nos);p-ooctst =acev
nt
+nndrcvinfo.ninfo_tsn+ +ccctst =acev
nt
+tst+  l horwitcha(cev
nt
+msg_flagd.& 
CTP_DATA_FRAG_MASK 2sl c	case1
CTP_DATA_FIRST_FRAG:
cp.l425i7 +425r7 cp.ipt_REJs4line ipe _nPectp_ulpev
nt *ectp
 p 0ekb_
 			bwalk(&ulpq
+reasm, nos)2sl c	cev
nt =uectp_skb2ev
nt(nos);p-ooctst =acev
nt
+nndrcvinfo.ninfo_tsn+ +ccctst =acev
nt
+tst+  l horwitcha(cev
nt
+msg_flagd.& 
CTP_DATA_FRAG_MASK 2sl c	case1
CTP_DATA_MIDDLE_FRAG:
cp.l486i7 +486r7 cp.ipt_REJs4line ipe _nPectp_ulpev
nt *ectp
 h /*rDo noi ev
n bouo T unlesa Tois_id.To
d_dxt tst to= cc * beiveOivwr{d.
 ck */p-hoctsnN= ev
nt
+nndrcvinfo.ninfo_tsn+ +coctsnN= ev
nt
+tst+  hoctsnap =uectp_tstmap_gwt_ctst/&ulpq
+asoc->peer.tst_map);p hoo alTSN_lte(ctst,mctsnap) } 		kro*val =sectp_ulpq_
etriev
_	 r,ial/ulpqgtpcp.l517r7 +517r7 cp.ipt_REJs4line ipe _nPectp_ulpev
nt *ectp
 p 0ekb_
 			bwalk(&ulpq
+reasm, nos)2sl c	cev
nt =uectp_skb2ev
nt(nos);p-ooctst =acev
nt
+nndrcvinfo.ninfo_tsn+ +ccctst =acev
nt
+tst+  l horwitcha(cev
nt
+msg_flagd.& 
CTP_DATA_FRAG_MASK 2sl c	case1
CTP_DATA_FIRST_FRAG:
cp.l563i15 +563i15 cp.ipt_REJs4line vfousectp_ulpq_
etriev
_orl /__u16 eid,icsid;t h__u16 est,mcsst;K oy sid_noev
nt
+nndrcvinfo.ninfo_ncpeam+ y ssnN= ev
nt
+nndrcvinfo.ninfo_nst+ +csid_noev
nt
+ncpeam+ +cnst =aev
nt
+nst+  	sn  =a&ulpq
+asoc->sstmap->it+  
  /*rW	f_re holdi + tre chunksdbydncpeam,dbydSSN.v *_f 	ectp_skb_for_eaus(pos, &ulpq
+lobby,2tmp)2sl hocev
nt =uttre _nPectp_ulpev
nt *) nos->cb;p-oocsid_nocev
nt
+nndrcvinfo.ninfo_ncpeam+ y 	csst =acev
nt
+nndrcvinfo.ninfo_ssn+ +cccsid_nocev
nt
+ncpeam+ +c	csst =acev
nt
+nst+  l ho/*rHsvw0we gone/too far?v *_f 	ho al sid_>altd) cp.l609i12 +609i12 cp.ipt_REJs4line vfousectp_ulpq_stor__o+aer  		ro*rettp ate 
y sid_noev
nt
+nndrcvinfo.ninfo_ncpeam+ y ssnN= ev
nt
+nndrcvinfo.ninfo_nst+ +csid_noev
nt
+ncpeam+ +cnst =aev
nt
+nst+  	f 	cev
nt =uttre _nPectp_ulpev
nt *) nos->cb;p-ocsid_nocev
nt
+nndrcvinfo.ninfo_ncpeam+ y csst =acev
nt
+nndrcvinfo.ninfo_ssn+ +ccsid_nocev
nt
+ncpeam+ +ccsst =acev
nt
+nst+  hed2trid_>acsid 2sl c	_/ikb_
 			bL,il(&ulpq
+lobby,2rutp_ev
nt2skb(ev
nt))+  		ro*rettpcp.l630,8 +630,8 cp.ipt_REJs4line vfousectp_ulpq_stor__o+aer  	v*/p 0ekb_
 			bwalk(&ulpq
+lobby,2nos)2sl c	cev
nt =uttre _nPectp_ulpev
nt *) nos->cb;p-oocsid_nocev
nt
+nndrcvinfo.ninfo_ncpeam+ y 	csst =acev
nt
+nndrcvinfo.ninfo_ssn+ +cccsid_nocev
nt
+ncpeam+ +c	csst =acev
nt
+nst+  l hoo al sid_>altd) = ckb+	 k =cp.l656,8 +656,8 cp.ipt_REJs4line ipe _nPectp_ulpev
nt *ectp
 h ro*retueve  ;l =  /*rNoie: To
dippeam ID mu - beiveracied befda  trisnroutine.v *_fy sid_noev
nt
+nndrcvinfo.ninfo_ncpeam+ y ssnN= ev
nt
+nndrcvinfo.ninfo_nst+ +csid_noev
nt
+ncpeam+ +cnst =aev
nt
+nst+  	sn  =a&ulpq
+asoc->sstmap->it+  
  /*rIa Tois_To
dexpec;_d SSN(
dat*oiseippeam ID?v *_fcp.l680i6 +680i71 cp.ipt_REJs4line ipe _nPectp_ulpev
nt *ectp
 hro*retueve  ;l }
 
(/*rHelper funtp->vetoagauo T ekbs To_.2_svw0possi
+y becom_=+ * o+aer{ddbyd
dawardaTsveskippi + uo irivep	cpenci_s.=+ */p(5pt_REJs4line vfousectp_ulpq_
eap_o+aer{dttre _nPectp_ulpq *ulpqg
+slowipe _nPrk_ace  *pos, *tmp
-+ktre _nPectp_ulpev
nt *ceve  ;l+ktre _nPectp_ulpev
nt *eve   =uamma =+ktre _nPectp_nppeam *in;lowipe _nPrk_ace ivegastemp =+	_/u16 ceid,icsst;K+lowon  =a&ulpq
+asoc->sstmap->it+ +=+ /* W	f_re holdi + tre chunksdbydncpeam,dbydSSN.v *_f+	ectp_skb_for_eaus(pos, &ulpq
+lobby,2tmp)2sl+c	cev
nt =uttre _nPectp_ulpev
nt *) nos->cb;p+cccsid_nocev
nt
+ncpeam+ +c	csst =acev
nt
+nst+ +=+ oo al sst !=uectp_sst_peek(in,icsid) }+ckkb+	 k =+=+ o/*rFduap i , lo eq = inxTo
dsstmap. *_k-      
+tcsutp_sst__dxt(in,icsid) =+=+ o_/ikb_unlink(pos, nos->l@ -);l+ oo al!ev
nt) {		kk	w}+ckk/* CreaiA H1temporiny l@ -etoacollec; chunksdou.r *_frhooev
nt =uectp_skb2ev
nt(nos);prhooskb_
 			bvega_cp_rt&temp);prhoo_/ikb_
 			bL,il(&temp,2rutp_ev
nt2skb(ev
nt))+ +	c} jeY22{}+ck /* Attaus*m,higauo Tnddikbs TouTo
dev
nt.r *_frhoo_/ikb_
 			bL,il(rutp_ev
nt2skb(ev
nt)->l@ -,2nos) =+	c}
+ate+=+ /*rSeap ev
nt TouTo
dULP.r *_frho aleve  )
+00ectp_ulpqbL,il_ev
nt/ulpq, ev
nt);p+}u+&(/* Skip over an 
SN.v*_frvfousectp_ulpq_skip(ipe _nPectp_ulpq *ulpq, __u16 eid,i__u16 estg
+slowipe _nPrutp_nppeam *in;lo=+ /*rNoie: To
dippeam ID mu - beiveracied befda  trisnroutine.v *_fowon  =a&ulpq
+asoc->sstmap->it+ +=+ /* Ia Tois_an old SSN?  I:6lo 
 	or_. *_frho alSSN_lt(est,mectp_sst_peek(in,isid)  }+ckro*retts+=+ /* Mark To_.2wef_re no  tnger expec;i + tris_SSN(datlowwr. *_f+	ectp_sst_skip(in,isid, sst) =+=+ /* Go fiap any ouo T chunksdTo_.2were2waifi + forp+k * o+aeri + and/veOivwr tremdo aneeded. =+  *_frhiutp_ulpq_
eap_o+aer{dtulpqgtp+kro*retts+it+& /* Renege 'needed' bytes from *o
do+aeri + 
 			. *_f trt_REJ_/u16 ectp_ulpq_
enege_o+aer(ipe _nPectp_ulpq *ulpq, __u16 needed)
 slcp.l694,7 +759r7 cp.ipt_REJ_/u16 ectp_ulpq_
enege_o+aer(ipe 
 hwhile ((skb = _/ikb_de
 			bL,il(&ulpq
+lobby)) 2sl c	
+	{d += ikb_vegalen(sL, ;l hoev
nt =uectp_skb2ev
nt(sL, ho-	btsnN= ev
nt
+nndrcvinfo.ninfo_tsn+ +cotst =aev
nt
+tst+  
  	ectp_ulpev
nt_
+	{lev
nt);p chectp_tstmap_
enege(tstmap, tst) =cp.l720r7 +785r7 cp.ipt_REJ_/u16 ectp_ulpq_
enege_frags(ipe 
 hwhile ((skb = _/ikb_de
 			bL,il(&ulpq
+reasmg) 2sl c	
+	{d += ikb_vegalen(sL, ;l hoev
nt =uectp_skb2ev
nt(sL, ho-	btsnN= ev
nt
+nndrcvinfo.ninfo_tsn+ +cotst =aev
nt
+tst+  
  	ectp_ulpev
nt_
+	{lev
nt);p chectp_tstmap_
enege(tstmap, tst) =